Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Counters and Lists REST API Conformance Tests #3546

Merged
merged 5 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/includes/sdk.mk
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ run-sdk-conformance-test-rest:
# run without feature flags
$(MAKE) run-sdk-conformance-test SDK_FOLDER=restapi GRPC_PORT=9050 HTTP_PORT=9150
# run with feature flags enabled
$(MAKE) run-sdk-conformance-test SDK_FOLDER=restapi GRPC_PORT=9050 HTTP_PORT=9150 FEATURE_GATES=PlayerTracking=true TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS)
$(MAKE) run-sdk-conformance-test SDK_FOLDER=restapi GRPC_PORT=9050 HTTP_PORT=9150 FEATURE_GATES=$(ALPHA_FEATURE_GATES) TESTS=$(DEFAULT_CONFORMANCE_TESTS),$(ALPHA_CONFORMANCE_TESTS),$(COUNTS_AND_LISTS_TESTS)

$(MAKE) run-sdk-command COMMAND=clean SDK_FOLDER=restapi

Expand Down
11 changes: 6 additions & 5 deletions pkg/sdkserver/localsdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -652,18 +652,19 @@ func (l *LocalSDKServer) UpdateCounter(ctx context.Context, in *alpha.UpdateCoun
// Set Capacity
if in.CounterUpdateRequest.Capacity != nil {
l.recordRequest("setcapacitycounter")
if in.CounterUpdateRequest.Capacity.GetValue() < 0 {
tmpCounter.Capacity = in.CounterUpdateRequest.Capacity.GetValue()
if tmpCounter.Capacity < 0 {
return nil, errors.Errorf("out of range. Capacity must be greater than or equal to 0. Found Capacity: %d",
in.CounterUpdateRequest.Capacity.GetValue())
tmpCounter.Capacity)
}
tmpCounter.Capacity = in.CounterUpdateRequest.Capacity.GetValue()
}
// Set Count
if in.CounterUpdateRequest.Count != nil {
l.recordRequest("setcountcounter")
if in.CounterUpdateRequest.Count.GetValue() < 0 || in.CounterUpdateRequest.Count.GetValue() > tmpCounter.Capacity {
tmpCounter.Count = in.CounterUpdateRequest.Count.GetValue()
if tmpCounter.Count < 0 || tmpCounter.Count > tmpCounter.Capacity {
return nil, errors.Errorf("out of range. Count must be within range [0,Capacity]. Found Count: %d, Capacity: %d",
in.CounterUpdateRequest.Count.GetValue(), tmpCounter.Capacity)
tmpCounter.Count, tmpCounter.Capacity)
}
}
// Increment or Decrement Count
Expand Down
6 changes: 3 additions & 3 deletions pkg/sdkserver/localsdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ func TestLocalSDKServerUpdateCounter(t *testing.T) {
"players": {Count: 100, Capacity: 100},
"lobbies": {Count: 0, Capacity: 0},
"games": {Count: 5, Capacity: 10},
"npcs": {Count: 0, Capacity: 10},
"npcs": {Count: 6, Capacity: 10},
}
fixture := &agonesv1.GameServer{
ObjectMeta: metav1.ObjectMeta{Name: "stuff"},
Expand Down Expand Up @@ -746,8 +746,8 @@ func TestLocalSDKServerUpdateCounter(t *testing.T) {
"Set Counter Count": {
updateRequest: &alpha.UpdateCounterRequest{
CounterUpdateRequest: &alpha.CounterUpdateRequest{
Name: "npcs",
CountDiff: 10,
Name: "npcs",
Count: wrapperspb.Int64(10),
}},
want: &alpha.Counter{
Name: "npcs", Count: 10, Capacity: 10,
Expand Down
53 changes: 30 additions & 23 deletions pkg/sdkserver/sdkserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,9 @@ func (s *SDKServer) UpdateCounter(ctx context.Context, in *alpha.UpdateCounterRe
if in.CounterUpdateRequest == nil {
return nil, errors.Errorf("invalid argument. CounterUpdateRequest: %v cannot be nil", in.CounterUpdateRequest)
}
if in.CounterUpdateRequest.CountDiff == 0 && in.CounterUpdateRequest.Count == nil && in.CounterUpdateRequest.Capacity == nil {
return nil, errors.Errorf("invalid argument. Malformed CounterUpdateRequest: %v", in.CounterUpdateRequest)
}

s.logger.WithField("name", in.CounterUpdateRequest.Name).Debug("Update Counter Request")

Expand All @@ -890,23 +893,17 @@ func (s *SDKServer) UpdateCounter(ctx context.Context, in *alpha.UpdateCounterRe

batchCounter.counter = *counter.DeepCopy()

switch {
case in.CounterUpdateRequest.CountDiff != 0: // Update based on if Client call is CountIncrement or CountDecrement
count := batchCounter.counter.Count
if batchCounter.countSet != nil {
count = *batchCounter.countSet
}
count += batchCounter.diff + in.CounterUpdateRequest.CountDiff
// Verify that 0 <= Count >= Capacity
capacity := batchCounter.counter.Capacity
if batchCounter.capacitySet != nil {
capacity = *batchCounter.capacitySet
}
if count < 0 || count > capacity {
return nil, errors.Errorf("out of range. Count must be within range [0,Capacity]. Found Count: %d, Capacity: %d", count, capacity)
// Updated based on if client call is CapacitySet
if in.CounterUpdateRequest.Capacity != nil {
if in.CounterUpdateRequest.Capacity.GetValue() < 0 {
return nil, errors.Errorf("out of range. Capacity must be greater than or equal to 0. Found Capacity: %d", in.CounterUpdateRequest.Capacity.GetValue())
}
batchCounter.diff += in.CounterUpdateRequest.CountDiff
case in.CounterUpdateRequest.Count != nil: // Update based on if Client call is CountSet
capacitySet := in.CounterUpdateRequest.Capacity.GetValue()
batchCounter.capacitySet = &capacitySet
}

// Update based on if Client call is CountSet
if in.CounterUpdateRequest.Count != nil {
// Verify that 0 <= Count >= Capacity
countSet := in.CounterUpdateRequest.Count.GetValue()
capacity := batchCounter.counter.Capacity
Expand All @@ -919,14 +916,24 @@ func (s *SDKServer) UpdateCounter(ctx context.Context, in *alpha.UpdateCounterRe
batchCounter.countSet = &countSet
// Clear any previous CountIncrement or CountDecrement requests, and add the CountSet as the first item.
batchCounter.diff = 0
case in.CounterUpdateRequest.Capacity != nil: // Updated based on if client call is CapacitySet
if in.CounterUpdateRequest.Capacity.GetValue() < 0 {
return nil, errors.Errorf("out of range. Capacity must be greater than or equal to 0. Found Capacity: %d", in.CounterUpdateRequest.Capacity.GetValue())
}

// Update based on if Client call is CountIncrement or CountDecrement
if in.CounterUpdateRequest.CountDiff != 0 {
count := batchCounter.counter.Count
if batchCounter.countSet != nil {
count = *batchCounter.countSet
}
capacitySet := in.CounterUpdateRequest.Capacity.GetValue()
batchCounter.capacitySet = &capacitySet
default:
return nil, errors.Errorf("invalid argument. Malformed CounterUpdateRequest: %v", in.CounterUpdateRequest)
count += batchCounter.diff + in.CounterUpdateRequest.CountDiff
// Verify that 0 <= Count >= Capacity
capacity := batchCounter.counter.Capacity
if batchCounter.capacitySet != nil {
capacity = *batchCounter.capacitySet
}
if count < 0 || count > capacity {
return nil, errors.Errorf("out of range. Count must be within range [0,Capacity]. Found Count: %d, Capacity: %d", count, capacity)
}
batchCounter.diff += in.CounterUpdateRequest.CountDiff
}

s.gsCounterUpdates[name] = batchCounter
Expand Down
14 changes: 14 additions & 0 deletions pkg/sdkserver/sdkserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,7 @@ func TestSDKServerUpdateCounter(t *testing.T) {
"twofish": {Count: int64(10), Capacity: int64(100)},
"redfish": {Count: int64(10), Capacity: int64(100)},
"bluefish": {Count: int64(10), Capacity: int64(100)},
"fivefish": {Count: int64(10), Capacity: int64(100)},
}

fixtures := map[string]struct {
Expand Down Expand Up @@ -1233,6 +1234,19 @@ func TestSDKServerUpdateCounter(t *testing.T) {
updateErrs: []bool{false, true},
updated: true,
},
"setcapacity, setcount, and diffcount": {
counterName: "fivefish",
requests: []*alpha.UpdateCounterRequest{{
CounterUpdateRequest: &alpha.CounterUpdateRequest{
Name: "fivefish",
Capacity: wrapperspb.Int64(25),
Count: wrapperspb.Int64(0),
CountDiff: 25,
}}},
want: agonesv1.CounterStatus{Count: int64(25), Capacity: int64(25)},
updateErrs: []bool{false},
updated: true,
},
}

for test, testCase := range fixtures {
Expand Down
160 changes: 123 additions & 37 deletions test/sdk/restapi/http-api-test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

alpha "agones.dev/agones/test/sdk/restapi/alpha/swagger"
"agones.dev/agones/test/sdk/restapi/swagger"
"github.com/google/go-cmp/cmp"
"golang.org/x/net/context"
)

Expand Down Expand Up @@ -114,57 +115,142 @@ func main() {

// easy feature flag check
if strings.Contains(os.Getenv("FEATURE_GATES"), "PlayerTracking=true") {
capacity := "10"
if _, _, err := alphaCli.SDKApi.SetPlayerCapacity(ctx, alpha.AlphaCount{Count: capacity}); err != nil {
log.Fatalf("Could not set Capacity: %v\n", err)
}
testPlayers(ctx, alphaCli)
} else {
log.Print("Player Tracking not enabled, skipping.")
}

count, _, err := alphaCli.SDKApi.GetPlayerCapacity(ctx)
if err != nil {
log.Fatalf("Could not get Capacity: %v\n", err)
}
if count.Count != capacity {
log.Fatalf("Player Capacity should be %s, but is %s", capacity, count.Count)
}
if strings.Contains(os.Getenv("FEATURE_GATES"), "CountsAndLists=true") {
testCounters(ctx, alphaCli)
testLists(ctx, alphaCli)
} else {
log.Print("Counts and Lists not enabled, skipping.")
}

_, _, err = cli.SDKApi.Shutdown(ctx, swagger.SdkEmpty{})
if err != nil {
log.Fatalf("Could not GetGameserver: %v\n", err)
}
log.Println("REST API test finished, all queries were performed")
}

func testPlayers(ctx context.Context, alphaCli *alpha.APIClient) {
capacity := "10"
if _, _, err := alphaCli.SDKApi.SetPlayerCapacity(ctx, alpha.AlphaCount{Count: capacity}); err != nil {
log.Fatalf("Could not set Capacity: %v\n", err)
}

count, _, err := alphaCli.SDKApi.GetPlayerCapacity(ctx)
if err != nil {
log.Fatalf("Could not get Capacity: %v\n", err)
}
if count.Count != capacity {
log.Fatalf("Player Capacity should be %s, but is %s", capacity, count.Count)
}

playerID := "1234"
if ok, _, err := alphaCli.SDKApi.PlayerConnect(ctx, alpha.AlphaPlayerId{PlayerID: playerID}); err != nil {
log.Fatalf("Error registering player as connected: %s", err)
} else if !ok.Bool_ {
log.Fatalf("PlayerConnect returned false")
}

if ok, _, err := alphaCli.SDKApi.IsPlayerConnected(ctx, playerID); err != nil {
log.Fatalf("Error checking if player is connected: %s", err)
} else if !ok.Bool_ {
log.Fatalf("IsPlayerConnected returned false")
}

if list, _, err := alphaCli.SDKApi.GetConnectedPlayers(ctx); err != nil {
log.Fatalf("Error getting connected player: %s", err)
} else if len(list.List) == 0 {
log.Fatalf("No connected players returned")
}

playerID := "1234"
if ok, _, err := alphaCli.SDKApi.PlayerConnect(ctx, alpha.AlphaPlayerId{PlayerID: playerID}); err != nil {
log.Fatalf("Error registering player as connected: %s", err)
} else if !ok.Bool_ {
log.Fatalf("PlayerConnect returned false")
if ok, _, err := alphaCli.SDKApi.PlayerDisconnect(ctx, alpha.AlphaPlayerId{PlayerID: playerID}); err != nil {
log.Fatalf("Error registering player as disconnected: %s", err)
} else if !ok.Bool_ {
log.Fatalf("PlayerDisconnect returned false")
}

if count, _, err := alphaCli.SDKApi.GetPlayerCount(ctx); err != nil {
log.Fatalf("Error retrieving player count: %s", err)
} else if count.Count != "0" {
log.Fatalf("Player Count should be 0, but is %v", count)
}
}

func testCounters(ctx context.Context, alphaCli *alpha.APIClient) {
// Tests are expected to run sequentially on the same pre-defined Counter in the localsdk server
counterName := "conformanceTestCounter"

expectedCounter := alpha.AlphaCounter{Name: counterName, Count: "1", Capacity: "10"}
if counter, _, err := alphaCli.SDKApi.GetCounter(ctx, counterName); err != nil {
log.Fatalf("Error getting Counter: %s", err)
} else {
if !cmp.Equal(expectedCounter, counter) {
log.Fatalf("GetCounter expected Counter: %v, got Counter: %v", expectedCounter, counter)
}
}

if ok, _, err := alphaCli.SDKApi.IsPlayerConnected(ctx, playerID); err != nil {
log.Fatalf("Error checking if player is connected: %s", err)
} else if !ok.Bool_ {
log.Fatalf("IsPlayerConnected returned false")
// Test updatecounter, setcapacitycounter
expectedCounter = alpha.AlphaCounter{Name: counterName, Count: "0", Capacity: "42"}
if counter, _, err := alphaCli.SDKApi.UpdateCounter(ctx, alpha.TheRequestedUpdateToMakeToTheCounter{CountDiff: "-1", Capacity: "42"}, counterName); err != nil {
log.Fatalf("Error getting Counter: %s", err)
} else {
if !cmp.Equal(expectedCounter, counter) {
log.Fatalf("UpdateCounter expected Counter: %v, got Counter: %v", expectedCounter, counter)
}
}

if list, _, err := alphaCli.SDKApi.GetConnectedPlayers(ctx); err != nil {
log.Fatalf("Error getting connected player: %s", err)
} else if len(list.List) == 0 {
log.Fatalf("No connected players returned")
// Test setcountcounter
expectedCounter = alpha.AlphaCounter{Name: counterName, Count: "40", Capacity: "42"}
if counter, _, err := alphaCli.SDKApi.UpdateCounter(ctx, alpha.TheRequestedUpdateToMakeToTheCounter{Count: "40", Capacity: "42"}, counterName); err != nil {
log.Fatalf("Error getting Counter: %s", err)
} else {
if !cmp.Equal(expectedCounter, counter) {
log.Fatalf("UpdateCounter expected Counter: %v, got Counter: %v", expectedCounter, counter)
}
}
}

if ok, _, err := alphaCli.SDKApi.PlayerDisconnect(ctx, alpha.AlphaPlayerId{PlayerID: playerID}); err != nil {
log.Fatalf("Error registering player as disconnected: %s", err)
} else if !ok.Bool_ {
log.Fatalf("PlayerDisconnect returned false")
func testLists(ctx context.Context, alphaCli *alpha.APIClient) {
// Tests are expected to run sequentially on the same pre-defined List in the localsdk server
listName := "conformanceTestList"

expectedList := alpha.AlphaList{Name: listName, Values: []string{"test0", "test1", "test2"}, Capacity: "100"}
if list, _, err := alphaCli.SDKApi.GetList(ctx, listName); err != nil {
log.Fatalf("Error getting List: %s", err)
} else {
if !cmp.Equal(expectedList, list) {
log.Fatalf("GetList expected List: %v, got List: %v", expectedList, list)
}
}

if count, _, err := alphaCli.SDKApi.GetPlayerCount(ctx); err != nil {
log.Fatalf("Error retrieving player count: %s", err)
} else if count.Count != "0" {
log.Fatalf("Player Count should be 0, but is %v", count)
expectedList = alpha.AlphaList{Name: listName, Values: []string{"test123", "test456"}, Capacity: "10"}
if list, _, err := alphaCli.SDKApi.UpdateList(ctx, alpha.TheListToUpdate{Values: []string{"test123", "test456"}, Capacity: "10"}, listName); err != nil {
log.Fatalf("Error getting List: %s", err)
} else {
if !cmp.Equal(expectedList, list) {
log.Fatalf("UpdateList expected List: %v, got List: %v", expectedList, list)
}
}

expectedList = alpha.AlphaList{Name: listName, Values: []string{"test123", "test456", "test789"}, Capacity: "10"}
if list, _, err := alphaCli.SDKApi.AddListValue(ctx, alpha.ListsNameaddValueBody{Value: "test789"}, listName); err != nil {
log.Fatalf("Error getting List: %s", err)
} else {
log.Print("Player Tracking not enabled, skipping.")
if !cmp.Equal(expectedList, list) {
log.Fatalf("AddListValue expected List: %v, got List: %v", expectedList, list)
}
}

_, _, err = cli.SDKApi.Shutdown(ctx, swagger.SdkEmpty{})
if err != nil {
log.Fatalf("Could not GetGameserver: %v\n", err)
expectedList = alpha.AlphaList{Name: listName, Values: []string{"test123", "test789"}, Capacity: "10"}
if list, _, err := alphaCli.SDKApi.RemoveListValue(ctx, alpha.ListsNameremoveValueBody{Value: "test456"}, listName); err != nil {
log.Fatalf("Error getting List: %s", err)
} else {
if !cmp.Equal(expectedList, list) {
log.Fatalf("RemoveListValue expected List: %v, got List: %v", expectedList, list)
}
}
log.Println("REST API test finished, all queries were performed")
}