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  }