...

Source file src/k8s.io/kubernetes/pkg/scheduler/framework/interface_test.go

Documentation: k8s.io/kubernetes/pkg/scheduler/framework

     1  /*
     2  Copyright 2019 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 framework
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	"k8s.io/apimachinery/pkg/util/sets"
    26  )
    27  
    28  var errorStatus = NewStatus(Error, "internal error")
    29  var statusWithErr = AsStatus(errors.New("internal error"))
    30  
    31  func TestStatus(t *testing.T) {
    32  	tests := []struct {
    33  		name              string
    34  		status            *Status
    35  		expectedCode      Code
    36  		expectedMessage   string
    37  		expectedIsSuccess bool
    38  		expectedIsWait    bool
    39  		expectedIsSkip    bool
    40  		expectedAsError   error
    41  	}{
    42  		{
    43  			name:              "success status",
    44  			status:            NewStatus(Success, ""),
    45  			expectedCode:      Success,
    46  			expectedMessage:   "",
    47  			expectedIsSuccess: true,
    48  			expectedIsWait:    false,
    49  			expectedIsSkip:    false,
    50  			expectedAsError:   nil,
    51  		},
    52  		{
    53  			name:              "wait status",
    54  			status:            NewStatus(Wait, ""),
    55  			expectedCode:      Wait,
    56  			expectedMessage:   "",
    57  			expectedIsSuccess: false,
    58  			expectedIsWait:    true,
    59  			expectedIsSkip:    false,
    60  			expectedAsError:   nil,
    61  		},
    62  		{
    63  			name:              "error status",
    64  			status:            NewStatus(Error, "unknown error"),
    65  			expectedCode:      Error,
    66  			expectedMessage:   "unknown error",
    67  			expectedIsSuccess: false,
    68  			expectedIsWait:    false,
    69  			expectedIsSkip:    false,
    70  			expectedAsError:   errors.New("unknown error"),
    71  		},
    72  		{
    73  			name:              "skip status",
    74  			status:            NewStatus(Skip, ""),
    75  			expectedCode:      Skip,
    76  			expectedMessage:   "",
    77  			expectedIsSuccess: false,
    78  			expectedIsWait:    false,
    79  			expectedIsSkip:    true,
    80  			expectedAsError:   nil,
    81  		},
    82  		{
    83  			name:              "nil status",
    84  			status:            nil,
    85  			expectedCode:      Success,
    86  			expectedMessage:   "",
    87  			expectedIsSuccess: true,
    88  			expectedIsSkip:    false,
    89  			expectedAsError:   nil,
    90  		},
    91  	}
    92  
    93  	for _, test := range tests {
    94  		t.Run(test.name, func(t *testing.T) {
    95  			if test.status.Code() != test.expectedCode {
    96  				t.Errorf("expect status.Code() returns %v, but %v", test.expectedCode, test.status.Code())
    97  			}
    98  
    99  			if test.status.Message() != test.expectedMessage {
   100  				t.Errorf("expect status.Message() returns %v, but %v", test.expectedMessage, test.status.Message())
   101  			}
   102  
   103  			if test.status.IsSuccess() != test.expectedIsSuccess {
   104  				t.Errorf("expect status.IsSuccess() returns %v, but %v", test.expectedIsSuccess, test.status.IsSuccess())
   105  			}
   106  
   107  			if test.status.IsWait() != test.expectedIsWait {
   108  				t.Errorf("status.IsWait() returns %v, but want %v", test.status.IsWait(), test.expectedIsWait)
   109  			}
   110  
   111  			if test.status.IsSkip() != test.expectedIsSkip {
   112  				t.Errorf("status.IsSkip() returns %v, but want %v", test.status.IsSkip(), test.expectedIsSkip)
   113  			}
   114  
   115  			if test.status.AsError() == test.expectedAsError {
   116  				return
   117  			}
   118  
   119  			if test.status.AsError().Error() != test.expectedAsError.Error() {
   120  				t.Errorf("expect status.AsError() returns %v, but %v", test.expectedAsError, test.status.AsError())
   121  			}
   122  		})
   123  	}
   124  }
   125  
   126  func TestPreFilterResultMerge(t *testing.T) {
   127  	tests := map[string]struct {
   128  		receiver *PreFilterResult
   129  		in       *PreFilterResult
   130  		want     *PreFilterResult
   131  	}{
   132  		"all nil": {},
   133  		"nil receiver empty input": {
   134  			in:   &PreFilterResult{NodeNames: sets.New[string]()},
   135  			want: &PreFilterResult{NodeNames: sets.New[string]()},
   136  		},
   137  		"empty receiver nil input": {
   138  			receiver: &PreFilterResult{NodeNames: sets.New[string]()},
   139  			want:     &PreFilterResult{NodeNames: sets.New[string]()},
   140  		},
   141  		"empty receiver empty input": {
   142  			receiver: &PreFilterResult{NodeNames: sets.New[string]()},
   143  			in:       &PreFilterResult{NodeNames: sets.New[string]()},
   144  			want:     &PreFilterResult{NodeNames: sets.New[string]()},
   145  		},
   146  		"nil receiver populated input": {
   147  			in:   &PreFilterResult{NodeNames: sets.New("node1")},
   148  			want: &PreFilterResult{NodeNames: sets.New("node1")},
   149  		},
   150  		"empty receiver populated input": {
   151  			receiver: &PreFilterResult{NodeNames: sets.New[string]()},
   152  			in:       &PreFilterResult{NodeNames: sets.New("node1")},
   153  			want:     &PreFilterResult{NodeNames: sets.New[string]()},
   154  		},
   155  
   156  		"populated receiver nil input": {
   157  			receiver: &PreFilterResult{NodeNames: sets.New("node1")},
   158  			want:     &PreFilterResult{NodeNames: sets.New("node1")},
   159  		},
   160  		"populated receiver empty input": {
   161  			receiver: &PreFilterResult{NodeNames: sets.New("node1")},
   162  			in:       &PreFilterResult{NodeNames: sets.New[string]()},
   163  			want:     &PreFilterResult{NodeNames: sets.New[string]()},
   164  		},
   165  		"populated receiver and input": {
   166  			receiver: &PreFilterResult{NodeNames: sets.New("node1", "node2")},
   167  			in:       &PreFilterResult{NodeNames: sets.New("node2", "node3")},
   168  			want:     &PreFilterResult{NodeNames: sets.New("node2")},
   169  		},
   170  	}
   171  	for name, test := range tests {
   172  		t.Run(name, func(t *testing.T) {
   173  			got := test.receiver.Merge(test.in)
   174  			if diff := cmp.Diff(test.want, got); diff != "" {
   175  				t.Errorf("unexpected diff (-want, +got):\n%s", diff)
   176  			}
   177  		})
   178  	}
   179  }
   180  
   181  func TestIsStatusEqual(t *testing.T) {
   182  	tests := []struct {
   183  		name string
   184  		x, y *Status
   185  		want bool
   186  	}{
   187  		{
   188  			name: "two nil should be equal",
   189  			x:    nil,
   190  			y:    nil,
   191  			want: true,
   192  		},
   193  		{
   194  			name: "nil should be equal to success status",
   195  			x:    nil,
   196  			y:    NewStatus(Success),
   197  			want: true,
   198  		},
   199  		{
   200  			name: "nil should not be equal with status except success",
   201  			x:    nil,
   202  			y:    NewStatus(Error, "internal error"),
   203  			want: false,
   204  		},
   205  		{
   206  			name: "one status should be equal to itself",
   207  			x:    errorStatus,
   208  			y:    errorStatus,
   209  			want: true,
   210  		},
   211  		{
   212  			name: "same type statuses without reasons should be equal",
   213  			x:    NewStatus(Success),
   214  			y:    NewStatus(Success),
   215  			want: true,
   216  		},
   217  		{
   218  			name: "statuses with same message should be equal",
   219  			x:    NewStatus(Unschedulable, "unschedulable"),
   220  			y:    NewStatus(Unschedulable, "unschedulable"),
   221  			want: true,
   222  		},
   223  		{
   224  			name: "error statuses with same message should be equal",
   225  			x:    NewStatus(Error, "error"),
   226  			y:    NewStatus(Error, "error"),
   227  			want: true,
   228  		},
   229  		{
   230  			name: "statuses with different reasons should not be equal",
   231  			x:    NewStatus(Unschedulable, "unschedulable"),
   232  			y:    NewStatus(Unschedulable, "unschedulable", "injected filter status"),
   233  			want: false,
   234  		},
   235  		{
   236  			name: "statuses with different codes should not be equal",
   237  			x:    NewStatus(Error, "internal error"),
   238  			y:    NewStatus(Unschedulable, "internal error"),
   239  			want: false,
   240  		},
   241  		{
   242  			name: "wrap error status should be equal with original one",
   243  			x:    statusWithErr,
   244  			y:    AsStatus(fmt.Errorf("error: %w", statusWithErr.AsError())),
   245  			want: true,
   246  		},
   247  		{
   248  			name: "statues with different errors that have the same message shouldn't be equal",
   249  			x:    AsStatus(errors.New("error")),
   250  			y:    AsStatus(errors.New("error")),
   251  			want: false,
   252  		},
   253  	}
   254  	for _, tt := range tests {
   255  		t.Run(tt.name, func(t *testing.T) {
   256  			if got := tt.x.Equal(tt.y); got != tt.want {
   257  				t.Errorf("cmp.Equal() = %v, want %v", got, tt.want)
   258  			}
   259  		})
   260  	}
   261  }
   262  

View as plain text