@ -3,28 +3,41 @@ package main
import (
import (
"context"
"context"
"encoding/json"
"encoding/json"
"github.com/pagefaultgames/rogueserver/api/account"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"io"
"io"
"net"
"net"
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
"runtime"
"strings"
"strings"
"testing"
"testing"
"github.com/pagefaultgames/rogueserver/api/account"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/pagefaultgames/rogueserver/api"
"github.com/pagefaultgames/rogueserver/api"
"github.com/pagefaultgames/rogueserver/db"
"github.com/pagefaultgames/rogueserver/db"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/mariadb"
"github.com/testcontainers/testcontainers-go/modules/mariadb"
)
)
const (
dbImage = "mariadb:11"
dbName = "pokeroguedb"
dbUsername = "pokerogue"
dbPassword = "pokerogue"
)
func TestRogueServer ( t * testing . T ) {
func TestRogueServer ( t * testing . T ) {
if testing . Short ( ) {
if testing . Short ( ) {
t . Skip ( "skipping test in short mode" )
t . Skip ( "skipping test in short mode" )
}
}
if runtime . GOOS == "windows" {
t . Skip ( "testcontainers-go does not support windows" )
}
setupDB ( t )
setupDB ( t )
apiURL := runServer ( t )
apiURL := runServer ( t )
@ -35,43 +48,42 @@ func TestRogueServer(t *testing.T) {
t . Run ( "/account/register" , func ( t * testing . T ) {
t . Run ( "/account/register" , func ( t * testing . T ) {
t . Run ( "invalid username" , func ( t * testing . T ) {
t . Run ( "invalid username" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { "" } , "password" : { "password" } } )
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { "" } , "password" : { "password" } } )
resp . assertStringResponse ( t , http . Status InternalServerError , "invalid username\n" )
resp . assertStringResponse ( t , http . Status BadRequest , "invalid username\n" )
} )
} )
t . Run ( "invalid password" , func ( t * testing . T ) {
t . Run ( "invalid password" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { "username" } , "password" : { "1" } } )
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { "username" } , "password" : { "1" } } )
resp . assertStringResponse ( t , http . Status InternalServerError , "invalid password\n" )
resp . assertStringResponse ( t , http . Status BadRequest , "invalid password\n" )
} )
} )
t . Run ( "register" , func ( t * testing . T ) {
t . Run ( "register" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { username } , "password" : { oldPassword } } )
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { username } , "password" : { oldPassword } } )
resp . assertStringResponse ( t , http . Status OK , "" )
resp . assertStringResponse ( t , http . Status Created , "" )
} )
} )
t . Run ( "fail when register called for already registered user" , func ( t * testing . T ) {
t . Run ( "fail when register called for already registered user" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { username } , "password" : { oldPassword } } )
resp := postHttpForm ( t , apiURL , "/account/register" , nil , url . Values { "username" : { username } , "password" : { oldPassword } } )
resp . assertStringResponse ( t , http . Status InternalServerError, "failed to add account record: Error 1062 (23000): Duplicate entry 'user1234' for key 'username' \n")
resp . assertStringResponse ( t , http . Status Conflict, "username \"user1234\" already taken \n")
} )
} )
} )
} )
var token string
var token string
t . Run ( "/account/login" , func ( t * testing . T ) {
t . Run ( "/account/login" , func ( t * testing . T ) {
t . Run ( "invalid username" , func ( t * testing . T ) {
t . Run ( "invalid username" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { "" } , "password" : { "password" } } )
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { "" } , "password" : { "password" } } )
resp . assertStringResponse ( t , http . Status InternalServerError , "invalid username\n" )
resp . assertStringResponse ( t , http . Status BadRequest , "invalid username\n" )
} )
} )
t . Run ( "invalid password" , func ( t * testing . T ) {
t . Run ( "invalid password" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { "username" } , "password" : { "1" } } )
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { "username" } , "password" : { "1" } } )
resp . assertStringResponse ( t , http . Status InternalServerError , "invalid password\n" )
resp . assertStringResponse ( t , http . Status BadRequest , "invalid password\n" )
} )
} )
t . Run ( "user do not exist" , func ( t * testing . T ) {
t . Run ( "user do not exist" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { "notexist" } , "password" : { "123456" } } )
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { "notexist" } , "password" : { "123456" } } )
resp . assertStringResponse ( t , http . Status InternalServerError , "account doesn't exist\n" )
resp . assertStringResponse ( t , http . Status NotFound , "account doesn't exist\n" )
} )
} )
t . Run ( "bad password" , func ( t * testing . T ) {
t . Run ( "bad password" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { username } , "password" : { "badpassword" } } )
resp := postHttpForm ( t , apiURL , "/account/login" , nil , url . Values { "username" : { username } , "password" : { "badpassword" } } )
resp . assertStringResponse ( t , http . Status InternalServerError , "password doesn't match\n" )
resp . assertStringResponse ( t , http . Status Unauthorized , "password doesn't match\n" )
} )
} )
t . Run ( "login successfully" , func ( t * testing . T ) {
t . Run ( "login successfully" , func ( t * testing . T ) {
@ -92,7 +104,7 @@ func TestRogueServer(t *testing.T) {
t . Run ( "bad token" , func ( t * testing . T ) {
t . Run ( "bad token" , func ( t * testing . T ) {
resp := getHTTP ( t , apiURL , "/account/info" , authHeader ( "foo" ) )
resp := getHTTP ( t , apiURL , "/account/info" , authHeader ( "foo" ) )
resp . assertStringResponse ( t , http . StatusBadRequest , "failed to decode token : illegal base64 data at input byte 0 \n")
resp . assertStringResponse ( t , http . StatusBadRequest , "failed to decode token \n")
} )
} )
t . Run ( "success" , func ( t * testing . T ) {
t . Run ( "success" , func ( t * testing . T ) {
@ -109,16 +121,16 @@ func TestRogueServer(t *testing.T) {
t . Run ( "bad token" , func ( t * testing . T ) {
t . Run ( "bad token" , func ( t * testing . T ) {
resp := getHTTP ( t , apiURL , "/account/logout" , authHeader ( "foo" ) )
resp := getHTTP ( t , apiURL , "/account/logout" , authHeader ( "foo" ) )
resp . assertStringResponse ( t , http . StatusBadRequest , "failed to decode token : illegal base64 data at input byte 0 \n")
resp . assertStringResponse ( t , http . StatusBadRequest , "failed to decode token \n")
} )
} )
t . Run ( "success" , func ( t * testing . T ) {
t . Run ( "success" , func ( t * testing . T ) {
resp := getHTTP ( t , apiURL , "/account/logout" , authHeader ( token ) )
resp := getHTTP ( t , apiURL , "/account/logout" , authHeader ( token ) )
resp . assertStatusCode ( t , http . Status OK )
resp . assertStatusCode ( t , http . Status NoContent )
} )
} )
t . Run ( "do nothing on second logout" , func ( t * testing . T ) {
t . Run ( "do nothing on second logout" , func ( t * testing . T ) {
resp := getHTTP ( t , apiURL , "/account/logout" , authHeader ( token ) )
resp := getHTTP ( t , apiURL , "/account/logout" , authHeader ( token ) )
resp . assertStatusCode ( t , http . Status OK )
resp . assertStatusCode ( t , http . Status NoContent )
} )
} )
} )
} )
@ -130,12 +142,12 @@ func TestRogueServer(t *testing.T) {
t . Run ( "bad token" , func ( t * testing . T ) {
t . Run ( "bad token" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( "foo" ) , url . Values { "password" : { newPassword } } )
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( "foo" ) , url . Values { "password" : { newPassword } } )
resp . assertStringResponse ( t , http . StatusBadRequest , "failed to decode token : illegal base64 data at input byte 0 \n")
resp . assertStringResponse ( t , http . StatusBadRequest , "failed to decode token \n")
} )
} )
t . Run ( "fail on unlogged token" , func ( t * testing . T ) {
t . Run ( "fail on unlogged token" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( token ) , url . Values { "password" : { newPassword } } )
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( token ) , url . Values { "password" : { newPassword } } )
resp . assertStringResponse ( t , http . Status BadRequest, "failed to validate token: sql: no rows in result set \n")
resp . assertStringResponse ( t , http . Status Unauthorized, "bad token \n")
} )
} )
t . Run ( "login successfully once again" , func ( t * testing . T ) {
t . Run ( "login successfully once again" , func ( t * testing . T ) {
@ -149,12 +161,12 @@ func TestRogueServer(t *testing.T) {
t . Run ( "bad password" , func ( t * testing . T ) {
t . Run ( "bad password" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( token ) , url . Values { "password" : { "123" } } )
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( token ) , url . Values { "password" : { "123" } } )
resp . assertStringResponse ( t , http . Status InternalServerError , "invalid password\n" )
resp . assertStringResponse ( t , http . Status BadRequest , "invalid password\n" )
} )
} )
t . Run ( "success" , func ( t * testing . T ) {
t . Run ( "success" , func ( t * testing . T ) {
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( token ) , url . Values { "password" : { newPassword } } )
resp := postHttpForm ( t , apiURL , "/account/changepw" , authHeader ( token ) , url . Values { "password" : { newPassword } } )
resp . assertStatusCode ( t , http . Status OK )
resp . assertStatusCode ( t , http . Status NoContent )
} )
} )
} )
} )
} )
} )
@ -259,15 +271,11 @@ func setupDB(t *testing.T) {
t . Helper ( )
t . Helper ( )
ctx := context . Background ( )
ctx := context . Background ( )
const dbName = "pokeroguedb"
const username = "pokerogue"
const password = "pokerogue"
c , err := mariadb . RunContainer ( ctx ,
c , err := mariadb . RunContainer ( ctx ,
testcontainers . WithImage ( "mariadb:11" ) ,
testcontainers . WithImage ( dbImage ) ,
mariadb . WithDatabase ( dbName ) ,
mariadb . WithDatabase ( dbName ) ,
mariadb . WithUsername ( u sername) ,
mariadb . WithUsername ( dbUsername ) ,
mariadb . WithPassword ( p assword) ,
mariadb . WithPassword ( dbP assword) ,
)
)
require . NoError ( t , err )
require . NoError ( t , err )
@ -280,6 +288,8 @@ func setupDB(t *testing.T) {
host , err := c . Host ( ctx )
host , err := c . Host ( ctx )
require . NoError ( t , err )
require . NoError ( t , err )
err = db . Init ( username, p assword, "tcp" , net . JoinHostPort ( host , port . Port ( ) ) , dbName )
err = db . Init ( dbUsername, dbP assword, "tcp" , net . JoinHostPort ( host , port . Port ( ) ) , dbName )
require . NoError ( t , err )
require . NoError ( t , err )
t . Logf ( "connection string to db for debugging (valid until tests are running): %s" , c . MustConnectionString ( ctx ) )
}
}