go.uber.org/cadence@v1.2.9/internal/common/autoscaler/recommender_test.go (about)

     1  // Copyright (c) 2017-2021 Uber Technologies Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package autoscaler
    22  
    23  import "testing"
    24  
    25  func Test_linearRecommender_Recommend(t *testing.T) {
    26  	type fields struct {
    27  		lower        ResourceUnit
    28  		upper        ResourceUnit
    29  		targetUsages Usages
    30  	}
    31  	type args struct {
    32  		currentResource ResourceUnit
    33  		currentUsages   Usages
    34  	}
    35  
    36  	defaultFields := fields{
    37  		lower: 5,
    38  		upper: 15,
    39  		targetUsages: map[UsageType]MilliUsage{
    40  			PollerUtilizationRate: 500,
    41  		},
    42  	}
    43  
    44  	highUpperValue := fields{
    45  		lower: 5,
    46  		upper: 100,
    47  		targetUsages: map[UsageType]MilliUsage{
    48  			PollerUtilizationRate: 500,
    49  		},
    50  	}
    51  
    52  	tests := []struct {
    53  		name   string
    54  		fields fields
    55  		args   args
    56  		want   ResourceUnit
    57  	}{
    58  		{
    59  			name:   "on target usage",
    60  			fields: defaultFields,
    61  			args: args{
    62  				currentResource: 10,
    63  				currentUsages: map[UsageType]MilliUsage{
    64  					PollerUtilizationRate: 500,
    65  				},
    66  			},
    67  			want: ResourceUnit(10),
    68  		},
    69  		{
    70  			name:   "under utilized, scale down",
    71  			fields: defaultFields,
    72  			args: args{
    73  				currentResource: 10,
    74  				currentUsages: map[UsageType]MilliUsage{
    75  					PollerUtilizationRate: 400,
    76  				},
    77  			},
    78  			want: ResourceUnit(8),
    79  		},
    80  		{
    81  			name:   "under utilized, scale down but bounded",
    82  			fields: defaultFields,
    83  			args: args{
    84  				currentResource: 10,
    85  				currentUsages: map[UsageType]MilliUsage{
    86  					PollerUtilizationRate: 200,
    87  				},
    88  			},
    89  			want: ResourceUnit(5),
    90  		},
    91  		{
    92  			name:   "zero utilization, scale down to min",
    93  			fields: defaultFields,
    94  			args: args{
    95  				currentResource: 10,
    96  				currentUsages: map[UsageType]MilliUsage{
    97  					PollerUtilizationRate: 0,
    98  				},
    99  			},
   100  			want: ResourceUnit(5),
   101  		},
   102  		{
   103  			name:   "over utilized, scale up",
   104  			fields: defaultFields,
   105  			args: args{
   106  				currentResource: 10,
   107  				currentUsages: map[UsageType]MilliUsage{
   108  					PollerUtilizationRate: 600,
   109  				},
   110  			},
   111  			want: ResourceUnit(12),
   112  		},
   113  		{
   114  			name:   "over utilized, scale up but bounded",
   115  			fields: defaultFields,
   116  			args: args{
   117  				currentResource: 10,
   118  				currentUsages: map[UsageType]MilliUsage{
   119  					PollerUtilizationRate: 1000,
   120  				},
   121  			},
   122  			want: ResourceUnit(15),
   123  		},
   124  		{
   125  			name:   "over utilized, since we do not how many tasks are in the queue (because poller usage at 100%), scale up to max",
   126  			fields: highUpperValue,
   127  			args: args{
   128  				currentResource: 10,
   129  				currentUsages: map[UsageType]MilliUsage{
   130  					PollerUtilizationRate: 1000,
   131  				},
   132  			},
   133  			want: ResourceUnit(100),
   134  		},
   135  	}
   136  	for _, tt := range tests {
   137  		t.Run(tt.name, func(t *testing.T) {
   138  			l := NewLinearRecommender(tt.fields.lower, tt.fields.upper, tt.fields.targetUsages)
   139  			if got := l.Recommend(tt.args.currentResource, tt.args.currentUsages); got != tt.want {
   140  				t.Errorf("Recommend() = %v, want %v", got, tt.want)
   141  			}
   142  		})
   143  	}
   144  }