github.com/GoogleCloudPlatform/testgrid@v0.0.174/config/queue_test.go (about) 1 /* 2 Copyright 2021 The TestGrid Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package config 18 19 import ( 20 "context" 21 "sync" 22 "testing" 23 "time" 24 25 configpb "github.com/GoogleCloudPlatform/testgrid/pb/config" 26 "github.com/google/go-cmp/cmp" 27 "github.com/sirupsen/logrus" 28 "google.golang.org/protobuf/testing/protocmp" 29 ) 30 31 func TestStatus(t *testing.T) { 32 now := time.Now() 33 log := logrus.WithField("test", "TestStatus") 34 cases := []struct { 35 name string 36 q *TestGroupQueue 37 38 depth int 39 next *configpb.TestGroup 40 when time.Time 41 }{ 42 { 43 name: "empty", 44 q: &TestGroupQueue{}, 45 }, 46 { 47 name: "single", 48 q: func() *TestGroupQueue { 49 var q TestGroupQueue 50 q.Init(log, []*configpb.TestGroup{ 51 { 52 Name: "hi", 53 }, 54 }, now) 55 return &q 56 }(), 57 depth: 1, 58 next: &configpb.TestGroup{ 59 Name: "hi", 60 }, 61 when: now, 62 }, 63 { 64 name: "multi", 65 q: func() *TestGroupQueue { 66 var q TestGroupQueue 67 q.Init(log, []*configpb.TestGroup{ 68 { 69 Name: "hi", 70 }, 71 { 72 Name: "middle", 73 }, 74 { 75 Name: "there", 76 }, 77 }, now) 78 q.Fix("middle", now.Add(-time.Minute), true) 79 return &q 80 }(), 81 depth: 3, 82 next: &configpb.TestGroup{ 83 Name: "middle", 84 }, 85 when: now.Add(-time.Minute), 86 }, 87 } 88 89 for _, tc := range cases { 90 t.Run(tc.name, func(t *testing.T) { 91 depth, next, when := tc.q.Status() 92 if want, got := tc.depth, depth; want != got { 93 t.Errorf("Status() wanted depth %d, got %d", want, got) 94 } 95 if diff := cmp.Diff(tc.next, next, protocmp.Transform()); diff != "" { 96 t.Errorf("Status() got unexpected next diff (-want +got):\n%s", diff) 97 } 98 if !when.Equal(tc.when) { 99 t.Errorf("Status() wanted when %v, got %v", tc.when, when) 100 } 101 }) 102 } 103 } 104 105 func TestSend(t *testing.T) { 106 log := logrus.WithField("test", "TestSend") 107 cases := []struct { 108 name string 109 q *TestGroupQueue 110 receivers func(context.Context, *testing.T) (context.Context, chan<- *configpb.TestGroup, func() []*configpb.TestGroup) 111 freq time.Duration 112 113 want []*configpb.TestGroup 114 }{ 115 { 116 name: "empty", 117 q: func() *TestGroupQueue { 118 var q TestGroupQueue 119 q.Init(log, nil, time.Now()) 120 return &q 121 }(), 122 receivers: func(ctx context.Context, t *testing.T) (context.Context, chan<- *configpb.TestGroup, func() []*configpb.TestGroup) { 123 ch := make(chan *configpb.TestGroup) 124 go func() { 125 for { 126 select { 127 case tg := <-ch: 128 t.Errorf("Send() receiver got unexpected group: %v", tg) 129 return 130 case <-ctx.Done(): 131 return 132 } 133 } 134 }() 135 136 return ctx, ch, func() []*configpb.TestGroup { return nil } 137 }, 138 }, 139 { 140 name: "empty loop", 141 q: func() *TestGroupQueue { 142 var q TestGroupQueue 143 q.Init(log, nil, time.Now()) 144 return &q 145 }(), 146 receivers: func(ctx context.Context, t *testing.T) (context.Context, chan<- *configpb.TestGroup, func() []*configpb.TestGroup) { 147 ch := make(chan *configpb.TestGroup) 148 ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 149 go func() { 150 for { 151 select { 152 case tg := <-ch: 153 t.Errorf("Send() receiver got unexpected group: %v", tg) 154 return 155 case <-ctx.Done(): 156 cancel() 157 return 158 } 159 } 160 }() 161 162 return ctx, ch, func() []*configpb.TestGroup { return nil } 163 }, 164 freq: time.Microsecond, 165 }, 166 { 167 name: "single", 168 q: func() *TestGroupQueue { 169 var q TestGroupQueue 170 q.Init(log, []*configpb.TestGroup{ 171 { 172 Name: "hi", 173 }, 174 }, time.Now()) 175 return &q 176 }(), 177 receivers: func(ctx context.Context, t *testing.T) (context.Context, chan<- *configpb.TestGroup, func() []*configpb.TestGroup) { 178 ch := make(chan *configpb.TestGroup) 179 var wg sync.WaitGroup 180 wg.Add(1) 181 var got []*configpb.TestGroup 182 go func() { 183 defer wg.Done() 184 for { 185 select { 186 case tg := <-ch: 187 got = append(got, tg) 188 return 189 case <-ctx.Done(): 190 return 191 } 192 } 193 }() 194 195 return ctx, ch, func() []*configpb.TestGroup { 196 wg.Wait() 197 return got 198 } 199 }, 200 want: []*configpb.TestGroup{ 201 { 202 Name: "hi", 203 }, 204 }, 205 }, 206 { 207 name: "single loop", 208 q: func() *TestGroupQueue { 209 var q TestGroupQueue 210 q.Init(log, []*configpb.TestGroup{ 211 { 212 Name: "hi", 213 }, 214 }, time.Now()) 215 return &q 216 }(), 217 receivers: func(ctx context.Context, _ *testing.T) (context.Context, chan<- *configpb.TestGroup, func() []*configpb.TestGroup) { 218 ch := make(chan *configpb.TestGroup) 219 var wg sync.WaitGroup 220 wg.Add(1) 221 var got []*configpb.TestGroup 222 ctx, cancel := context.WithCancel(ctx) 223 go func() { 224 defer wg.Done() 225 for { 226 select { 227 case tg := <-ch: 228 got = append(got, tg) 229 if len(got) == 3 { 230 cancel() 231 } 232 case <-ctx.Done(): 233 cancel() 234 return 235 } 236 } 237 }() 238 239 return ctx, ch, func() []*configpb.TestGroup { 240 wg.Wait() 241 return got 242 } 243 }, 244 freq: time.Microsecond, 245 want: []*configpb.TestGroup{ 246 { 247 Name: "hi", 248 }, 249 { 250 Name: "hi", 251 }, 252 { 253 Name: "hi", 254 }, 255 }, 256 }, 257 { 258 name: "multi", 259 q: func() *TestGroupQueue { 260 var q TestGroupQueue 261 q.Init(log, []*configpb.TestGroup{ 262 { 263 Name: "hi", 264 }, 265 { 266 Name: "there", 267 }, 268 }, time.Now()) 269 return &q 270 }(), 271 receivers: func(ctx context.Context, _ *testing.T) (context.Context, chan<- *configpb.TestGroup, func() []*configpb.TestGroup) { 272 ch := make(chan *configpb.TestGroup) 273 var wg sync.WaitGroup 274 wg.Add(1) 275 var got []*configpb.TestGroup 276 go func() { 277 defer wg.Done() 278 for { 279 select { 280 case tg := <-ch: 281 got = append(got, tg) 282 if len(got) == 2 { 283 return 284 } 285 case <-ctx.Done(): 286 return 287 } 288 } 289 }() 290 291 return ctx, ch, func() []*configpb.TestGroup { 292 wg.Wait() 293 return got 294 } 295 }, 296 want: []*configpb.TestGroup{ 297 { 298 Name: "hi", 299 }, 300 { 301 Name: "there", 302 }, 303 }, 304 }, 305 { 306 name: "multi loop", 307 q: func() *TestGroupQueue { 308 var q TestGroupQueue 309 q.Init(log, []*configpb.TestGroup{ 310 { 311 Name: "hi", 312 }, 313 { 314 Name: "there", 315 }, 316 }, time.Now()) 317 return &q 318 }(), 319 receivers: func(ctx context.Context, _ *testing.T) (context.Context, chan<- *configpb.TestGroup, func() []*configpb.TestGroup) { 320 ch := make(chan *configpb.TestGroup) 321 var wg sync.WaitGroup 322 wg.Add(1) 323 var got []*configpb.TestGroup 324 ctx, cancel := context.WithCancel(ctx) 325 go func() { 326 defer wg.Done() 327 for { 328 select { 329 case tg := <-ch: 330 got = append(got, tg) 331 if len(got) == 6 { 332 cancel() 333 } 334 case <-ctx.Done(): 335 cancel() 336 return 337 } 338 } 339 }() 340 341 return ctx, ch, func() []*configpb.TestGroup { 342 wg.Wait() 343 return got 344 } 345 }, 346 freq: time.Microsecond, 347 want: []*configpb.TestGroup{ 348 { 349 Name: "hi", 350 }, 351 { 352 Name: "there", 353 }, 354 { 355 Name: "hi", 356 }, 357 { 358 Name: "there", 359 }, 360 { 361 Name: "hi", 362 }, 363 { 364 Name: "there", 365 }, 366 }, 367 }, 368 } 369 370 for _, tc := range cases { 371 t.Run(tc.name, func(t *testing.T) { 372 373 ctx, cancel := context.WithCancel(context.Background()) 374 defer cancel() 375 376 ctx, channel, get := tc.receivers(ctx, t) 377 if err := tc.q.Send(ctx, channel, tc.freq); err != ctx.Err() { 378 t.Errorf("Send() returned unexpected error: want %v, got %v", ctx.Err(), err) 379 } 380 got := get() 381 if diff := cmp.Diff(tc.want, got, protocmp.Transform()); diff != "" { 382 t.Errorf("Send() got unexpected diff (-want +got):\n%s", diff) 383 } 384 }) 385 } 386 }