agones.dev/agones@v1.54.0/sdks/go/beta_test.go (about)

     1  // Copyright 2020 Google LLC All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package sdk
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  
    21  	"github.com/pkg/errors"
    22  	"github.com/stretchr/testify/assert"
    23  	"google.golang.org/grpc"
    24  
    25  	"agones.dev/agones/pkg/sdk/beta"
    26  )
    27  
    28  func TestBetaGetAndUpdateCounter(t *testing.T) {
    29  	mock := &betaMock{}
    30  	// Counters must be predefined in the GameServer resource on creation.
    31  	mock.counters = make(map[string]*beta.Counter)
    32  
    33  	sessions := beta.Counter{
    34  		Name:     "sessions",
    35  		Count:    21,
    36  		Capacity: 42,
    37  	}
    38  	games := beta.Counter{
    39  		Name:     "games",
    40  		Count:    12,
    41  		Capacity: 24,
    42  	}
    43  	gamers := beta.Counter{
    44  		Name:     "gamers",
    45  		Count:    263,
    46  		Capacity: 500,
    47  	}
    48  
    49  	mock.counters["sessions"] = &beta.Counter{
    50  		Name:     "sessions",
    51  		Count:    21,
    52  		Capacity: 42,
    53  	}
    54  	mock.counters["games"] = &beta.Counter{
    55  		Name:     "games",
    56  		Count:    12,
    57  		Capacity: 24,
    58  	}
    59  	mock.counters["gamers"] = &beta.Counter{
    60  		Name:     "gamers",
    61  		Count:    263,
    62  		Capacity: 500,
    63  	}
    64  
    65  	b := Beta{
    66  		client: mock,
    67  	}
    68  
    69  	t.Parallel()
    70  
    71  	t.Run("Set Counter and Set Capacity", func(t *testing.T) {
    72  		count, err := b.GetCounterCount("sessions")
    73  		assert.NoError(t, err)
    74  		assert.Equal(t, sessions.Count, count)
    75  
    76  		capacity, err := b.GetCounterCapacity("sessions")
    77  		assert.NoError(t, err)
    78  		assert.Equal(t, sessions.Capacity, capacity)
    79  
    80  		wantCapacity := int64(25)
    81  		err = b.SetCounterCapacity("sessions", wantCapacity)
    82  		assert.NoError(t, err)
    83  
    84  		capacity, err = b.GetCounterCapacity("sessions")
    85  		assert.NoError(t, err)
    86  		assert.Equal(t, wantCapacity, capacity)
    87  
    88  		wantCount := int64(10)
    89  		err = b.SetCounterCount("sessions", wantCount)
    90  		assert.NoError(t, err)
    91  
    92  		count, err = b.GetCounterCount("sessions")
    93  		assert.NoError(t, err)
    94  		assert.Equal(t, wantCount, count)
    95  	})
    96  
    97  	t.Run("Get and Set Non-Defined Counter", func(t *testing.T) {
    98  		_, err := b.GetCounterCount("secessions")
    99  		assert.Error(t, err)
   100  
   101  		_, err = b.GetCounterCapacity("secessions")
   102  		assert.Error(t, err)
   103  
   104  		err = b.SetCounterCapacity("secessions", int64(100))
   105  		assert.Error(t, err)
   106  
   107  		err = b.SetCounterCount("secessions", int64(0))
   108  		assert.Error(t, err)
   109  	})
   110  
   111  	// nolint:dupl // testing DecrementCounter and IncrementCounter are not duplicates.
   112  	t.Run("Decrement Counter Fails then Success", func(t *testing.T) {
   113  		count, err := b.GetCounterCount("games")
   114  		assert.NoError(t, err)
   115  		assert.Equal(t, games.Count, count)
   116  
   117  		err = b.DecrementCounter("games", 21)
   118  		assert.Error(t, err)
   119  
   120  		count, err = b.GetCounterCount("games")
   121  		assert.NoError(t, err)
   122  		assert.Equal(t, games.Count, count)
   123  
   124  		err = b.DecrementCounter("games", -12)
   125  		assert.Error(t, err)
   126  
   127  		count, err = b.GetCounterCount("games")
   128  		assert.NoError(t, err)
   129  		assert.Equal(t, games.Count, count)
   130  
   131  		err = b.DecrementCounter("games", 12)
   132  		assert.NoError(t, err)
   133  
   134  		count, err = b.GetCounterCount("games")
   135  		assert.NoError(t, err)
   136  		assert.Equal(t, int64(0), count)
   137  	})
   138  
   139  	// nolint:dupl // testing DecrementCounter and IncrementCounter are not duplicates.
   140  	t.Run("Increment Counter Fails then Success", func(t *testing.T) {
   141  		count, err := b.GetCounterCount("gamers")
   142  		assert.NoError(t, err)
   143  		assert.Equal(t, gamers.Count, count)
   144  
   145  		err = b.IncrementCounter("gamers", 250)
   146  		assert.Error(t, err)
   147  
   148  		count, err = b.GetCounterCount("gamers")
   149  		assert.NoError(t, err)
   150  		assert.Equal(t, gamers.Count, count)
   151  
   152  		err = b.IncrementCounter("gamers", -237)
   153  		assert.Error(t, err)
   154  
   155  		count, err = b.GetCounterCount("gamers")
   156  		assert.NoError(t, err)
   157  		assert.Equal(t, gamers.Count, count)
   158  
   159  		err = b.IncrementCounter("gamers", 237)
   160  		assert.NoError(t, err)
   161  
   162  		count, err = b.GetCounterCount("gamers")
   163  		assert.NoError(t, err)
   164  		assert.Equal(t, int64(500), count)
   165  	})
   166  
   167  }
   168  
   169  func TestBetaGetAndUpdateList(t *testing.T) {
   170  	mock := &betaMock{}
   171  	// Lists must be predefined in the GameServer resource on creation.
   172  	mock.lists = make(map[string]*beta.List)
   173  
   174  	foo := beta.List{
   175  		Name:     "foo",
   176  		Values:   []string{},
   177  		Capacity: 2,
   178  	}
   179  	bar := beta.List{
   180  		Name:     "bar",
   181  		Values:   []string{"abc", "def"},
   182  		Capacity: 5,
   183  	}
   184  	baz := beta.List{
   185  		Name:     "baz",
   186  		Values:   []string{"123", "456", "789"},
   187  		Capacity: 5,
   188  	}
   189  
   190  	mock.lists["foo"] = &beta.List{
   191  		Name:     "foo",
   192  		Values:   []string{},
   193  		Capacity: 2,
   194  	}
   195  	mock.lists["bar"] = &beta.List{
   196  		Name:     "bar",
   197  		Values:   []string{"abc", "def"},
   198  		Capacity: 5,
   199  	}
   200  	mock.lists["baz"] = &beta.List{
   201  		Name:     "baz",
   202  		Values:   []string{"123", "456", "789"},
   203  		Capacity: 5,
   204  	}
   205  
   206  	b := Beta{
   207  		client: mock,
   208  	}
   209  
   210  	t.Parallel()
   211  
   212  	t.Run("Get and Set List Capacity", func(t *testing.T) {
   213  		capacity, err := b.GetListCapacity("foo")
   214  		assert.NoError(t, err)
   215  		assert.Equal(t, foo.Capacity, capacity)
   216  
   217  		wantCapacity := int64(5)
   218  		err = b.SetListCapacity("foo", wantCapacity)
   219  		assert.NoError(t, err)
   220  
   221  		capacity, err = b.GetListCapacity("foo")
   222  		assert.NoError(t, err)
   223  		assert.Equal(t, wantCapacity, capacity)
   224  	})
   225  
   226  	t.Run("Get List Length, Get List Values, ListContains, and Append List Value", func(t *testing.T) {
   227  		length, err := b.GetListLength("bar")
   228  		assert.NoError(t, err)
   229  		assert.Equal(t, len(bar.Values), length)
   230  
   231  		values, err := b.GetListValues("bar")
   232  		assert.NoError(t, err)
   233  		assert.Equal(t, bar.Values, values)
   234  
   235  		err = b.AppendListValue("bar", "ghi")
   236  		assert.NoError(t, err)
   237  
   238  		length, err = b.GetListLength("bar")
   239  		assert.NoError(t, err)
   240  		assert.Equal(t, len(bar.Values)+1, length)
   241  
   242  		wantValues := []string{"abc", "def", "ghi"}
   243  		values, err = b.GetListValues("bar")
   244  		assert.NoError(t, err)
   245  		assert.Equal(t, wantValues, values)
   246  
   247  		contains, err := b.ListContains("bar", "ghi")
   248  		assert.NoError(t, err)
   249  		assert.True(t, contains)
   250  	})
   251  
   252  	t.Run("Get List Length, Get List Values, ListContains, and Delete List Value", func(t *testing.T) {
   253  		length, err := b.GetListLength("baz")
   254  		assert.NoError(t, err)
   255  		assert.Equal(t, len(baz.Values), length)
   256  
   257  		values, err := b.GetListValues("baz")
   258  		assert.NoError(t, err)
   259  		assert.Equal(t, baz.Values, values)
   260  
   261  		err = b.DeleteListValue("baz", "456")
   262  		assert.NoError(t, err)
   263  
   264  		length, err = b.GetListLength("baz")
   265  		assert.NoError(t, err)
   266  		assert.Equal(t, len(baz.Values)-1, length)
   267  
   268  		wantValues := []string{"123", "789"}
   269  		values, err = b.GetListValues("baz")
   270  		assert.NoError(t, err)
   271  		assert.Equal(t, wantValues, values)
   272  
   273  		contains, err := b.ListContains("baz", "456")
   274  		assert.NoError(t, err)
   275  		assert.False(t, contains)
   276  	})
   277  
   278  }
   279  
   280  type betaMock struct {
   281  	counters map[string]*beta.Counter
   282  	lists    map[string]*beta.List
   283  }
   284  
   285  func (b *betaMock) GetCounter(_ context.Context, in *beta.GetCounterRequest, _ ...grpc.CallOption) (*beta.Counter, error) {
   286  	if counter, ok := b.counters[in.Name]; ok {
   287  		return counter, nil
   288  	}
   289  	return nil, errors.Errorf("counter not found: %s", in.Name)
   290  }
   291  
   292  func (b *betaMock) UpdateCounter(ctx context.Context, in *beta.UpdateCounterRequest, _ ...grpc.CallOption) (*beta.Counter, error) {
   293  	counter, err := b.GetCounter(ctx, &beta.GetCounterRequest{Name: in.CounterUpdateRequest.Name})
   294  	if err != nil {
   295  		return nil, err
   296  	}
   297  
   298  	switch {
   299  	case in.CounterUpdateRequest.CountDiff != 0:
   300  		count := counter.Count + in.CounterUpdateRequest.CountDiff
   301  		if count < 0 || count > counter.Capacity {
   302  			return nil, errors.Errorf("out of range. Count must be within range [0,Capacity]. Found Count: %d, Capacity: %d", count, counter.Capacity)
   303  		}
   304  		counter.Count = count
   305  	case in.CounterUpdateRequest.Count != nil:
   306  		countSet := in.CounterUpdateRequest.Count.GetValue()
   307  		if countSet < 0 || countSet > counter.Capacity {
   308  			return nil, errors.Errorf("out of range. Count must be within range [0,Capacity]. Found Count: %d, Capacity: %d", countSet, counter.Capacity)
   309  		}
   310  		counter.Count = countSet
   311  	case in.CounterUpdateRequest.Capacity != nil:
   312  		capacity := in.CounterUpdateRequest.Capacity.GetValue()
   313  		if capacity < 0 {
   314  			return nil, errors.Errorf("out of range. Capacity must be greater than or equal to 0. Found Capacity: %d", capacity)
   315  		}
   316  		counter.Capacity = capacity
   317  	default:
   318  		return nil, errors.Errorf("invalid argument. Malformed CounterUpdateRequest: %v",
   319  			in.CounterUpdateRequest)
   320  	}
   321  
   322  	b.counters[in.CounterUpdateRequest.Name] = counter
   323  	return b.counters[in.CounterUpdateRequest.Name], nil
   324  }
   325  
   326  // GetList returns the list of betaMock. Note: unlike the SDK Server, this does not return
   327  // a list with any pending batched changes applied.
   328  func (b *betaMock) GetList(_ context.Context, in *beta.GetListRequest, _ ...grpc.CallOption) (*beta.List, error) {
   329  	if in == nil {
   330  		return nil, errors.Errorf("GetListRequest cannot be nil")
   331  	}
   332  	if list, ok := b.lists[in.Name]; ok {
   333  		return list, nil
   334  	}
   335  	return nil, errors.Errorf("list not found: %s", in.Name)
   336  }
   337  
   338  // Note: unlike the SDK Server, UpdateList does not batch changes and instead updates the list
   339  // directly.
   340  func (b *betaMock) UpdateList(_ context.Context, in *beta.UpdateListRequest, _ ...grpc.CallOption) (*beta.List, error) {
   341  	if in == nil {
   342  		return nil, errors.Errorf("UpdateListRequest cannot be nil")
   343  	}
   344  	list, ok := b.lists[in.List.Name]
   345  	if !ok {
   346  		return nil, errors.Errorf("list not found: %s", in.List.Name)
   347  	}
   348  	if in.List.Capacity < 0 || in.List.Capacity > 1000 {
   349  		return nil, errors.Errorf("out of range. Capacity must be within range [0,1000]. Found Capacity: %d", in.List.Capacity)
   350  	}
   351  	list.Capacity = in.List.Capacity
   352  	if len(list.Values) > int(list.Capacity) {
   353  		list.Values = append([]string{}, list.Values[:list.Capacity]...)
   354  	}
   355  	b.lists[in.List.Name] = list
   356  	return &beta.List{}, nil
   357  }
   358  
   359  // Note: unlike the SDK Server, AddListValue does not batch changes and instead updates the list
   360  // directly.
   361  func (b *betaMock) AddListValue(_ context.Context, in *beta.AddListValueRequest, _ ...grpc.CallOption) (*beta.List, error) {
   362  	if in == nil {
   363  		return nil, errors.Errorf("AddListValueRequest cannot be nil")
   364  	}
   365  	list, ok := b.lists[in.Name]
   366  	if !ok {
   367  		return nil, errors.Errorf("list not found: %s", in.Name)
   368  	}
   369  	if int(list.Capacity) <= len(list.Values) {
   370  		return nil, errors.Errorf("out of range. No available capacity. Current Capacity: %d, List Size: %d", list.Capacity, len(list.Values))
   371  	}
   372  	for _, val := range list.Values {
   373  		if in.Value == val {
   374  			return nil, errors.Errorf("already exists. Value: %s already in List: %s", in.Value, in.Name)
   375  		}
   376  	}
   377  	list.Values = append(list.Values, in.Value)
   378  	b.lists[in.Name] = list
   379  	return &beta.List{}, nil
   380  }
   381  
   382  // Note: unlike the SDK Server, RemoveListValue does not batch changes and instead updates the list
   383  // directly.
   384  func (b *betaMock) RemoveListValue(_ context.Context, in *beta.RemoveListValueRequest, _ ...grpc.CallOption) (*beta.List, error) {
   385  	if in == nil {
   386  		return nil, errors.Errorf("RemoveListValueRequest cannot be nil")
   387  	}
   388  	list, ok := b.lists[in.Name]
   389  	if !ok {
   390  		return nil, errors.Errorf("list not found: %s", in.Name)
   391  	}
   392  	for i, val := range list.Values {
   393  		if in.Value != val {
   394  			continue
   395  		}
   396  		list.Values = append(list.Values[:i], list.Values[i+1:]...)
   397  		b.lists[in.Name] = list
   398  		return &beta.List{}, nil
   399  	}
   400  	return nil, errors.Errorf("not found. Value: %s not found in List: %s", in.Value, in.Name)
   401  }