package domain_test import ( "fmt" "math" "slices" "testing" "gitea.dwysokinski.me/twhelp/corev3/internal/domain" "gitea.dwysokinski.me/twhelp/corev3/internal/domain/domaintest" "github.com/brianvoe/gofakeit/v6" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestServers_Close(t *testing.T) { t.Parallel() open := domain.BaseServers{ domaintest.NewBaseServer(t), domaintest.NewBaseServer(t), domaintest.NewBaseServer(t), } servers := domain.Servers{ domaintest.NewServer(t, func(cfg *domaintest.ServerConfig) { cfg.Key = open[0].Key() }), domaintest.NewServer(t, func(cfg *domaintest.ServerConfig) { cfg.Key = open[2].Key() }), domaintest.NewServer(t), domaintest.NewServer(t, func(cfg *domaintest.ServerConfig) { cfg.Open = false }), } res, err := servers.Close(open) require.NoError(t, err) assert.NotEmpty(t, res) for _, s := range servers { expected := domaintest.NewBaseServer(t, func(cfg *domaintest.BaseServerConfig) { cfg.Key = s.Key() cfg.URL = s.URL() cfg.Open = false }) if !s.Open() || slices.ContainsFunc(open, func(server domain.BaseServer) bool { return server.Key() == s.Key() }) { assert.NotContains(t, res, expected) continue } assert.Contains(t, res, expected) } } func TestNewCreateServerParams(t *testing.T) { t.Parallel() validVersion := domaintest.NewVersion(t) validBaseServer := domaintest.NewBaseServer(t) type args struct { servers domain.BaseServers versionCode string } type test struct { name string args args expectedErr error } tests := []test{ { name: "OK", args: args{ versionCode: validVersion.Code(), servers: domain.BaseServers{ validBaseServer, }, }, }, } for _, versionCodeTest := range newVersionCodeValidationTests() { tests = append(tests, test{ name: versionCodeTest.name, args: args{ versionCode: versionCodeTest.code, servers: domain.BaseServers{ validBaseServer, }, }, expectedErr: domain.ValidationError{ Model: "CreateServerParams", Field: "versionCode", Err: versionCodeTest.expectedErr, }, }) } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() res, err := domain.NewCreateServerParams(tt.args.servers, tt.args.versionCode) require.ErrorIs(t, err, tt.expectedErr) if tt.expectedErr != nil { return } require.Len(t, res, len(tt.args.servers)) for i, b := range tt.args.servers { assert.Equal(t, b, res[i].Base()) assert.Equal(t, tt.args.versionCode, res[i].VersionCode()) } }) } } func TestUpdateServerParams_SetNumTribes(t *testing.T) { t.Parallel() type args struct { numTribes domain.NullInt } tests := []struct { name string args args expectedErr error }{ { name: "OK", args: args{ numTribes: domain.NullInt{ Value: gofakeit.IntRange(0, math.MaxInt), Valid: true, }, }, }, { name: "OK: null value", args: args{ numTribes: domain.NullInt{ Valid: false, }, }, }, { name: "ERR: numTribes < 0", args: args{ numTribes: domain.NullInt{ Value: -1, Valid: true, }, }, expectedErr: domain.ValidationError{ Model: "UpdateServerParams", Field: "numTribes", Err: domain.MinGreaterEqualError{ Min: 0, Current: -1, }, }, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() var params domain.UpdateServerParams require.ErrorIs(t, params.SetNumTribes(tt.args.numTribes), tt.expectedErr) if tt.expectedErr != nil { return } assert.Equal(t, tt.args.numTribes, params.NumTribes()) }) } } func TestNewServerCursor(t *testing.T) { t.Parallel() validServerCursor := domaintest.NewServerCursor(t) type args struct { key string open bool } type test struct { name string args args expectedErr error } tests := []test{ { name: "OK", args: args{ key: validServerCursor.Key(), open: validServerCursor.Open(), }, expectedErr: nil, }, } for _, serverKeyTest := range newServerKeyValidationTests() { tests = append(tests, test{ name: serverKeyTest.name, args: args{ key: serverKeyTest.key, }, expectedErr: domain.ValidationError{ Model: "ServerCursor", Field: "key", Err: serverKeyTest.expectedErr, }, }) } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() sc, err := domain.NewServerCursor(tt.args.key, tt.args.open) require.ErrorIs(t, err, tt.expectedErr) if tt.expectedErr != nil { return } assert.Equal(t, tt.args.key, sc.Key()) assert.Equal(t, tt.args.open, sc.Open()) assert.NotEmpty(t, sc.Encode()) }) } } func TestListServersParams_SetSort(t *testing.T) { t.Parallel() type args struct { sort []domain.ServerSort } tests := []struct { name string args args expectedErr error }{ { name: "OK", args: args{ sort: []domain.ServerSort{ domain.ServerSortKeyASC, }, }, }, { name: "ERR: len(sort) < 1", args: args{ sort: nil, }, expectedErr: domain.ValidationError{ Model: "ListServersParams", Field: "sort", Err: domain.LenOutOfRangeError{ Min: 1, Max: 2, Current: 0, }, }, }, { name: "ERR: len(sort) > 2", args: args{ sort: []domain.ServerSort{ domain.ServerSortKeyASC, domain.ServerSortKeyDESC, domain.ServerSortOpenASC, }, }, expectedErr: domain.ValidationError{ Model: "ListServersParams", Field: "sort", Err: domain.LenOutOfRangeError{ Min: 1, Max: 2, Current: 3, }, }, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() params := domain.NewListServersParams() require.ErrorIs(t, params.SetSort(tt.args.sort), tt.expectedErr) if tt.expectedErr != nil { return } assert.Equal(t, tt.args.sort, params.Sort()) }) } } func TestListServersParams_SetEncodedCursor(t *testing.T) { t.Parallel() validCursor := domaintest.NewServerCursor(t) type args struct { cursor string } tests := []struct { name string args args expectedCursor domain.ServerCursor expectedErr error }{ { name: "OK", args: args{ cursor: validCursor.Encode(), }, expectedCursor: validCursor, }, { name: "ERR: len(cursor) < 1", args: args{ cursor: "", }, expectedErr: domain.ValidationError{ Model: "ListServersParams", Field: "cursor", Err: domain.LenOutOfRangeError{ Min: 1, Max: 1000, Current: 0, }, }, }, { name: "ERR: len(cursor) > 1000", args: args{ cursor: gofakeit.LetterN(1001), }, expectedErr: domain.ValidationError{ Model: "ListServersParams", Field: "cursor", Err: domain.LenOutOfRangeError{ Min: 1, Max: 1000, Current: 1001, }, }, }, { name: "ERR: malformed base64", args: args{ cursor: "112345", }, expectedErr: domain.ValidationError{ Model: "ListServersParams", Field: "cursor", Err: domain.ErrInvalidCursor, }, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() params := domain.NewListServersParams() require.ErrorIs(t, params.SetEncodedCursor(tt.args.cursor), tt.expectedErr) if tt.expectedErr != nil { return } assert.Equal(t, tt.expectedCursor.Key(), params.Cursor().Key()) assert.Equal(t, tt.expectedCursor.Open(), params.Cursor().Open()) assert.Equal(t, tt.args.cursor, params.Cursor().Encode()) }) } } func TestListServersParams_SetLimit(t *testing.T) { t.Parallel() type args struct { limit int } tests := []struct { name string args args expectedErr error }{ { name: "OK", args: args{ limit: domain.ServerListMaxLimit, }, }, { name: "ERR: limit < 1", args: args{ limit: 0, }, expectedErr: domain.ValidationError{ Model: "ListServersParams", Field: "limit", Err: domain.MinGreaterEqualError{ Min: 1, Current: 0, }, }, }, { name: fmt.Sprintf("ERR: limit > %d", domain.ServerListMaxLimit), args: args{ limit: domain.ServerListMaxLimit + 1, }, expectedErr: domain.ValidationError{ Model: "ListServersParams", Field: "limit", Err: domain.MaxLessEqualError{ Max: domain.ServerListMaxLimit, Current: domain.ServerListMaxLimit + 1, }, }, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() params := domain.NewListServersParams() require.ErrorIs(t, params.SetLimit(tt.args.limit), tt.expectedErr) if tt.expectedErr != nil { return } assert.Equal(t, tt.args.limit, params.Limit()) }) } } func TestNewListServersResult(t *testing.T) { t.Parallel() servers := domain.Servers{ domaintest.NewServer(t), domaintest.NewServer(t), domaintest.NewServer(t), } next := domaintest.NewServer(t) t.Run("OK: with next", func(t *testing.T) { t.Parallel() res, err := domain.NewListServersResult(servers, next) require.NoError(t, err) assert.Equal(t, servers, res.Servers()) assert.Equal(t, servers[0].Key(), res.Self().Key()) assert.Equal(t, servers[0].Open(), res.Self().Open()) assert.Equal(t, next.Key(), res.Next().Key()) assert.Equal(t, next.Open(), res.Next().Open()) }) t.Run("OK: without next", func(t *testing.T) { t.Parallel() res, err := domain.NewListServersResult(servers, domain.Server{}) require.NoError(t, err) assert.Equal(t, servers, res.Servers()) assert.Equal(t, servers[0].Key(), res.Self().Key()) assert.Equal(t, servers[0].Open(), res.Self().Open()) assert.True(t, res.Next().IsZero()) }) t.Run("OK: 0 versions", func(t *testing.T) { t.Parallel() res, err := domain.NewListServersResult(nil, domain.Server{}) require.NoError(t, err) assert.Zero(t, res.Servers()) assert.True(t, res.Self().IsZero()) assert.True(t, res.Next().IsZero()) }) } type serverKeyValidationTest struct { name string key string expectedErr error } func newServerKeyValidationTests() []serverKeyValidationTest { return []serverKeyValidationTest{ { name: "ERR: server key length < 1", expectedErr: domain.LenOutOfRangeError{ Min: 1, Max: 10, }, }, { name: "ERR: server key length > 10", key: "keykeykeyke", expectedErr: domain.LenOutOfRangeError{ Min: 1, Max: 10, Current: len("keykeykeyke"), }, }, } }