go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/sync/dispatcher/buffer/options_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 buffer
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	"go.chromium.org/luci/common/retry"
    22  
    23  	. "github.com/smartystreets/goconvey/convey"
    24  	. "go.chromium.org/luci/common/testing/assertions"
    25  )
    26  
    27  func TestOptionValidationGood(t *testing.T) {
    28  	var goodOptions = []struct {
    29  		name     string
    30  		options  Options
    31  		expected Options
    32  	}{
    33  		{
    34  			name:     "minimal",
    35  			options:  Options{},
    36  			expected: Defaults,
    37  		},
    38  
    39  		{
    40  			name: "full",
    41  			options: Options{
    42  				MaxLeases:     2,
    43  				BatchItemsMax: 99,
    44  				BatchSizeMax:  10,
    45  				BatchAgeMax:   2 * time.Minute,
    46  				FullBehavior:  &DropOldestBatch{MaxLiveItems: 400, MaxLiveSize: -1},
    47  				Retry:         retry.None,
    48  			},
    49  			expected: Options{
    50  				MaxLeases:     2,
    51  				BatchItemsMax: 99,
    52  				BatchSizeMax:  10,
    53  				BatchAgeMax:   2 * time.Minute,
    54  				FullBehavior:  &DropOldestBatch{MaxLiveItems: 400, MaxLiveSize: -1},
    55  				Retry:         retry.None,
    56  			},
    57  		},
    58  
    59  		{
    60  			name: "BatchItemsMax == -1 OK",
    61  			options: Options{
    62  				MaxLeases:     Defaults.MaxLeases,
    63  				BatchItemsMax: -1,
    64  				BatchSizeMax:  Defaults.BatchSizeMax,
    65  				BatchAgeMax:   Defaults.BatchAgeMax,
    66  				FullBehavior:  Defaults.FullBehavior,
    67  				Retry:         Defaults.Retry,
    68  			},
    69  			expected: Options{
    70  				MaxLeases:     Defaults.MaxLeases,
    71  				BatchItemsMax: -1,
    72  				BatchSizeMax:  Defaults.BatchSizeMax,
    73  				BatchAgeMax:   Defaults.BatchAgeMax,
    74  				FullBehavior:  Defaults.FullBehavior,
    75  				Retry:         Defaults.Retry,
    76  			},
    77  		},
    78  
    79  		{
    80  			name: "BatchSizeMax == 0 -> default",
    81  			options: Options{
    82  				MaxLeases:     Defaults.MaxLeases,
    83  				BatchItemsMax: -1,
    84  				BatchAgeMax:   Defaults.BatchAgeMax,
    85  				FullBehavior:  Defaults.FullBehavior,
    86  				Retry:         Defaults.Retry,
    87  			},
    88  			expected: Options{
    89  				MaxLeases:     Defaults.MaxLeases,
    90  				BatchItemsMax: -1,
    91  				BatchSizeMax:  Defaults.BatchSizeMax,
    92  				BatchAgeMax:   Defaults.BatchAgeMax,
    93  				FullBehavior:  Defaults.FullBehavior,
    94  				Retry:         Defaults.Retry,
    95  			},
    96  		},
    97  
    98  		{
    99  			name: "BatchSizeMax == 0 w/ BlockNewItems -> default",
   100  			options: Options{
   101  				MaxLeases:     Defaults.MaxLeases,
   102  				BatchItemsMax: Defaults.BatchItemsMax,
   103  				BatchAgeMax:   Defaults.BatchAgeMax,
   104  				FullBehavior:  &BlockNewItems{},
   105  				Retry:         Defaults.Retry,
   106  			},
   107  			expected: Options{
   108  				MaxLeases:     Defaults.MaxLeases,
   109  				BatchItemsMax: Defaults.BatchItemsMax,
   110  				BatchSizeMax:  Defaults.BatchSizeMax,
   111  				BatchAgeMax:   Defaults.BatchAgeMax,
   112  				FullBehavior:  &BlockNewItems{MaxItems: 1000, MaxSize: -1},
   113  				Retry:         Defaults.Retry,
   114  			},
   115  		},
   116  
   117  		{
   118  			name: "BatchSizeMax > 0 -> default sizer func",
   119  			options: Options{
   120  				MaxLeases:     Defaults.MaxLeases,
   121  				BatchItemsMax: -1,
   122  				BatchSizeMax:  10000,
   123  				BatchAgeMax:   Defaults.BatchAgeMax,
   124  				FullBehavior:  Defaults.FullBehavior,
   125  				Retry:         Defaults.Retry,
   126  			},
   127  			expected: Options{
   128  				MaxLeases:     Defaults.MaxLeases,
   129  				BatchItemsMax: -1,
   130  				BatchSizeMax:  10000,
   131  				BatchAgeMax:   Defaults.BatchAgeMax,
   132  				FullBehavior:  Defaults.FullBehavior,
   133  				Retry:         Defaults.Retry,
   134  			},
   135  		},
   136  
   137  		{
   138  			name: "DropOldestBatch default",
   139  			options: Options{
   140  				MaxLeases:     Defaults.MaxLeases,
   141  				BatchItemsMax: Defaults.BatchItemsMax,
   142  				BatchSizeMax:  Defaults.BatchSizeMax,
   143  				BatchAgeMax:   Defaults.BatchAgeMax,
   144  				FullBehavior:  &DropOldestBatch{},
   145  				Retry:         Defaults.Retry,
   146  			},
   147  			expected: Options{
   148  				MaxLeases:     Defaults.MaxLeases,
   149  				BatchItemsMax: Defaults.BatchItemsMax,
   150  				BatchSizeMax:  Defaults.BatchSizeMax,
   151  				BatchAgeMax:   Defaults.BatchAgeMax,
   152  				FullBehavior:  &DropOldestBatch{MaxLiveItems: 1000, MaxLiveSize: -1},
   153  				Retry:         Defaults.Retry,
   154  			},
   155  		},
   156  
   157  		{
   158  			name: "DropOldestBatch default large BatchItemsMax",
   159  			options: Options{
   160  				MaxLeases:     Defaults.MaxLeases,
   161  				BatchItemsMax: 2000,
   162  				BatchSizeMax:  Defaults.BatchSizeMax,
   163  				BatchAgeMax:   Defaults.BatchAgeMax,
   164  				FullBehavior:  &DropOldestBatch{},
   165  				Retry:         Defaults.Retry,
   166  			},
   167  			expected: Options{
   168  				MaxLeases:     Defaults.MaxLeases,
   169  				BatchItemsMax: 2000,
   170  				BatchSizeMax:  Defaults.BatchSizeMax,
   171  				BatchAgeMax:   Defaults.BatchAgeMax,
   172  				FullBehavior:  &DropOldestBatch{MaxLiveItems: 2000, MaxLiveSize: -1},
   173  				Retry:         Defaults.Retry,
   174  			},
   175  		},
   176  
   177  		{
   178  			name: "BlockNewItems default",
   179  			options: Options{
   180  				MaxLeases:     Defaults.MaxLeases,
   181  				BatchItemsMax: Defaults.BatchItemsMax,
   182  				BatchSizeMax:  Defaults.BatchSizeMax,
   183  				BatchAgeMax:   Defaults.BatchAgeMax,
   184  				FullBehavior:  &BlockNewItems{},
   185  				Retry:         Defaults.Retry,
   186  			},
   187  			expected: Options{
   188  				MaxLeases:     Defaults.MaxLeases,
   189  				BatchItemsMax: Defaults.BatchItemsMax,
   190  				BatchSizeMax:  Defaults.BatchSizeMax,
   191  				BatchAgeMax:   Defaults.BatchAgeMax,
   192  				FullBehavior:  &BlockNewItems{MaxItems: 1000, MaxSize: -1},
   193  				Retry:         Defaults.Retry,
   194  			},
   195  		},
   196  
   197  		{
   198  			name: "BlockNewItems size only",
   199  			options: Options{
   200  				MaxLeases:     Defaults.MaxLeases,
   201  				BatchItemsMax: -1,
   202  				BatchSizeMax:  10000,
   203  				BatchAgeMax:   Defaults.BatchAgeMax,
   204  				FullBehavior:  &BlockNewItems{},
   205  				Retry:         Defaults.Retry,
   206  			},
   207  			expected: Options{
   208  				MaxLeases:     Defaults.MaxLeases,
   209  				BatchItemsMax: -1,
   210  				BatchSizeMax:  10000,
   211  				BatchAgeMax:   Defaults.BatchAgeMax,
   212  				FullBehavior:  &BlockNewItems{MaxItems: -1, MaxSize: 50000},
   213  				Retry:         Defaults.Retry,
   214  			},
   215  		},
   216  
   217  		{
   218  			name: "BlockNewItems default large BatchItemsMax",
   219  			options: Options{
   220  				MaxLeases:     Defaults.MaxLeases,
   221  				BatchItemsMax: 2000,
   222  				BatchSizeMax:  Defaults.BatchSizeMax,
   223  				BatchAgeMax:   Defaults.BatchAgeMax,
   224  				FullBehavior:  &BlockNewItems{},
   225  				Retry:         Defaults.Retry,
   226  			},
   227  			expected: Options{
   228  				MaxLeases:     Defaults.MaxLeases,
   229  				BatchItemsMax: 2000,
   230  				BatchSizeMax:  Defaults.BatchSizeMax,
   231  				BatchAgeMax:   Defaults.BatchAgeMax,
   232  				FullBehavior:  &BlockNewItems{MaxItems: 2000, MaxSize: -1},
   233  				Retry:         Defaults.Retry,
   234  			},
   235  		},
   236  	}
   237  
   238  	Convey(`test good option groups`, t, func() {
   239  		for _, options := range goodOptions {
   240  			Convey(options.name, func() {
   241  				myOptions := options.options
   242  				expect := options.expected
   243  
   244  				So(myOptions.normalize(), ShouldBeNil)
   245  
   246  				// ShouldResemble doesn't like function pointers, apparently, so
   247  				// explicitly compare the Retry field.
   248  				So(myOptions.Retry, ShouldEqual, expect.Retry)
   249  				myOptions.Retry = nil
   250  				expect.Retry = nil
   251  
   252  				So(myOptions, ShouldResemble, expect)
   253  			})
   254  		}
   255  	})
   256  }
   257  
   258  func TestOptionValidationBad(t *testing.T) {
   259  	var badOptions = []struct {
   260  		name     string
   261  		options  Options
   262  		expected string
   263  	}{
   264  		{
   265  			"MaxLeases",
   266  			Options{
   267  				MaxLeases: -1,
   268  			},
   269  			"MaxLeases must be",
   270  		},
   271  
   272  		{
   273  			"BatchItemsMax",
   274  			Options{
   275  				BatchItemsMax: -2,
   276  			},
   277  			"BatchItemsMax must be",
   278  		},
   279  
   280  		{
   281  			"BatchSizeMax",
   282  			Options{
   283  				BatchSizeMax: -2,
   284  			},
   285  			"BatchSizeMax must be",
   286  		},
   287  
   288  		{
   289  			"BatchAgeMax",
   290  			Options{
   291  				BatchAgeMax: -time.Minute,
   292  			},
   293  			"BatchAgeMax must be",
   294  		},
   295  
   296  		{
   297  			"FIFO",
   298  			Options{
   299  				MaxLeases: 10,
   300  				FIFO:      true,
   301  			},
   302  			"FIFO is true, but MaxLeases",
   303  		},
   304  
   305  		{
   306  			"DropOldestBatch.MaxLiveItems < -1",
   307  			Options{
   308  				FullBehavior: &DropOldestBatch{MaxLiveItems: -2},
   309  			},
   310  			"DropOldestBatch.MaxLiveItems must be",
   311  		},
   312  
   313  		{
   314  			"DropOldestBatch.MaxLiveSize < -1",
   315  			Options{
   316  				FullBehavior: &DropOldestBatch{MaxLiveSize: -2},
   317  			},
   318  			"DropOldestBatch.MaxLiveSize must be",
   319  		},
   320  
   321  		{
   322  			"DropOldestBatch.MaxLiveItems == DropOldestBatch.MaxLiveSize == -1",
   323  			Options{
   324  				FullBehavior: &DropOldestBatch{MaxLiveItems: -1, MaxLiveSize: -1},
   325  			},
   326  			"DropOldestBatch must have one of",
   327  		},
   328  
   329  		{
   330  			"DropOldestBatch.MaxLiveSize > 0 && BatchSizeMax == -1",
   331  			Options{
   332  				FullBehavior: &DropOldestBatch{MaxLiveSize: 100},
   333  			},
   334  			"DropOldestBatch.MaxLiveSize may only be set",
   335  		},
   336  
   337  		{
   338  			"BlockNewItems.MaxItems < -1",
   339  			Options{
   340  				FullBehavior: &BlockNewItems{MaxItems: -2},
   341  			},
   342  			"BlockNewItems.MaxItems must be",
   343  		},
   344  
   345  		{
   346  			"BlockNewItems.MaxSize < -1",
   347  			Options{
   348  				FullBehavior: &BlockNewItems{MaxSize: -2},
   349  			},
   350  			"BlockNewItems.MaxSize must be",
   351  		},
   352  
   353  		{
   354  			"BlockNewItems.MaxItems == BlockNewItems.MaxSize == -1",
   355  			Options{
   356  				FullBehavior: &BlockNewItems{MaxItems: -1, MaxSize: -1},
   357  			},
   358  			"BlockNewItems must have one of",
   359  		},
   360  
   361  		{
   362  			"BlockNewItems.MaxSize > 0 && BatchSizeMax == -1",
   363  			Options{
   364  				FullBehavior: &BlockNewItems{MaxSize: 100},
   365  			},
   366  			"BlockNewItems.MaxSize may only be set",
   367  		},
   368  	}
   369  
   370  	Convey(`test bad option groups`, t, func() {
   371  		for _, options := range badOptions {
   372  			Convey(options.name, func() {
   373  				myOptions := options.options
   374  				So(myOptions.normalize(), ShouldErrLike, options.expected)
   375  			})
   376  		}
   377  	})
   378  }