Loading CHANGELOG.md +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr - Storage write batches now correctly abort when any query in the batch fails. - Rank cache correctly calculates record expiry times. - Return correct response to group join operations when the user is already a member of the group. - Fix query when selecting a page of leaderboard records around a user. ## [2.4.2] - 2019-03-25 ### Added Loading server/core_leaderboard.go +1 −1 Original line number Diff line number Diff line Loading @@ -536,7 +536,7 @@ func getLeaderboardRecordsHaystack(ctx context.Context, logger *zap.Logger, db * query := `SELECT leaderboard_id, owner_id, username, score, subscore, num_score, max_num_score, metadata, create_time, update_time, expiry_time FROM leaderboard_record AND leaderboard_id = $1 WHERE leaderboard_id = $1 AND expiry_time = $2` // First half. Loading tests/core_wallet_test.go 0 → 100644 +463 −0 Original line number Diff line number Diff line package tests import ( "context" "encoding/json" "github.com/gofrs/uuid" "github.com/heroiclabs/nakama/runtime" "github.com/heroiclabs/nakama/server" "github.com/stretchr/testify/assert" "testing" ) func TestUpdateWalletSingleUser(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } for _, val := range values { err := nk.WalletUpdate(context.Background(), userID, map[string]interface{}{"value": val}, nil, true) if err != nil { t.Fatalf("error updating wallet: %v", err.Error()) } } account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } func TestUpdateWalletMultiUser(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } for _, val := range values { for _, userID := range userIDs { err := nk.WalletUpdate(context.Background(), userID, map[string]interface{}{"value": val}, nil, true) if err != nil { t.Fatalf("error updating wallet: %v", err.Error()) } } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } } func TestUpdateWalletsMultiUser(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } for _, val := range values { updates := make([]*runtime.WalletUpdate, 0, len(userIDs)) for _, userID := range userIDs { updates = append(updates, &runtime.WalletUpdate{ UserID: userID, Changeset: map[string]interface{}{"value": val}, }) } err := nk.WalletsUpdate(context.Background(), updates, true) if err != nil { t.Fatalf("error updating wallets: %v", err.Error()) } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } } func TestUpdateWalletsMultiUserSharedChangeset(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } for _, val := range values { changeset := map[string]interface{}{"value": val} updates := make([]*runtime.WalletUpdate, 0, len(userIDs)) for _, userID := range userIDs { updates = append(updates, &runtime.WalletUpdate{ UserID: userID, Changeset: changeset, }) } err := nk.WalletsUpdate(context.Background(), updates, true) if err != nil { t.Fatalf("error updating wallets: %v", err.Error()) } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } } func TestUpdateWalletsMultiUserSharedChangesetDeductions(t *testing.T) { values := []float64{ 34.01, -34.01, 7.41, -7.41, 70.86, -70.86, 35.11, -35.11, 2.68, 5.55, 32.05, -40.28, 48.07, -48.07, 12.07, -12.07, 6.62, 6.86, -13.48, 3.94, 2.05, 3.87, 2.38, 17.42, -29.66, 20.79, -20.79, 1.58, 2.5, 3.7, 14.88, 17.51, -40.17, 10.91, 19.6, -30.51, 9.98, 7.86, 33.11, -50.95, 13.58, -13.58, 306.74, -306.74, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } foo := float64(1) for _, val := range values { changeset := map[string]interface{}{"value": val, "foo": foo} updates := make([]*runtime.WalletUpdate, 0, len(userIDs)) for _, userID := range userIDs { updates = append(updates, &runtime.WalletUpdate{ UserID: userID, Changeset: changeset, }) } err := nk.WalletsUpdate(context.Background(), updates, true) if err != nil { t.Fatalf("error updating wallets: %v", err.Error()) } if foo == 1 { foo = -1 } else { foo = 1 } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(0), wallet["value"].(float64), "wallet value did not match") } } Loading
CHANGELOG.md +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr - Storage write batches now correctly abort when any query in the batch fails. - Rank cache correctly calculates record expiry times. - Return correct response to group join operations when the user is already a member of the group. - Fix query when selecting a page of leaderboard records around a user. ## [2.4.2] - 2019-03-25 ### Added Loading
server/core_leaderboard.go +1 −1 Original line number Diff line number Diff line Loading @@ -536,7 +536,7 @@ func getLeaderboardRecordsHaystack(ctx context.Context, logger *zap.Logger, db * query := `SELECT leaderboard_id, owner_id, username, score, subscore, num_score, max_num_score, metadata, create_time, update_time, expiry_time FROM leaderboard_record AND leaderboard_id = $1 WHERE leaderboard_id = $1 AND expiry_time = $2` // First half. Loading
tests/core_wallet_test.go 0 → 100644 +463 −0 Original line number Diff line number Diff line package tests import ( "context" "encoding/json" "github.com/gofrs/uuid" "github.com/heroiclabs/nakama/runtime" "github.com/heroiclabs/nakama/server" "github.com/stretchr/testify/assert" "testing" ) func TestUpdateWalletSingleUser(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } for _, val := range values { err := nk.WalletUpdate(context.Background(), userID, map[string]interface{}{"value": val}, nil, true) if err != nil { t.Fatalf("error updating wallet: %v", err.Error()) } } account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } func TestUpdateWalletMultiUser(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } for _, val := range values { for _, userID := range userIDs { err := nk.WalletUpdate(context.Background(), userID, map[string]interface{}{"value": val}, nil, true) if err != nil { t.Fatalf("error updating wallet: %v", err.Error()) } } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } } func TestUpdateWalletsMultiUser(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } for _, val := range values { updates := make([]*runtime.WalletUpdate, 0, len(userIDs)) for _, userID := range userIDs { updates = append(updates, &runtime.WalletUpdate{ UserID: userID, Changeset: map[string]interface{}{"value": val}, }) } err := nk.WalletsUpdate(context.Background(), updates, true) if err != nil { t.Fatalf("error updating wallets: %v", err.Error()) } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } } func TestUpdateWalletsMultiUserSharedChangeset(t *testing.T) { values := []float64{ 34.01, 7.41, 70.86, 35.11, 2.68, 5.55, 32.05, 48.07, 12.07, 6.62, 6.86, 3.94, 2.05, 3.87, 2.38, 17.42, 20.79, 1.58, 2.5, 3.7, 14.88, 17.51, 10.91, 19.6, 9.98, 7.86, 33.11, 13.58, 306.74, 4.9, 5.11, 19.15, 10.28, 25.51, 3.69, 13.21, 4.93, 4.4, 135.13, 22.83, 2.17, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } for _, val := range values { changeset := map[string]interface{}{"value": val} updates := make([]*runtime.WalletUpdate, 0, len(userIDs)) for _, userID := range userIDs { updates = append(updates, &runtime.WalletUpdate{ UserID: userID, Changeset: changeset, }) } err := nk.WalletsUpdate(context.Background(), updates, true) if err != nil { t.Fatalf("error updating wallets: %v", err.Error()) } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(1005), wallet["value"].(float64), "wallet value did not match") } } func TestUpdateWalletsMultiUserSharedChangesetDeductions(t *testing.T) { values := []float64{ 34.01, -34.01, 7.41, -7.41, 70.86, -70.86, 35.11, -35.11, 2.68, 5.55, 32.05, -40.28, 48.07, -48.07, 12.07, -12.07, 6.62, 6.86, -13.48, 3.94, 2.05, 3.87, 2.38, 17.42, -29.66, 20.79, -20.79, 1.58, 2.5, 3.7, 14.88, 17.51, -40.17, 10.91, 19.6, -30.51, 9.98, 7.86, 33.11, -50.95, 13.58, -13.58, 306.74, -306.74, } db := NewDB(t) nk := server.NewRuntimeGoNakamaModule(logger, db, config, nil, nil, nil, nil, nil, nil, nil, nil, nil) count := 5 userIDs := make([]string, 0, count) for i := 0; i < count; i++ { userID, _, _, err := server.AuthenticateCustom(context.Background(), logger, db, uuid.Must(uuid.NewV4()).String(), uuid.Must(uuid.NewV4()).String(), true) if err != nil { t.Fatalf("error creating user: %v", err.Error()) } userIDs = append(userIDs, userID) } foo := float64(1) for _, val := range values { changeset := map[string]interface{}{"value": val, "foo": foo} updates := make([]*runtime.WalletUpdate, 0, len(userIDs)) for _, userID := range userIDs { updates = append(updates, &runtime.WalletUpdate{ UserID: userID, Changeset: changeset, }) } err := nk.WalletsUpdate(context.Background(), updates, true) if err != nil { t.Fatalf("error updating wallets: %v", err.Error()) } if foo == 1 { foo = -1 } else { foo = 1 } } for _, userID := range userIDs { account, err := server.GetAccount(context.Background(), logger, db, nil, uuid.FromStringOrNil(userID)) if err != nil { t.Fatalf("error getting user: %v", err.Error()) } assert.NotNil(t, account, "account is nil") var wallet map[string]interface{} err = json.Unmarshal([]byte(account.Wallet), &wallet) if err != nil { t.Fatalf("json unmarshal error: %v", err.Error()) } assert.Contains(t, wallet, "value", "wallet did not contain value") assert.IsType(t, float64(0), wallet["value"], "wallet value was not float64") assert.Equal(t, float64(0), wallet["value"].(float64), "wallet value did not match") } }