go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/gce/api/config/v1/amount_test.go (about)

     1  // Copyright 2019 The LUCI Authors.
     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 config
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  	"time"
    21  
    22  	"google.golang.org/genproto/googleapis/type/dayofweek"
    23  
    24  	"go.chromium.org/luci/config/validation"
    25  
    26  	. "github.com/smartystreets/goconvey/convey"
    27  	. "go.chromium.org/luci/common/testing/assertions"
    28  )
    29  
    30  func TestAmount(t *testing.T) {
    31  	t.Parallel()
    32  
    33  	Convey("getAmount", t, func() {
    34  		now := time.Time{}
    35  		So(now.Weekday(), ShouldEqual, time.Monday)
    36  		So(now.Hour(), ShouldEqual, 0)
    37  
    38  		Convey("min", func() {
    39  			a := &Amount{
    40  				Min: 1,
    41  				Max: 3,
    42  			}
    43  			n, err := a.getAmount(0, now)
    44  			So(err, ShouldBeNil)
    45  			So(n, ShouldEqual, 1)
    46  		})
    47  
    48  		Convey("max", func() {
    49  			a := &Amount{
    50  				Min: 1,
    51  				Max: 3,
    52  			}
    53  			n, err := a.getAmount(4, now)
    54  			So(err, ShouldBeNil)
    55  			So(n, ShouldEqual, 3)
    56  		})
    57  
    58  		Convey("proposed", func() {
    59  			a := &Amount{
    60  				Min: 1,
    61  				Max: 3,
    62  			}
    63  			n, err := a.getAmount(2, now)
    64  			So(err, ShouldBeNil)
    65  			So(n, ShouldEqual, 2)
    66  		})
    67  
    68  		Convey("equal", func() {
    69  			a := &Amount{
    70  				Min: 2,
    71  				Max: 2,
    72  			}
    73  			n, err := a.getAmount(2, now)
    74  			So(err, ShouldBeNil)
    75  			So(n, ShouldEqual, 2)
    76  		})
    77  
    78  		Convey("schedule", func() {
    79  			a := &Amount{
    80  				Min: 1,
    81  				Max: 1,
    82  				Change: []*Schedule{
    83  					{
    84  						Min: 2,
    85  						Max: 2,
    86  						Length: &TimePeriod{
    87  							Time: &TimePeriod_Duration{
    88  								Duration: "2h",
    89  							},
    90  						},
    91  						Start: &TimeOfDay{
    92  							Day:  dayofweek.DayOfWeek_SUNDAY,
    93  							Time: "23:00",
    94  						},
    95  					},
    96  				},
    97  			}
    98  			n, err := a.getAmount(5, now)
    99  			So(err, ShouldBeNil)
   100  			So(n, ShouldEqual, 2)
   101  
   102  			n, err = a.getAmount(5, now.Add(time.Minute*59))
   103  			So(err, ShouldBeNil)
   104  			So(n, ShouldEqual, 2)
   105  
   106  			n, err = a.getAmount(5, now.Add(time.Hour))
   107  			So(err, ShouldBeNil)
   108  			So(n, ShouldEqual, 1)
   109  
   110  			n, err = a.getAmount(5, now.Add(time.Hour*-1))
   111  			So(err, ShouldBeNil)
   112  			So(n, ShouldEqual, 2)
   113  
   114  			n, err = a.getAmount(5, now.Add(time.Minute*-61))
   115  			So(err, ShouldBeNil)
   116  			So(n, ShouldEqual, 1)
   117  		})
   118  
   119  		Convey("schedules", func() {
   120  			a := &Amount{
   121  				Min: 1,
   122  				Max: 1,
   123  				Change: []*Schedule{
   124  					{
   125  						Min: 2,
   126  						Max: 2,
   127  						Length: &TimePeriod{
   128  							Time: &TimePeriod_Duration{
   129  								Duration: "2h",
   130  							},
   131  						},
   132  						Start: &TimeOfDay{
   133  							Day:  dayofweek.DayOfWeek_SUNDAY,
   134  							Time: "23:00",
   135  						},
   136  					},
   137  					{
   138  						Min: 3,
   139  						Max: 3,
   140  						Length: &TimePeriod{
   141  							Time: &TimePeriod_Duration{
   142  								Duration: "1m",
   143  							},
   144  						},
   145  						Start: &TimeOfDay{
   146  							Day:  dayofweek.DayOfWeek_MONDAY,
   147  							Time: "1:00",
   148  						},
   149  					},
   150  				},
   151  			}
   152  			n, err := a.getAmount(5, now)
   153  			So(err, ShouldBeNil)
   154  			So(n, ShouldEqual, 2)
   155  
   156  			n, err = a.getAmount(5, now.Add(time.Minute*59))
   157  			So(err, ShouldBeNil)
   158  			So(n, ShouldEqual, 2)
   159  
   160  			n, err = a.getAmount(5, now.Add(time.Hour))
   161  			So(err, ShouldBeNil)
   162  			So(n, ShouldEqual, 3)
   163  
   164  			n, err = a.getAmount(5, now.Add(time.Minute*61))
   165  			So(err, ShouldBeNil)
   166  			So(n, ShouldEqual, 1)
   167  		})
   168  	})
   169  
   170  	Convey("Validate", t, func() {
   171  		c := &validation.Context{Context: context.Background()}
   172  
   173  		Convey("invalid", func() {
   174  			Convey("min", func() {
   175  				a := &Amount{
   176  					Min: -1,
   177  				}
   178  				a.Validate(c)
   179  				errs := c.Finalize().(*validation.Error).Errors
   180  				So(errs, ShouldContainErr, "minimum amount must be non-negative")
   181  			})
   182  
   183  			Convey("max", func() {
   184  				a := &Amount{
   185  					Max: -1,
   186  				}
   187  				a.Validate(c)
   188  				errs := c.Finalize().(*validation.Error).Errors
   189  				So(errs, ShouldContainErr, "maximum amount must be non-negative")
   190  			})
   191  
   192  			Convey("min > max", func() {
   193  				a := &Amount{
   194  					Min: 2,
   195  					Max: 1,
   196  				}
   197  				a.Validate(c)
   198  				errs := c.Finalize().(*validation.Error).Errors
   199  				So(errs, ShouldContainErr, "minimum amount must not exceed maximum amount")
   200  			})
   201  
   202  			Convey("schedule", func() {
   203  				Convey("empty", func() {
   204  					a := &Amount{
   205  						Change: []*Schedule{
   206  							{},
   207  						},
   208  					}
   209  					a.Validate(c)
   210  					errs := c.Finalize().(*validation.Error).Errors
   211  					So(errs, ShouldContainErr, "duration or seconds is required")
   212  					So(errs, ShouldContainErr, "time must match regex")
   213  				})
   214  
   215  				Convey("conflict", func() {
   216  					Convey("same day", func() {
   217  						a := &Amount{
   218  							Change: []*Schedule{
   219  								{
   220  									Length: &TimePeriod{
   221  										Time: &TimePeriod_Duration{
   222  											Duration: "2h",
   223  										},
   224  									},
   225  									Start: &TimeOfDay{
   226  										Day:  dayofweek.DayOfWeek_WEDNESDAY,
   227  										Time: "1:00",
   228  									},
   229  								},
   230  								{
   231  									Start: &TimeOfDay{
   232  										Day:  dayofweek.DayOfWeek_WEDNESDAY,
   233  										Time: "2:59",
   234  									},
   235  								},
   236  							},
   237  						}
   238  						a.Validate(c)
   239  						errs := c.Finalize().(*validation.Error).Errors
   240  						So(errs, ShouldContainErr, "start time is before")
   241  					})
   242  
   243  					Convey("different day", func() {
   244  						a := &Amount{
   245  							Change: []*Schedule{
   246  								{
   247  									Length: &TimePeriod{
   248  										Time: &TimePeriod_Duration{
   249  											Duration: "48h",
   250  										},
   251  									},
   252  									Start: &TimeOfDay{
   253  										Day:  dayofweek.DayOfWeek_WEDNESDAY,
   254  										Time: "1:00",
   255  									},
   256  								},
   257  								{
   258  									Start: &TimeOfDay{
   259  										Day:  dayofweek.DayOfWeek_THURSDAY,
   260  										Time: "1:00",
   261  									},
   262  								},
   263  							},
   264  						}
   265  						a.Validate(c)
   266  						errs := c.Finalize().(*validation.Error).Errors
   267  						So(errs, ShouldContainErr, "start time is before")
   268  					})
   269  
   270  					Convey("different week", func() {
   271  						a := &Amount{
   272  							Change: []*Schedule{
   273  								{
   274  									Length: &TimePeriod{
   275  										Time: &TimePeriod_Duration{
   276  											Duration: "6d",
   277  										},
   278  									},
   279  									Start: &TimeOfDay{
   280  										Day:  dayofweek.DayOfWeek_TUESDAY,
   281  										Time: "1:00",
   282  									},
   283  								},
   284  								{
   285  									Start: &TimeOfDay{
   286  										Day:  dayofweek.DayOfWeek_MONDAY,
   287  										Time: "0:59",
   288  									},
   289  								},
   290  							},
   291  						}
   292  						a.Validate(c)
   293  						errs := c.Finalize().(*validation.Error).Errors
   294  						So(errs, ShouldContainErr, "start time is before")
   295  					})
   296  				})
   297  			})
   298  		})
   299  
   300  		Convey("valid", func() {
   301  			Convey("empty", func() {
   302  				a := &Amount{}
   303  				a.Validate(c)
   304  				So(c.Finalize(), ShouldBeNil)
   305  			})
   306  
   307  			Convey("non-empty", func() {
   308  				a := &Amount{
   309  					Min: 1,
   310  					Max: 1,
   311  				}
   312  				a.Validate(c)
   313  				So(c.Finalize(), ShouldBeNil)
   314  			})
   315  
   316  			Convey("schedule", func() {
   317  				Convey("empty", func() {
   318  					a := &Amount{
   319  						Change: []*Schedule{},
   320  					}
   321  					a.Validate(c)
   322  					So(c.Finalize(), ShouldBeNil)
   323  				})
   324  
   325  				Convey("same day", func() {
   326  					a := &Amount{
   327  						Change: []*Schedule{
   328  							{
   329  								Length: &TimePeriod{
   330  									Time: &TimePeriod_Duration{
   331  										Duration: "2h",
   332  									},
   333  								},
   334  								Start: &TimeOfDay{
   335  									Day:  dayofweek.DayOfWeek_WEDNESDAY,
   336  									Time: "1:00",
   337  								},
   338  							},
   339  							{
   340  								Length: &TimePeriod{
   341  									Time: &TimePeriod_Duration{
   342  										Duration: "2h",
   343  									},
   344  								},
   345  								Start: &TimeOfDay{
   346  									Day:  dayofweek.DayOfWeek_WEDNESDAY,
   347  									Time: "3:00",
   348  								},
   349  							},
   350  						},
   351  					}
   352  					a.Validate(c)
   353  					So(c.Finalize(), ShouldBeNil)
   354  				})
   355  
   356  				Convey("different day", func() {
   357  					a := &Amount{
   358  						Change: []*Schedule{
   359  							{
   360  								Length: &TimePeriod{
   361  									Time: &TimePeriod_Duration{
   362  										Duration: "48h",
   363  									},
   364  								},
   365  								Start: &TimeOfDay{
   366  									Day:  dayofweek.DayOfWeek_WEDNESDAY,
   367  									Time: "1:00",
   368  								},
   369  							},
   370  							{
   371  								Length: &TimePeriod{
   372  									Time: &TimePeriod_Duration{
   373  										Duration: "48h",
   374  									},
   375  								},
   376  								Start: &TimeOfDay{
   377  									Day:  dayofweek.DayOfWeek_FRIDAY,
   378  									Time: "1:00",
   379  								},
   380  							},
   381  						},
   382  					}
   383  					a.Validate(c)
   384  					So(c.Finalize(), ShouldBeNil)
   385  				})
   386  
   387  				Convey("different week", func() {
   388  					a := &Amount{
   389  						Change: []*Schedule{
   390  							{
   391  								Length: &TimePeriod{
   392  									Time: &TimePeriod_Duration{
   393  										Duration: "6d",
   394  									},
   395  								},
   396  								Start: &TimeOfDay{
   397  									Day:      dayofweek.DayOfWeek_TUESDAY,
   398  									Location: "America/Los_Angeles",
   399  									Time:     "1:00",
   400  								},
   401  							},
   402  							{
   403  								Length: &TimePeriod{
   404  									Time: &TimePeriod_Duration{
   405  										Duration: "2h",
   406  									},
   407  								},
   408  								Start: &TimeOfDay{
   409  									Day:      dayofweek.DayOfWeek_MONDAY,
   410  									Location: "America/Los_Angeles",
   411  									Time:     "1:00",
   412  								},
   413  							},
   414  						},
   415  					}
   416  					a.Validate(c)
   417  					So(c.Finalize(), ShouldBeNil)
   418  				})
   419  
   420  				Convey("different location", func() {
   421  					a := &Amount{
   422  						Change: []*Schedule{
   423  							{
   424  								Length: &TimePeriod{
   425  									Time: &TimePeriod_Duration{
   426  										Duration: "1h",
   427  									},
   428  								},
   429  								Start: &TimeOfDay{
   430  									Day:      dayofweek.DayOfWeek_MONDAY,
   431  									Location: "America/Los_Angeles",
   432  									Time:     "23:00",
   433  								},
   434  							},
   435  							{
   436  								Length: &TimePeriod{
   437  									Time: &TimePeriod_Duration{
   438  										Duration: "6h",
   439  									},
   440  								},
   441  								Start: &TimeOfDay{
   442  									Day:  dayofweek.DayOfWeek_TUESDAY,
   443  									Time: "1:00",
   444  								},
   445  							},
   446  						},
   447  					}
   448  					a.Validate(c)
   449  					So(c.Finalize(), ShouldBeNil)
   450  				})
   451  			})
   452  		})
   453  	})
   454  }