agones.dev/agones@v1.53.0/pkg/gameserversets/gameserversets_test.go (about) 1 // Copyright 2018 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 gameserversets 16 17 import ( 18 "sort" 19 "testing" 20 "time" 21 22 agonesv1 "agones.dev/agones/pkg/apis/agones/v1" 23 "agones.dev/agones/pkg/gameservers" 24 agtesting "agones.dev/agones/pkg/testing" 25 utilruntime "agones.dev/agones/pkg/util/runtime" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/apimachinery/pkg/runtime" 30 k8stesting "k8s.io/client-go/testing" 31 ) 32 33 func TestSortGameServersByPackedStrategy(t *testing.T) { 34 t.Parallel() 35 36 utilruntime.FeatureTestMutex.Lock() 37 defer utilruntime.FeatureTestMutex.Unlock() 38 39 require.NoError(t, utilruntime.ParseFeatures(string(utilruntime.FeatureCountsAndLists)+"=true")) 40 41 nc := map[string]gameservers.NodeCount{ 42 "n1": {Ready: 1, Allocated: 0}, 43 "n2": {Ready: 0, Allocated: 2}, 44 "n3": {Ready: 2, Allocated: 2}, 45 "n4": {Ready: 2, Allocated: 2}, 46 } 47 48 list := []*agonesv1.GameServer{ 49 {ObjectMeta: metav1.ObjectMeta{Name: "g1"}, Status: agonesv1.GameServerStatus{NodeName: "n2", State: agonesv1.GameServerStateReady}}, 50 {ObjectMeta: metav1.ObjectMeta{Name: "g2"}, Status: agonesv1.GameServerStatus{NodeName: "", State: agonesv1.GameServerStateReady}}, 51 {ObjectMeta: metav1.ObjectMeta{Name: "g3"}, Status: agonesv1.GameServerStatus{NodeName: "n1", State: agonesv1.GameServerStateReady}}, 52 {ObjectMeta: metav1.ObjectMeta{Name: "g4"}, Status: agonesv1.GameServerStatus{NodeName: "n2", State: agonesv1.GameServerStateCreating}}, 53 {ObjectMeta: metav1.ObjectMeta{Name: "g5"}, Status: agonesv1.GameServerStatus{NodeName: "n3", State: agonesv1.GameServerStateReady}}, 54 {ObjectMeta: metav1.ObjectMeta{Name: "g6"}, Status: agonesv1.GameServerStatus{NodeName: "n4", State: agonesv1.GameServerStateReady}}, 55 {ObjectMeta: metav1.ObjectMeta{Name: "g7"}, Status: agonesv1.GameServerStatus{NodeName: "n3", State: agonesv1.GameServerStateReady}}, 56 {ObjectMeta: metav1.ObjectMeta{Name: "g8"}, Status: agonesv1.GameServerStatus{NodeName: "n4", State: agonesv1.GameServerStateReady}}, 57 {ObjectMeta: metav1.ObjectMeta{Name: "g9"}, Status: agonesv1.GameServerStatus{ 58 NodeName: "n3", 59 State: agonesv1.GameServerStateAllocated, 60 Counters: map[string]agonesv1.CounterStatus{ 61 "foo": { 62 Count: 0, 63 Capacity: 100, 64 }}}}, 65 {ObjectMeta: metav1.ObjectMeta{Name: "g10"}, Status: agonesv1.GameServerStatus{ 66 NodeName: "n3", 67 State: agonesv1.GameServerStateAllocated, 68 Counters: map[string]agonesv1.CounterStatus{ 69 "foo": { 70 Count: 99, 71 Capacity: 100, 72 }}}}, 73 {ObjectMeta: metav1.ObjectMeta{Name: "g11"}, Status: agonesv1.GameServerStatus{ 74 NodeName: "n4", 75 State: agonesv1.GameServerStateAllocated, 76 Counters: map[string]agonesv1.CounterStatus{ 77 "foo": { 78 Count: 0, 79 Capacity: 90, 80 }}}}, 81 {ObjectMeta: metav1.ObjectMeta{Name: "g12"}, Status: agonesv1.GameServerStatus{ 82 NodeName: "n4", 83 State: agonesv1.GameServerStateAllocated, 84 Counters: map[string]agonesv1.CounterStatus{ 85 "foo": { 86 Count: 89, 87 Capacity: 90, 88 }}}}, 89 } 90 91 priorities := []agonesv1.Priority{{ 92 Type: "Counter", 93 Key: "foo", 94 Order: "Descending", 95 }} 96 97 result := sortGameServersByPackedStrategy(list, nc, priorities) 98 99 require.Len(t, result, len(list)) 100 assert.Equal(t, "g2", result[0].ObjectMeta.Name) 101 assert.Equal(t, "g3", result[1].ObjectMeta.Name) 102 assert.Equal(t, "g4", result[2].ObjectMeta.Name) 103 assert.Equal(t, "g1", result[3].ObjectMeta.Name) 104 assert.Equal(t, "g9", result[4].ObjectMeta.Name) 105 assert.Equal(t, "g10", result[5].ObjectMeta.Name) 106 assert.Equal(t, "g5", result[6].ObjectMeta.Name) 107 assert.Equal(t, "g7", result[7].ObjectMeta.Name) 108 assert.Equal(t, "g11", result[8].ObjectMeta.Name) 109 assert.Equal(t, "g12", result[9].ObjectMeta.Name) 110 assert.Equal(t, "g6", result[10].ObjectMeta.Name) 111 assert.Equal(t, "g8", result[11].ObjectMeta.Name) 112 113 priorities = []agonesv1.Priority{{ 114 Type: "Counter", 115 Key: "foo", 116 Order: "Ascending", 117 }} 118 119 result = sortGameServersByPackedStrategy(list, nc, priorities) 120 121 require.Len(t, result, len(list)) 122 assert.Equal(t, "g2", result[0].ObjectMeta.Name) 123 assert.Equal(t, "g3", result[1].ObjectMeta.Name) 124 assert.Equal(t, "g4", result[2].ObjectMeta.Name) 125 assert.Equal(t, "g1", result[3].ObjectMeta.Name) 126 assert.Equal(t, "g10", result[4].ObjectMeta.Name) 127 assert.Equal(t, "g9", result[5].ObjectMeta.Name) 128 assert.Equal(t, "g5", result[6].ObjectMeta.Name) 129 assert.Equal(t, "g7", result[7].ObjectMeta.Name) 130 assert.Equal(t, "g12", result[8].ObjectMeta.Name) 131 assert.Equal(t, "g11", result[9].ObjectMeta.Name) 132 assert.Equal(t, "g6", result[10].ObjectMeta.Name) 133 assert.Equal(t, "g8", result[11].ObjectMeta.Name) 134 } 135 136 func TestSortGameServersByDistributedStrategy(t *testing.T) { 137 t.Parallel() 138 139 utilruntime.FeatureTestMutex.Lock() 140 defer utilruntime.FeatureTestMutex.Unlock() 141 142 require.NoError(t, utilruntime.ParseFeatures(string(utilruntime.FeatureCountsAndLists)+"=true")) 143 144 now := metav1.Now() 145 146 gs1 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "g1", CreationTimestamp: metav1.Time{Time: now.Add(10 * time.Second)}}} 147 gs2 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "g2", CreationTimestamp: now}} 148 gs3 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "g3", CreationTimestamp: metav1.Time{Time: now.Add(30 * time.Second)}}} 149 gs4 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "g4", CreationTimestamp: metav1.Time{Time: now.Add(30 * time.Second)}}, 150 Status: agonesv1.GameServerStatus{ 151 Counters: map[string]agonesv1.CounterStatus{ 152 "bar": { 153 Count: 0, 154 Capacity: 100, 155 }}}} 156 gs5 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "g5", CreationTimestamp: now}, 157 Status: agonesv1.GameServerStatus{ 158 Counters: map[string]agonesv1.CounterStatus{ 159 "bar": { 160 Count: 0, 161 Capacity: 100, 162 }}}} 163 gs6 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "g6", CreationTimestamp: now}, 164 Status: agonesv1.GameServerStatus{ 165 Counters: map[string]agonesv1.CounterStatus{ 166 "bar": { 167 Count: 0, 168 Capacity: 1000, 169 }}}} 170 171 testScenarios := map[string]struct { 172 list []*agonesv1.GameServer 173 priorities []agonesv1.Priority 174 want []*agonesv1.GameServer 175 }{ 176 "No priorities, sort by creation time": { 177 list: []*agonesv1.GameServer{&gs1, &gs2, &gs3}, 178 priorities: nil, 179 want: []*agonesv1.GameServer{&gs2, &gs1, &gs3}, 180 }, 181 "Descending priorities": { 182 list: []*agonesv1.GameServer{&gs4, &gs6, &gs5}, 183 priorities: []agonesv1.Priority{{ 184 Type: "Counter", 185 Key: "bar", 186 Order: "Descending", 187 }}, 188 want: []*agonesv1.GameServer{&gs6, &gs5, &gs4}, 189 }, 190 "Ascending priorities": { 191 list: []*agonesv1.GameServer{&gs4, &gs5, &gs6}, 192 priorities: []agonesv1.Priority{{ 193 Type: "Counter", 194 Key: "bar", 195 Order: "Ascending", 196 }}, 197 want: []*agonesv1.GameServer{&gs5, &gs4, &gs6}, 198 }, 199 } 200 201 for testName, testScenario := range testScenarios { 202 t.Run(testName, func(t *testing.T) { 203 204 result := sortGameServersByDistributedStrategy(testScenario.list, testScenario.priorities) 205 assert.Equal(t, testScenario.want, result) 206 }) 207 } 208 } 209 210 func TestListGameServersByGameServerSetOwner(t *testing.T) { 211 t.Parallel() 212 213 gsSet := &agonesv1.GameServerSet{ 214 ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "test", UID: "1234"}, 215 Spec: agonesv1.GameServerSetSpec{ 216 Replicas: 10, 217 Template: agonesv1.GameServerTemplateSpec{}, 218 }, 219 } 220 221 gs1 := gsSet.GameServer() 222 gs1.ObjectMeta.Name = "test-1" 223 gs2 := gsSet.GameServer() 224 assert.True(t, metav1.IsControlledBy(gs2, gsSet)) 225 226 gs2.ObjectMeta.Name = "test-2" 227 gs3 := agonesv1.GameServer{ObjectMeta: metav1.ObjectMeta{Name: "not-included"}} 228 gs4 := gsSet.GameServer() 229 gs4.ObjectMeta.OwnerReferences = nil 230 231 m := agtesting.NewMocks() 232 m.AgonesClient.AddReactor("list", "gameservers", func(_ k8stesting.Action) (bool, runtime.Object, error) { 233 return true, &agonesv1.GameServerList{Items: []agonesv1.GameServer{*gs1, *gs2, gs3, *gs4}}, nil 234 }) 235 236 gameServers := m.AgonesInformerFactory.Agones().V1().GameServers() 237 _, cancel := agtesting.StartInformers(m, gameServers.Informer().HasSynced) 238 defer cancel() 239 240 list, err := ListGameServersByGameServerSetOwner(gameServers.Lister(), gsSet) 241 require.NoError(t, err) 242 243 // sort of stable ordering 244 sort.SliceStable(list, func(i, j int) bool { 245 return list[i].ObjectMeta.Name < list[j].ObjectMeta.Name 246 }) 247 assert.Equal(t, []*agonesv1.GameServer{gs1, gs2}, list) 248 }