github.com/GoogleCloudPlatform/testgrid@v0.0.174/pkg/updater/persist_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes 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 updater
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"errors"
    23  	"testing"
    24  	"time"
    25  
    26  	"cloud.google.com/go/storage"
    27  	"github.com/GoogleCloudPlatform/testgrid/config"
    28  	configpb "github.com/GoogleCloudPlatform/testgrid/pb/config"
    29  	"github.com/GoogleCloudPlatform/testgrid/util/gcs"
    30  	"github.com/GoogleCloudPlatform/testgrid/util/gcs/fake"
    31  	"github.com/google/go-cmp/cmp"
    32  	"github.com/sirupsen/logrus"
    33  )
    34  
    35  func TestFixPersistent(t *testing.T) {
    36  	now := time.Now().Round(time.Second)
    37  	next := now.Add(time.Minute)
    38  	later := now.Add(time.Hour)
    39  	cases := []struct {
    40  		name        string
    41  		q           *config.TestGroupQueue
    42  		currently   fake.Object
    43  		ticks       []time.Time
    44  		fixes       map[string]time.Time
    45  		wantCurrent map[string]time.Time
    46  		wantBuf     string
    47  	}{
    48  		{
    49  			name:        "basic",
    50  			q:           &config.TestGroupQueue{},
    51  			wantCurrent: map[string]time.Time{},
    52  		},
    53  		{
    54  			name: "no load",
    55  			q: func() *config.TestGroupQueue {
    56  				var q config.TestGroupQueue
    57  				groups := []*configpb.TestGroup{
    58  					{
    59  						Name: "foo",
    60  					},
    61  					{
    62  						Name: "bar",
    63  					},
    64  				}
    65  				q.Init(logrus.New(), groups, next)
    66  				return &q
    67  			}(),
    68  			wantCurrent: map[string]time.Time{
    69  				"foo": next,
    70  				"bar": next,
    71  			},
    72  		},
    73  		{
    74  			name: "load empty",
    75  			q: func() *config.TestGroupQueue {
    76  				var q config.TestGroupQueue
    77  				groups := []*configpb.TestGroup{
    78  					{
    79  						Name: "foo",
    80  					},
    81  					{
    82  						Name: "bar",
    83  					},
    84  				}
    85  				q.Init(logrus.New(), groups, next)
    86  				return &q
    87  			}(),
    88  			ticks: []time.Time{now},
    89  			wantCurrent: map[string]time.Time{
    90  				"foo": next,
    91  				"bar": next,
    92  			},
    93  		},
    94  		{
    95  			name: "load",
    96  			q: func() *config.TestGroupQueue {
    97  				var q config.TestGroupQueue
    98  				groups := []*configpb.TestGroup{
    99  					{
   100  						Name: "keep-next",
   101  					},
   102  					{
   103  						Name: "bump-to-now",
   104  					},
   105  				}
   106  				q.Init(logrus.New(), groups, next)
   107  				return &q
   108  			}(),
   109  			ticks: []time.Time{now},
   110  			currently: fake.Object{
   111  				Data: func() string {
   112  					saved := map[string]time.Time{
   113  						"keep-next":   later,
   114  						"bump-to-now": now,
   115  						"ignore-old":  now,
   116  					}
   117  					buf, err := json.Marshal(saved)
   118  					if err != nil {
   119  						t.Fatalf("Failed to marshal: %v", err)
   120  					}
   121  					return string(buf)
   122  				}(),
   123  				Attrs: &storage.ReaderObjectAttrs{},
   124  			},
   125  			wantCurrent: map[string]time.Time{
   126  				"keep-next":   next,
   127  				"bump-to-now": now,
   128  			},
   129  		},
   130  		{
   131  			name: "load err",
   132  			q: func() *config.TestGroupQueue {
   133  				var q config.TestGroupQueue
   134  				groups := []*configpb.TestGroup{
   135  					{
   136  						Name: "keep-next",
   137  					},
   138  					{
   139  						Name: "would-bump-to-now-if-read",
   140  					},
   141  				}
   142  				q.Init(logrus.New(), groups, next)
   143  				return &q
   144  			}(),
   145  			ticks: []time.Time{now},
   146  			currently: fake.Object{
   147  				Data: func() string {
   148  					saved := map[string]time.Time{
   149  						"keep-next":                 later,
   150  						"would-bump-to-now-if-read": now,
   151  					}
   152  					buf, err := json.Marshal(saved)
   153  					if err != nil {
   154  						t.Fatalf("Failed to marshal: %v", err)
   155  					}
   156  					return string(buf)
   157  				}(),
   158  				Attrs:   &storage.ReaderObjectAttrs{},
   159  				OpenErr: errors.New("fake open error"),
   160  			},
   161  			wantCurrent: map[string]time.Time{
   162  				"keep-next":                 next,
   163  				"would-bump-to-now-if-read": next,
   164  			},
   165  		},
   166  		{
   167  			name: "load and save",
   168  			q: func() *config.TestGroupQueue {
   169  				var q config.TestGroupQueue
   170  				groups := []*configpb.TestGroup{
   171  					{
   172  						Name: "keep-next",
   173  					},
   174  					{
   175  						Name: "bump-to-now",
   176  					},
   177  				}
   178  				q.Init(logrus.New(), groups, next)
   179  				return &q
   180  			}(),
   181  			ticks: []time.Time{now, now, now},
   182  			currently: fake.Object{
   183  				Data: func() string {
   184  					saved := map[string]time.Time{
   185  						"keep-next":   later,
   186  						"bump-to-now": now,
   187  						"ignore-old":  now,
   188  					}
   189  					buf, err := json.Marshal(saved)
   190  					if err != nil {
   191  						t.Fatalf("Failed to marshal: %v", err)
   192  					}
   193  					return string(buf)
   194  				}(),
   195  				Attrs: &storage.ReaderObjectAttrs{},
   196  			},
   197  			wantCurrent: map[string]time.Time{
   198  				"keep-next":   next,
   199  				"bump-to-now": now,
   200  			},
   201  			wantBuf: func() string {
   202  				saved := map[string]time.Time{
   203  					"keep-next":   next,
   204  					"bump-to-now": now,
   205  				}
   206  				buf, err := json.MarshalIndent(saved, "", "  ")
   207  				if err != nil {
   208  					t.Fatalf("Failed to marshal: %v", err)
   209  				}
   210  				return string(buf)
   211  			}(),
   212  		},
   213  	}
   214  
   215  	path, err := gcs.NewPath("gs://fake-bucket/path/to/whatever")
   216  	if err != nil {
   217  		t.Fatalf("NewPath(): %v", err)
   218  	}
   219  
   220  	for _, tc := range cases {
   221  		t.Run(tc.name, func(t *testing.T) {
   222  			client := fake.UploadClient{
   223  				Uploader: fake.Uploader{},
   224  				Client: fake.Client{
   225  					Opener: fake.Opener{
   226  						Paths: map[gcs.Path]fake.Object{
   227  							*path: tc.currently,
   228  						},
   229  					},
   230  				},
   231  			}
   232  			ch := make(chan time.Time)
   233  			fix := FixPersistent(logrus.WithField("name", tc.name), client, *path, ch)
   234  			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   235  			defer cancel()
   236  			go func() {
   237  				for _, tick := range tc.ticks {
   238  					ch <- tick
   239  				}
   240  				cancel()
   241  			}()
   242  			if err := fix(ctx, nil, tc.q, nil); !errors.Is(err, context.Canceled) {
   243  				t.Errorf("fix() returned unexpected error: %v", err)
   244  			} else {
   245  				got := tc.q.Current()
   246  				if diff := cmp.Diff(tc.wantCurrent, got); diff != "" {
   247  					t.Errorf("fix() got unexpected current diff (-want +got):\n%s", diff)
   248  				}
   249  				gotBytes := string(client.Uploader[*path].Buf)
   250  				if diff := cmp.Diff(tc.wantBuf, gotBytes); diff != "" {
   251  					t.Errorf("fix() got unexpected byte diff (-want +got):\n%s", diff)
   252  				}
   253  
   254  			}
   255  		})
   256  	}
   257  }