diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000000..5bd23da5e1 --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,19 @@ +# every push to a branch: run tests +name: Run tests +on: + pull_request: + types: [opened, synchronize] +jobs: + run_tests: + name: Run Nakama tests + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Run tests + run: docker-compose -f ./docker-compose-tests.yml up --build --abort-on-container-exit + + - name: Cleanup + if: always() + run: docker-compose -f ./docker-compose-tests.yml down -v diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e3e6a0475..397673b85f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr - Tracker interface cleanup. - Converted StatusRegistry to an interface. +### Added +- Add an ability to easily run unit and integration tests in an isolated docker-compose environment. + ## [3.21.0] - 2024-03-17 ### Added - Add Fleet Manager API to power session-based multiplayer integrations. See [the documentation](https://heroiclabs.com/docs/nakama/concepts/multiplayer/session-based/) for more details. diff --git a/README.md b/README.md index c48fc9d92d..1b7126ffdc 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,17 @@ To build the codebase and generate all sources follow these steps. go build -trimpath -mod=vendor ``` +### Testing + +In order to run all the unit and integration tests run: + +```shell +docker-compose -f ./docker-compose-tests.yml up --build --abort-on-container-exit; docker-compose -f ./docker-compose-tests.yml down -v +``` + +This will create an isolated environment with Nakama and database instances, run +all the tests, and drop the environment afterwards. + ### License This project is licensed under the [Apache-2 License](https://github.com/heroiclabs/nakama/blob/master/LICENSE). diff --git a/docker-compose-tests.yml b/docker-compose-tests.yml new file mode 100644 index 0000000000..eca2cb8ce1 --- /dev/null +++ b/docker-compose-tests.yml @@ -0,0 +1,67 @@ +version: "3.9" +services: + db: + container_name: db + image: postgres:15 + command: -c 'max_connections=1000' + environment: + - POSTGRES_DB=nakama + - POSTGRES_PASSWORD=localdb + expose: + - "5432" + healthcheck: + test: ["CMD", "pg_isready", "-U", "postgres", "-d", "nakama"] + start_period: 10s + interval: 10s + timeout: 10s + retries: 10 + + nakama: + build: + context: . + dockerfile: ./build/Dockerfile.local + image: nakama-tests + entrypoint: + - "/bin/sh" + - "-ecx" + - > + /nakama/nakama migrate up --database.address postgres:localdb@db:5432/nakama && + exec /nakama/nakama --logger.level DEBUG --name nakama --database.address postgres:localdb@db:5432/nakama --session.token_expiry_sec 7200 --socket.port 7350 --console.port 7351 + restart: always + links: + - "db:db" + depends_on: + db: + condition: service_healthy + healthcheck: + test: ["CMD", "/nakama/nakama", "healthcheck"] + timeout: 10s + retries: 10 + start_period: 5s + interval: 5s + + test: + image: "golang:1.21" + command: /bin/sh -c "mkdir -p /nakama/internal/gopher-lua/_lua5.1-tests/libs/P1; go test -v -race ./..." + + working_dir: "/nakama" + environment: + - "GODEBUG=netdns=cgo" + - TEST_DB_URL=postgresql://postgres:localdb@db:5432/nakama?sslmode=disable + volumes: + - "./:/nakama" + - "lua:/nakama/internal/gopher-lua/_lua5.1-tests/libs" + links: + - "db:db" + depends_on: + db: + condition: service_healthy + nakama: + condition: service_healthy + +volumes: + lua: + +networks: + default: + driver: bridge diff --git a/internal/gopher-lua/script_test.go b/internal/gopher-lua/script_test.go index 6ecf105e7e..6bf9525090 100644 --- a/internal/gopher-lua/script_test.go +++ b/internal/gopher-lua/script_test.go @@ -68,6 +68,7 @@ func testScriptDir(t *testing.T, tests []string, directory string) { t.Error(err) } defer os.Chdir("..") + for _, script := range tests { fmt.Printf("testing %s/%s\n", directory, script) testScriptCompile(t, script) @@ -106,7 +107,7 @@ func sleep(L *LState) int { } func countFinalizers(L *LState) int { - L.Push(LNumber(numActiveUserDatas)) + L.Push(LNumber(atomic.LoadInt32(&numActiveUserDatas))) return 1 } diff --git a/main.go b/main.go index 6380386000..c5a48ec3d9 100644 --- a/main.go +++ b/main.go @@ -291,7 +291,7 @@ func newOrLoadCookie(config server.Config) string { cookie := uuid.FromBytesOrNil(b) if err != nil || cookie == uuid.Nil { cookie = uuid.Must(uuid.NewV4()) - _ = os.WriteFile(filePath, cookie.Bytes(), 0644) + _ = os.WriteFile(filePath, cookie.Bytes(), 0o644) } return cookie.String() } diff --git a/server/api_test.go b/server/api_test.go index 4e255a1b39..6624da00d2 100644 --- a/server/api_test.go +++ b/server/api_test.go @@ -171,8 +171,13 @@ func NewConsoleLogger(output *os.File, verbose bool) *zap.Logger { } func NewDB(t *testing.T) *sql.DB { - db, err := sql.Open("pgx", "postgresql://root@127.0.0.1:26257/nakama?sslmode=disable") - // db, err := sql.Open("pgx", "postgresql://postgres@127.0.0.1:5432/nakama?sslmode=disable") + // dbUrl := "postgresql://postgres@127.0.0.1:5432/nakama?sslmode=disable" + dbUrl := "postgresql://root@127.0.0.1:26257/nakama?sslmode=disable" + if dbUrlEnv := os.Getenv("TEST_DB_URL"); len(dbUrlEnv) > 0 { + dbUrl = dbUrlEnv + } + + db, err := sql.Open("pgx", dbUrl) if err != nil { t.Fatal("Error connecting to database", err) } @@ -218,10 +223,11 @@ func WaitForSocket(expected error, cfg *config) { func NewAPIServer(t *testing.T, runtime *Runtime) (*ApiServer, *Pipeline) { db := NewDB(t) router := &DummyMessageRouter{} - tracker := &LocalTracker{} sessionCache := NewLocalSessionCache(3_600, 7_200) - pipeline := NewPipeline(logger, cfg, db, protojsonMarshaler, protojsonUnmarshaler, nil, nil, nil, nil, nil, tracker, router, runtime) - apiServer := StartApiServer(logger, logger, db, protojsonMarshaler, protojsonUnmarshaler, cfg, "3.0.0", nil, storageIdx, nil, nil, nil, sessionCache, nil, nil, nil, tracker, router, nil, metrics, pipeline, runtime) + sessionRegistry := NewLocalSessionRegistry(metrics) + tracker := &LocalTracker{sessionRegistry: sessionRegistry} + pipeline := NewPipeline(logger, cfg, db, protojsonMarshaler, protojsonUnmarshaler, sessionRegistry, nil, nil, nil, nil, tracker, router, runtime) + apiServer := StartApiServer(logger, logger, db, protojsonMarshaler, protojsonUnmarshaler, cfg, "3.0.0", nil, storageIdx, nil, nil, sessionRegistry, sessionCache, nil, nil, nil, tracker, router, nil, metrics, pipeline, runtime) WaitForSocket(nil, cfg) return apiServer, pipeline diff --git a/server/match_common_test.go b/server/match_common_test.go index 3e9b561f21..59303c1ded 100644 --- a/server/match_common_test.go +++ b/server/match_common_test.go @@ -57,8 +57,7 @@ func createTestMatchRegistry(t fatalable, logger *zap.Logger) (*LocalMatchRegist mp := NewMatchProvider() mp.RegisterCreateFn("go", - func(ctx context.Context, logger *zap.Logger, id uuid.UUID, node string, stopped *atomic.Bool, - name string) (RuntimeMatchCore, error) { + func(ctx context.Context, logger *zap.Logger, id uuid.UUID, node string, stopped *atomic.Bool, name string) (RuntimeMatchCore, error) { match, err := newTestMatch(context.Background(), NewRuntimeGoLogger(logger), nil, nil) if err != nil { return nil, err @@ -82,13 +81,11 @@ type testMatchState struct { // testMatch is a minimal implementation of runtime.Match for testing purposes type testMatch struct{} -func newTestMatch(ctx context.Context, logger runtime.Logger, db *sql.DB, - nk runtime.NakamaModule) (m runtime.Match, err error) { +func newTestMatch(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule) (m runtime.Match, err error) { return &testMatch{}, nil } -func (m *testMatch) MatchInit(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, - params map[string]interface{}) (interface{}, int, string) { +func (m *testMatch) MatchInit(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, params map[string]interface{}) (interface{}, int, string) { state := &testMatchState{ presences: make(map[string]runtime.Presence), } @@ -104,15 +101,12 @@ func (m *testMatch) MatchInit(ctx context.Context, logger runtime.Logger, db *sq return state, tickRate, label } -func (m *testMatch) MatchJoinAttempt(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, - dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presence runtime.Presence, - metadata map[string]string) (interface{}, bool, string) { +func (m *testMatch) MatchJoinAttempt(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presence runtime.Presence, metadata map[string]string) (interface{}, bool, string) { acceptUser := true return state, acceptUser, "" } -func (m *testMatch) MatchJoin(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, - dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} { +func (m *testMatch) MatchJoin(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} { mState, _ := state.(*testMatchState) for _, p := range presences { mState.presences[p.GetUserId()] = p @@ -120,8 +114,7 @@ func (m *testMatch) MatchJoin(ctx context.Context, logger runtime.Logger, db *sq return mState } -func (m *testMatch) MatchLeave(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, - dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} { +func (m *testMatch) MatchLeave(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} { mState, _ := state.(*testMatchState) for _, p := range presences { delete(mState.presences, p.GetUserId()) @@ -129,8 +122,7 @@ func (m *testMatch) MatchLeave(ctx context.Context, logger runtime.Logger, db *s return mState } -func (m *testMatch) MatchLoop(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, - dispatcher runtime.MatchDispatcher, tick int64, state interface{}, messages []runtime.MatchData) interface{} { +func (m *testMatch) MatchLoop(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, messages []runtime.MatchData) interface{} { mState, _ := state.(*testMatchState) for _, presence := range mState.presences { logger.Info("Presence %v named %v", presence.GetUserId(), presence.GetUsername()) @@ -145,8 +137,7 @@ func (m *testMatch) MatchLoop(ctx context.Context, logger runtime.Logger, db *sq return mState } -func (m *testMatch) MatchTerminate(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, - dispatcher runtime.MatchDispatcher, tick int64, state interface{}, graceSeconds int) interface{} { +func (m *testMatch) MatchTerminate(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, graceSeconds int) interface{} { message := "Server shutting down in " + strconv.Itoa(graceSeconds) + " seconds." reliable := true if err := dispatcher.BroadcastMessage(2, []byte(message), []runtime.Presence{}, nil, reliable); err != nil { @@ -155,8 +146,7 @@ func (m *testMatch) MatchTerminate(ctx context.Context, logger runtime.Logger, d return state } -func (m *testMatch) MatchSignal(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, - dispatcher runtime.MatchDispatcher, tick int64, state interface{}, data string) (interface{}, string) { +func (m *testMatch) MatchSignal(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, data string) (interface{}, string) { return state, "signal received: " + data } @@ -170,6 +160,7 @@ func (s *testMetrics) SnapshotRecvKbSec() float64 { return 0 } func (s *testMetrics) SnapshotSentKbSec() float64 { return 0 } func (s *testMetrics) Api(name string, elapsed time.Duration, recvBytes, sentBytes int64, isErr bool) { } + func (s *testMetrics) ApiRpc(id string, elapsed time.Duration, recvBytes, sentBytes int64, isErr bool) { } func (s *testMetrics) ApiBefore(name string, elapsed time.Duration, isErr bool) {} @@ -199,8 +190,7 @@ type testMessageRouter struct { sendToPresence func(presences []*PresenceID, envelope *rtapi.Envelope) } -func (s *testMessageRouter) SendToPresenceIDs(_ *zap.Logger, presences []*PresenceID, - envelope *rtapi.Envelope, _ bool) { +func (s *testMessageRouter) SendToPresenceIDs(_ *zap.Logger, presences []*PresenceID, envelope *rtapi.Envelope, _ bool) { if s.sendToPresence != nil { s.sendToPresence(presences, envelope) } @@ -219,12 +209,11 @@ func (s *testTracker) SetPartyLeaveListener(func(id uuid.UUID, leaves []*Presenc func (s *testTracker) Stop() {} // Track returns success true/false, and new presence true/false. -func (s *testTracker) Track(ctx context.Context, sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID, - meta PresenceMeta, allowIfFirstForSession bool) (bool, bool) { +func (s *testTracker) Track(ctx context.Context, sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID, meta PresenceMeta) (bool, bool) { return true, true } -func (s *testTracker) TrackMulti(ctx context.Context, sessionID uuid.UUID, ops []*TrackerOp, userID uuid.UUID, - allowIfFirstForSession bool) bool { + +func (s *testTracker) TrackMulti(ctx context.Context, sessionID uuid.UUID, ops []*TrackerOp, userID uuid.UUID) bool { return true } func (s *testTracker) Untrack(sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID) {} @@ -234,8 +223,7 @@ func (s *testTracker) UntrackAll(sessionID uuid.UUID, reason runtime.PresenceRea // Update returns success true/false - will only fail if the user has no presence and allowIfFirstForSession is false, // otherwise is an upsert. -func (s *testTracker) Update(ctx context.Context, sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID, - meta PresenceMeta, allowIfFirstForSession bool) bool { +func (s *testTracker) Update(ctx context.Context, sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID, meta PresenceMeta) bool { return true } @@ -275,14 +263,12 @@ func (s *testTracker) CountByStreamModeFilter(modes map[uint8]*uint8) map[*Prese } // Check if a single presence on the current node exists. -func (s *testTracker) GetLocalBySessionIDStreamUserID(sessionID uuid.UUID, stream PresenceStream, - userID uuid.UUID) *PresenceMeta { +func (s *testTracker) GetLocalBySessionIDStreamUserID(sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID) *PresenceMeta { return nil } // Check if a single presence on any node exists. -func (s *testTracker) GetBySessionIDStreamUserID(node string, sessionID uuid.UUID, stream PresenceStream, - userID uuid.UUID) *PresenceMeta { +func (s *testTracker) GetBySessionIDStreamUserID(node string, sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID) *PresenceMeta { return nil } @@ -320,8 +306,7 @@ func (s *testSessionRegistry) Add(session Session) {} func (s *testSessionRegistry) Remove(sessionID uuid.UUID) {} -func (s *testSessionRegistry) Disconnect(ctx context.Context, sessionID uuid.UUID, ban bool, - reason ...runtime.PresenceReason) error { +func (s *testSessionRegistry) Disconnect(ctx context.Context, sessionID uuid.UUID, ban bool, reason ...runtime.PresenceReason) error { return nil } diff --git a/server/matchmaker_test.go b/server/matchmaker_test.go index 47bb2af7ce..c58f56da27 100644 --- a/server/matchmaker_test.go +++ b/server/matchmaker_test.go @@ -43,7 +43,7 @@ func TestMatchmakerAddOnly(t *testing.T) { sessionID, _ := uuid.NewV4() ticket, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -71,7 +71,7 @@ func TestMatchmakerAddRemoveRepeated(t *testing.T) { sessionID, _ := uuid.NewV4() ticket, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -93,7 +93,7 @@ func TestMatchmakerAddRemoveRepeated(t *testing.T) { } ticket, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -115,7 +115,7 @@ func TestMatchmakerAddRemoveRepeated(t *testing.T) { } ticket, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -137,7 +137,7 @@ func TestMatchmakerAddRemoveRepeated(t *testing.T) { } ticket, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -388,7 +388,7 @@ func TestMatchmakerAddAndRemove(t *testing.T) { sessionID, _ := uuid.NewV4() ticket, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -427,7 +427,7 @@ func TestMatchmakerAddWithBasicMatch(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -446,7 +446,7 @@ func TestMatchmakerAddWithBasicMatch(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -557,7 +557,7 @@ func TestMatchmakerAddWithMatchOnStar(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -674,7 +674,7 @@ func TestMatchmakerAddWithMatchOnRange(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -772,7 +772,7 @@ func TestMatchmakerAddWithMatchOnRangeAndValue(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -797,7 +797,7 @@ func TestMatchmakerAddWithMatchOnRangeAndValue(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -898,7 +898,7 @@ func TestMatchmakerAddRemoveNotMatch(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -945,7 +945,7 @@ func TestMatchmakerAddButNotMatch(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -968,7 +968,7 @@ func TestMatchmakerAddButNotMatch(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1017,7 +1017,7 @@ func TestMatchmakerAddButNotMatchOnRange(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -1042,7 +1042,7 @@ func TestMatchmakerAddButNotMatchOnRange(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1093,7 +1093,7 @@ func TestMatchmakerAddButNotMatchOnRangeAndValue(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -1119,7 +1119,7 @@ func TestMatchmakerAddButNotMatchOnRangeAndValue(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1168,7 +1168,7 @@ func TestMatchmakerAddMultipleAndSomeMatch(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -1192,7 +1192,7 @@ func TestMatchmakerAddMultipleAndSomeMatch(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1216,7 +1216,7 @@ func TestMatchmakerAddMultipleAndSomeMatch(t *testing.T) { sessionID3, _ := uuid.NewV4() ticket3, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "c", SessionId: "c", Username: "c", @@ -1270,7 +1270,7 @@ func TestMatchmakerAddMultipleAndSomeMatchWithBoost(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -1296,7 +1296,7 @@ func TestMatchmakerAddMultipleAndSomeMatchWithBoost(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1322,7 +1322,7 @@ func TestMatchmakerAddMultipleAndSomeMatchWithBoost(t *testing.T) { sessionID3, _ := uuid.NewV4() ticket3, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "c", SessionId: "c", Username: "c", @@ -1388,7 +1388,7 @@ func TestMatchmakerAddMultipleAndSomeMatchOptionalTextAlteringScore(t *testing.T sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -1412,7 +1412,7 @@ func TestMatchmakerAddMultipleAndSomeMatchOptionalTextAlteringScore(t *testing.T sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1436,7 +1436,7 @@ func TestMatchmakerAddMultipleAndSomeMatchOptionalTextAlteringScore(t *testing.T sessionID3, _ := uuid.NewV4() ticket3, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "c", SessionId: "c", Username: "c", @@ -1488,7 +1488,7 @@ func TestMatchmakerAddAndMatchAuthoritative(t *testing.T) { sessionID, _ := uuid.NewV4() ticket1, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "a", SessionId: "a", Username: "a", @@ -1511,7 +1511,7 @@ func TestMatchmakerAddAndMatchAuthoritative(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1655,7 +1655,7 @@ func createTestMatchmaker(t fatalable, logger *zap.Logger, tickerActive bool, me t.Fatalf("error creating test match registry: %v", err) } - runtime, _, err := NewRuntime(context.Background(), logger, logger, nil, jsonpbMarshaler, jsonpbUnmarshaler, cfg, "", nil, nil, nil, nil, sessionRegistry, nil, nil, nil, tracker, metrics, nil, messageRouter, storageIdx) + runtime, _, err := NewRuntime(context.Background(), logger, logger, nil, jsonpbMarshaler, jsonpbUnmarshaler, cfg, "", nil, nil, nil, nil, sessionRegistry, nil, nil, nil, tracker, metrics, nil, messageRouter, storageIdx, nil) if err != nil { t.Fatal(err) } @@ -1778,7 +1778,7 @@ func TestMatchmakerRequireMutualMatch(t *testing.T) { sessionID2, _ := uuid.NewV4() ticket2, _, err := matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1862,7 +1862,7 @@ func TestMatchmakerRequireMutualMatchLarger(t *testing.T) { sessionID2, _ := uuid.NewV4() _, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1884,7 +1884,7 @@ func TestMatchmakerRequireMutualMatchLarger(t *testing.T) { sessionID3, _ := uuid.NewV4() _, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "c", SessionId: "c", Username: "c", @@ -1964,7 +1964,7 @@ func TestMatchmakerRequireMutualMatchLargerReversed(t *testing.T) { sessionID2, _ := uuid.NewV4() _, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "b", SessionId: "b", Username: "b", @@ -1986,7 +1986,7 @@ func TestMatchmakerRequireMutualMatchLargerReversed(t *testing.T) { sessionID3, _ := uuid.NewV4() _, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: "c", SessionId: "c", Username: "c", @@ -2127,7 +2127,8 @@ func BenchmarkMatchmakerProcessMediumSomeNonMutualBiggerGroupAndDifficultMatch(b } func benchmarkMatchmakerHelper(b *testing.B, activeCount, minCount, maxCount, countMultiple int, - withQueryAndProps func(i int) (string, map[string]string)) { + withQueryAndProps func(i int) (string, map[string]string), +) { consoleLogger := loggerForBenchmark(b) matchMaker, cleanup, err := createTestMatchmaker(b, consoleLogger, true, nil) if err != nil { @@ -2168,16 +2169,20 @@ func benchmarkMatchmakerHelper(b *testing.B, activeCount, minCount, maxCount, co } } -var benchmarkMatchQueryAny = "+properties.a6:bar" -var benchmarkMatchQuerySome = benchmarkMatchQueryAny + " +properties.a7:foo" -var benchmarkMatchQueryFew = benchmarkMatchQuerySome + " +properties.a8:baz" -var benchmarkPropsAny = map[string]string{ - "a6": "bar", -} +var ( + benchmarkMatchQueryAny = "+properties.a6:bar" + benchmarkMatchQuerySome = benchmarkMatchQueryAny + " +properties.a7:foo" + benchmarkMatchQueryFew = benchmarkMatchQuerySome + " +properties.a8:baz" + benchmarkPropsAny = map[string]string{ + "a6": "bar", + } +) + var benchmarkPropsSome = map[string]string{ "a6": "bar", "a7": "foo", } + var benchmarkPropsFew = map[string]string{ "a6": "bar", "a7": "foo", @@ -2200,7 +2205,7 @@ func TestMatchmakerMaxPartyTracking(t *testing.T) { createTicketFunc := func(party string) error { sessionID, _ := uuid.NewV4() _, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: sessionID.String(), SessionId: sessionID.String(), Username: sessionID.String(), @@ -2280,7 +2285,7 @@ func TestMatchmakerMaxSessionTracking(t *testing.T) { createTicketFunc := func(sessionID uuid.UUID) error { _, _, err = matchMaker.Add(context.Background(), []*MatchmakerPresence{ - &MatchmakerPresence{ + { UserId: sessionID.String(), SessionId: sessionID.String(), Username: sessionID.String(), @@ -2437,6 +2442,7 @@ func benchmarkMatchmakerProcessTickets(ticketsMax int32, unmatchable int, minCou func BenchmarkMatchmakerProcessTickets100_min2_max2(b *testing.B) { benchmarkMatchmakerProcessTickets(100, 50, 2, 2, b) } + func BenchmarkMatchmakerProcessTickets500_min2_max2(b *testing.B) { benchmarkMatchmakerProcessTickets(500, 250, 2, 2, b) } @@ -2456,9 +2462,11 @@ func BenchmarkMatchmakerProcessTickets1_000_min2_max2(b *testing.B) { func BenchmarkMatchmakerProcessTickets100_min4_max10(b *testing.B) { benchmarkMatchmakerProcessTickets(100, 10, 4, 10, b) } + func BenchmarkMatchmakerProcessTickets500_min4_max10(b *testing.B) { benchmarkMatchmakerProcessTickets(500, 50, 4, 10, b) } + func BenchmarkMatchmakerProcessTickets1_000_min4_max10(b *testing.B) { benchmarkMatchmakerProcessTickets(1_000, 100, 4, 10, b) } diff --git a/server/runtime_test.go b/server/runtime_test.go index 9158e4d46d..e0a3ba79ff 100644 --- a/server/runtime_test.go +++ b/server/runtime_test.go @@ -80,7 +80,7 @@ func runtimeWithModulesWithData(t *testing.T, modules map[string]string) (*Runti defer os.RemoveAll(dir) for moduleName, moduleData := range modules { - if err := os.WriteFile(filepath.Join(dir, fmt.Sprintf("%v.lua", moduleName)), []byte(moduleData), 0644); err != nil { + if err := os.WriteFile(filepath.Join(dir, fmt.Sprintf("%v.lua", moduleName)), []byte(moduleData), 0o644); err != nil { t.Fatalf("Failed initializing runtime modules tempfile: %s", err.Error()) } } @@ -100,9 +100,11 @@ func runtimeWithModulesWithData(t *testing.T, modules map[string]string) (*Runti leaderboardRankCache: lbRankCache, } - tracker := &LocalTracker{} + sessionRegistry := NewLocalSessionRegistry(metrics) + tracker := &LocalTracker{sessionRegistry: sessionRegistry} + statusRegistry := NewLocalStatusRegistry(logger, cfg, sessionRegistry, protojsonMarshaler) - rt, rtInfo, err := NewRuntime(ctx, logger, logger, db, protojsonMarshaler, protojsonUnmarshaler, cfg, "", nil, lbCache, lbRankCache, lbSched, nil, nil, nil, nil, tracker, metrics, nil, &DummyMessageRouter{}, storageIdx) + rt, rtInfo, err := NewRuntime(ctx, logger, logger, db, protojsonMarshaler, protojsonUnmarshaler, cfg, "", nil, lbCache, lbRankCache, lbSched, sessionRegistry, nil, statusRegistry, nil, tracker, metrics, nil, &DummyMessageRouter{}, storageIdx, nil) return rt, rtInfo, data, err } @@ -817,7 +819,6 @@ nakama.register_req_before(before_storage_write, "WriteStorageObjects")`, }`, }}, }) - if err != nil { t.Fatal(err) } @@ -894,7 +895,6 @@ nakama.register_req_after(after_storage_write, "WriteStorageObjects")`, }`, }}, }) - if err != nil { t.Fatal(err) }