github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/prow/config/tide_test.go (about)

     1  /*
     2  Copyright 2017 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 config
    18  
    19  import (
    20  	"reflect"
    21  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"k8s.io/apimachinery/pkg/util/sets"
    26  	"k8s.io/test-infra/prow/github"
    27  )
    28  
    29  var testQuery = TideQuery{
    30  	Orgs:                   []string{"org"},
    31  	Repos:                  []string{"k/k", "k/t-i"},
    32  	Labels:                 []string{"lgtm", "approved"},
    33  	MissingLabels:          []string{"foo"},
    34  	Milestone:              "milestone",
    35  	ReviewApprovedRequired: true,
    36  }
    37  
    38  func TestTideQuery(t *testing.T) {
    39  	q := " " + testQuery.Query() + " "
    40  	checkTok := func(tok string) {
    41  		if !strings.Contains(q, " "+tok+" ") {
    42  			t.Errorf("Expected query to contain \"%s\", got \"%s\"", tok, q)
    43  		}
    44  	}
    45  
    46  	checkTok("is:pr")
    47  	checkTok("state:open")
    48  	checkTok("org:\"org\"")
    49  	checkTok("repo:\"k/k\"")
    50  	checkTok("repo:\"k/t-i\"")
    51  	checkTok("label:\"lgtm\"")
    52  	checkTok("label:\"approved\"")
    53  	checkTok("-label:\"foo\"")
    54  	checkTok("milestone:\"milestone\"")
    55  	checkTok("review:approved")
    56  }
    57  
    58  func TestAllPRsSince(t *testing.T) {
    59  	testTime, err := time.Parse(time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")
    60  	if err != nil {
    61  		t.Fatalf("Error parsing test time string: %v.", err)
    62  	}
    63  	testTimeOld, err := time.Parse(time.UnixDate, "Sat Mar  7 11:06:39 PST 1915")
    64  	if err != nil {
    65  		t.Fatalf("Error parsing test time string: %v.", err)
    66  	}
    67  	var q string
    68  	checkTok := func(tok string, shouldExist bool) {
    69  		if shouldExist == strings.Contains(q, " "+tok+" ") {
    70  			return
    71  		} else if shouldExist {
    72  			t.Errorf("Expected query to contain \"%s\", got \"%s\"", tok, q)
    73  		} else {
    74  			t.Errorf("Expected query to not contain \"%s\", got \"%s\"", tok, q)
    75  
    76  		}
    77  	}
    78  
    79  	queries := TideQueries([]TideQuery{
    80  		testQuery,
    81  		{
    82  			Orgs:   []string{"foo"},
    83  			Repos:  []string{"k/foo"},
    84  			Labels: []string{"lgtm", "mergeable"},
    85  		},
    86  	})
    87  	q = " " + queries.AllPRsSince(testTime) + " "
    88  	checkTok("is:pr", true)
    89  	checkTok("state:open", true)
    90  	checkTok("org:\"org\"", true)
    91  	checkTok("org:\"foo\"", true)
    92  	checkTok("repo:\"k/k\"", true)
    93  	checkTok("repo:\"k/t-i\"", true)
    94  	checkTok("repo:\"k/foo\"", true)
    95  	checkTok("label:\"lgtm\"", false)
    96  	checkTok("label:\"approved\"", false)
    97  	checkTok("label:\"mergeable\"", false)
    98  	checkTok("-label:\"foo\"", false)
    99  	checkTok("milestone:\"milestone\"", false)
   100  	checkTok("review:approved", false)
   101  	checkTok("updated:>=2015-03-07T11:06:39Z", true)
   102  
   103  	// Test that if time is the zero time value, the token is not included.
   104  	q = " " + queries.AllPRsSince(time.Time{}) + " "
   105  	checkTok("updated:>=0001-01-01T00:00:00Z", false)
   106  	// Test that if time is before 1970, the token is not included.
   107  	q = " " + queries.AllPRsSince(testTimeOld) + " "
   108  	checkTok("updated:>=1915-03-07T11:06:39Z", false)
   109  }
   110  
   111  func TestMergeMethod(t *testing.T) {
   112  	ti := &Tide{
   113  		MergeType: map[string]github.PullRequestMergeType{
   114  			"kubernetes/kops":             github.MergeRebase,
   115  			"kubernetes/charts":           github.MergeSquash,
   116  			"helm/charts":                 github.MergeSquash,
   117  			"kubernetes-helm":             github.MergeSquash,
   118  			"kubernetes-helm/chartmuseum": github.MergeMerge,
   119  		},
   120  	}
   121  
   122  	var testcases = []struct {
   123  		org      string
   124  		repo     string
   125  		expected github.PullRequestMergeType
   126  	}{
   127  		{
   128  			"kubernetes",
   129  			"kubernetes",
   130  			github.MergeMerge,
   131  		},
   132  		{
   133  			"kubernetes",
   134  			"kops",
   135  			github.MergeRebase,
   136  		},
   137  		{
   138  			"kubernetes",
   139  			"charts",
   140  			github.MergeSquash,
   141  		},
   142  		{
   143  			"kubernetes-helm",
   144  			"monocular",
   145  			github.MergeSquash,
   146  		},
   147  		{
   148  			"kubernetes-helm",
   149  			"chartmuseum",
   150  			github.MergeMerge,
   151  		},
   152  	}
   153  
   154  	for _, test := range testcases {
   155  		if ti.MergeMethod(test.org, test.repo) != test.expected {
   156  			t.Errorf("Expected merge method %q but got %q for %s/%s", test.expected, ti.MergeMethod(test.org, test.repo), test.org, test.repo)
   157  		}
   158  	}
   159  }
   160  
   161  func TestParseTideContextPolicyOptions(t *testing.T) {
   162  	yes := true
   163  	no := false
   164  	org, repo, branch := "org", "repo", "branch"
   165  	testCases := []struct {
   166  		name     string
   167  		config   TideContextPolicyOptions
   168  		expected TideContextPolicy
   169  	}{
   170  		{
   171  			name: "empty",
   172  		},
   173  		{
   174  			name: "global config",
   175  			config: TideContextPolicyOptions{
   176  				TideContextPolicy: TideContextPolicy{
   177  					FromBranchProtection: &yes,
   178  					SkipUnknownContexts:  &yes,
   179  					RequiredContexts:     []string{"r1"},
   180  					OptionalContexts:     []string{"o1"},
   181  				},
   182  			},
   183  			expected: TideContextPolicy{
   184  				SkipUnknownContexts:  &yes,
   185  				RequiredContexts:     []string{"r1"},
   186  				OptionalContexts:     []string{"o1"},
   187  				FromBranchProtection: &yes,
   188  			},
   189  		},
   190  		{
   191  			name: "org config",
   192  			config: TideContextPolicyOptions{
   193  				TideContextPolicy: TideContextPolicy{
   194  					RequiredContexts:     []string{"r1"},
   195  					OptionalContexts:     []string{"o1"},
   196  					FromBranchProtection: &no,
   197  				},
   198  				Orgs: map[string]TideOrgContextPolicy{
   199  					"org": {
   200  						TideContextPolicy: TideContextPolicy{
   201  							SkipUnknownContexts:  &yes,
   202  							RequiredContexts:     []string{"r2"},
   203  							OptionalContexts:     []string{"o2"},
   204  							FromBranchProtection: &yes,
   205  						},
   206  					},
   207  				},
   208  			},
   209  			expected: TideContextPolicy{
   210  				SkipUnknownContexts:  &yes,
   211  				RequiredContexts:     []string{"r1", "r2"},
   212  				OptionalContexts:     []string{"o1", "o2"},
   213  				FromBranchProtection: &yes,
   214  			},
   215  		},
   216  		{
   217  			name: "repo config",
   218  			config: TideContextPolicyOptions{
   219  				TideContextPolicy: TideContextPolicy{
   220  					RequiredContexts:     []string{"r1"},
   221  					OptionalContexts:     []string{"o1"},
   222  					FromBranchProtection: &no,
   223  				},
   224  				Orgs: map[string]TideOrgContextPolicy{
   225  					"org": {
   226  						TideContextPolicy: TideContextPolicy{
   227  							SkipUnknownContexts:  &no,
   228  							RequiredContexts:     []string{"r2"},
   229  							OptionalContexts:     []string{"o2"},
   230  							FromBranchProtection: &no,
   231  						},
   232  						Repos: map[string]TideRepoContextPolicy{
   233  							"repo": {
   234  								TideContextPolicy: TideContextPolicy{
   235  									SkipUnknownContexts:  &yes,
   236  									RequiredContexts:     []string{"r3"},
   237  									OptionalContexts:     []string{"o3"},
   238  									FromBranchProtection: &yes,
   239  								},
   240  							},
   241  						},
   242  					},
   243  				},
   244  			},
   245  			expected: TideContextPolicy{
   246  				SkipUnknownContexts:  &yes,
   247  				RequiredContexts:     []string{"r1", "r2", "r3"},
   248  				OptionalContexts:     []string{"o1", "o2", "o3"},
   249  				FromBranchProtection: &yes,
   250  			},
   251  		},
   252  		{
   253  			name: "branch config",
   254  			config: TideContextPolicyOptions{
   255  				TideContextPolicy: TideContextPolicy{
   256  					RequiredContexts: []string{"r1"},
   257  					OptionalContexts: []string{"o1"},
   258  				},
   259  				Orgs: map[string]TideOrgContextPolicy{
   260  					"org": {
   261  						TideContextPolicy: TideContextPolicy{
   262  							RequiredContexts: []string{"r2"},
   263  							OptionalContexts: []string{"o2"},
   264  						},
   265  						Repos: map[string]TideRepoContextPolicy{
   266  							"repo": {
   267  								TideContextPolicy: TideContextPolicy{
   268  									RequiredContexts: []string{"r3"},
   269  									OptionalContexts: []string{"o3"},
   270  								},
   271  								Branches: map[string]TideContextPolicy{
   272  									"branch": {
   273  										RequiredContexts: []string{"r4"},
   274  										OptionalContexts: []string{"o4"},
   275  									},
   276  								},
   277  							},
   278  						},
   279  					},
   280  				},
   281  			},
   282  			expected: TideContextPolicy{
   283  				RequiredContexts: []string{"r1", "r2", "r3", "r4"},
   284  				OptionalContexts: []string{"o1", "o2", "o3", "o4"},
   285  			},
   286  		},
   287  	}
   288  	for _, tc := range testCases {
   289  		policy := parseTideContextPolicyOptions(org, repo, branch, tc.config)
   290  		if !reflect.DeepEqual(policy, tc.expected) {
   291  			t.Errorf("%s - expected %v got %v", tc.name, tc.expected, policy)
   292  		}
   293  	}
   294  }
   295  
   296  func TestConfigGetTideContextPolicy(t *testing.T) {
   297  	yes := true
   298  	no := false
   299  	org, repo, branch := "org", "repo", "branch"
   300  	testCases := []struct {
   301  		name     string
   302  		config   Config
   303  		expected TideContextPolicy
   304  		error    string
   305  	}{
   306  		{
   307  			name: "no policy - use prow jobs",
   308  			config: Config{
   309  				ProwConfig: ProwConfig{
   310  					BranchProtection: BranchProtection{
   311  						Policy: Policy{
   312  							Protect: &yes,
   313  							RequiredStatusChecks: &ContextPolicy{
   314  								Contexts: []string{"r1", "r2"},
   315  							},
   316  						},
   317  					},
   318  				},
   319  				JobConfig: JobConfig{
   320  					Presubmits: map[string][]Presubmit{
   321  						"org/repo": {
   322  							Presubmit{
   323  								Context:   "pr1",
   324  								AlwaysRun: true,
   325  							},
   326  							Presubmit{
   327  								Context:   "po1",
   328  								AlwaysRun: true,
   329  								Optional:  true,
   330  							},
   331  						},
   332  					},
   333  				},
   334  			},
   335  			expected: TideContextPolicy{
   336  				RequiredContexts: []string{"pr1"},
   337  				OptionalContexts: []string{"po1"},
   338  			},
   339  		},
   340  		{
   341  			name: "no policy no prow jobs defined - empty",
   342  			config: Config{
   343  				ProwConfig: ProwConfig{
   344  					BranchProtection: BranchProtection{
   345  						Policy: Policy{
   346  							Protect: &yes,
   347  							RequiredStatusChecks: &ContextPolicy{
   348  								Contexts: []string{"r1", "r2"},
   349  							},
   350  						},
   351  					},
   352  				},
   353  			},
   354  			expected: TideContextPolicy{
   355  				RequiredContexts: []string{},
   356  				OptionalContexts: []string{},
   357  			},
   358  		},
   359  		{
   360  			name: "no branch protection",
   361  			config: Config{
   362  				ProwConfig: ProwConfig{
   363  					Tide: Tide{
   364  						ContextOptions: TideContextPolicyOptions{
   365  							TideContextPolicy: TideContextPolicy{
   366  								FromBranchProtection: &yes,
   367  							},
   368  						},
   369  					},
   370  				},
   371  			},
   372  			expected: TideContextPolicy{
   373  				RequiredContexts: []string{},
   374  				OptionalContexts: []string{},
   375  			},
   376  		},
   377  		{
   378  			name: "invalid branch protection",
   379  			config: Config{
   380  				ProwConfig: ProwConfig{
   381  					BranchProtection: BranchProtection{
   382  						Orgs: map[string]Org{
   383  							"org": {
   384  								Policy: Policy{
   385  									Protect: &no,
   386  								},
   387  							},
   388  						},
   389  					},
   390  					Tide: Tide{
   391  						ContextOptions: TideContextPolicyOptions{
   392  							TideContextPolicy: TideContextPolicy{
   393  								FromBranchProtection: &yes,
   394  							},
   395  						},
   396  					},
   397  				},
   398  			},
   399  			expected: TideContextPolicy{
   400  				RequiredContexts: []string{},
   401  				OptionalContexts: []string{},
   402  			},
   403  		},
   404  		{
   405  			name: "manually defined policy",
   406  			config: Config{
   407  				ProwConfig: ProwConfig{
   408  					Tide: Tide{
   409  						ContextOptions: TideContextPolicyOptions{
   410  							TideContextPolicy: TideContextPolicy{
   411  								RequiredContexts:    []string{"r1"},
   412  								OptionalContexts:    []string{"o1"},
   413  								SkipUnknownContexts: &yes,
   414  							},
   415  						},
   416  					},
   417  				},
   418  			},
   419  			expected: TideContextPolicy{
   420  				RequiredContexts:    []string{"r1"},
   421  				OptionalContexts:    []string{"o1"},
   422  				SkipUnknownContexts: &yes,
   423  			},
   424  		},
   425  	}
   426  
   427  	for _, tc := range testCases {
   428  		p, err := tc.config.GetTideContextPolicy(org, repo, branch)
   429  		if !reflect.DeepEqual(p, &tc.expected) {
   430  			t.Errorf("%s - expected contexts %v got %v", tc.name, &tc.expected, p)
   431  		}
   432  		if err != nil {
   433  			if err.Error() != tc.error {
   434  				t.Errorf("%s - expected error %v got %v", tc.name, tc.error, err.Error())
   435  			}
   436  		} else if tc.error != "" {
   437  			t.Errorf("%s - expected error %v got nil", tc.name, tc.error)
   438  		}
   439  	}
   440  }
   441  
   442  func TestMergeTideContextPolicyConfig(t *testing.T) {
   443  	yes := true
   444  	no := false
   445  	testCases := []struct {
   446  		name    string
   447  		a, b, c TideContextPolicy
   448  	}{
   449  		{
   450  			name: "all empty",
   451  		},
   452  		{
   453  			name: "empty a",
   454  			b: TideContextPolicy{
   455  				SkipUnknownContexts:  &yes,
   456  				FromBranchProtection: &no,
   457  				RequiredContexts:     []string{"r1"},
   458  				OptionalContexts:     []string{"o1"},
   459  			},
   460  			c: TideContextPolicy{
   461  				SkipUnknownContexts:  &yes,
   462  				FromBranchProtection: &no,
   463  				RequiredContexts:     []string{"r1"},
   464  				OptionalContexts:     []string{"o1"},
   465  			},
   466  		},
   467  		{
   468  			name: "empty b",
   469  			a: TideContextPolicy{
   470  				SkipUnknownContexts:  &yes,
   471  				FromBranchProtection: &no,
   472  				RequiredContexts:     []string{"r1"},
   473  				OptionalContexts:     []string{"o1"},
   474  			},
   475  			c: TideContextPolicy{
   476  				SkipUnknownContexts:  &yes,
   477  				FromBranchProtection: &no,
   478  				RequiredContexts:     []string{"r1"},
   479  				OptionalContexts:     []string{"o1"},
   480  			},
   481  		},
   482  		{
   483  			name: "merging unset boolean",
   484  			a: TideContextPolicy{
   485  				FromBranchProtection: &no,
   486  				RequiredContexts:     []string{"r1"},
   487  				OptionalContexts:     []string{"o1"},
   488  			},
   489  			b: TideContextPolicy{
   490  				SkipUnknownContexts: &yes,
   491  				RequiredContexts:    []string{"r2"},
   492  				OptionalContexts:    []string{"o2"},
   493  			},
   494  			c: TideContextPolicy{
   495  				SkipUnknownContexts:  &yes,
   496  				FromBranchProtection: &no,
   497  				RequiredContexts:     []string{"r1", "r2"},
   498  				OptionalContexts:     []string{"o1", "o2"},
   499  			},
   500  		},
   501  		{
   502  			name: "merging unset contexts in a",
   503  			a: TideContextPolicy{
   504  				FromBranchProtection: &no,
   505  				SkipUnknownContexts:  &yes,
   506  			},
   507  			b: TideContextPolicy{
   508  				FromBranchProtection: &yes,
   509  				SkipUnknownContexts:  &no,
   510  				RequiredContexts:     []string{"r1"},
   511  				OptionalContexts:     []string{"o1"},
   512  			},
   513  			c: TideContextPolicy{
   514  				FromBranchProtection: &yes,
   515  				SkipUnknownContexts:  &no,
   516  				RequiredContexts:     []string{"r1"},
   517  				OptionalContexts:     []string{"o1"},
   518  			},
   519  		},
   520  		{
   521  			name: "merging unset contexts in b",
   522  			a: TideContextPolicy{
   523  				FromBranchProtection: &yes,
   524  				SkipUnknownContexts:  &no,
   525  				RequiredContexts:     []string{"r1"},
   526  				OptionalContexts:     []string{"o1"},
   527  			},
   528  			b: TideContextPolicy{
   529  				FromBranchProtection: &no,
   530  				SkipUnknownContexts:  &yes,
   531  			},
   532  			c: TideContextPolicy{
   533  				FromBranchProtection: &no,
   534  				SkipUnknownContexts:  &yes,
   535  				RequiredContexts:     []string{"r1"},
   536  				OptionalContexts:     []string{"o1"},
   537  			},
   538  		},
   539  	}
   540  
   541  	for _, tc := range testCases {
   542  		c := mergeTideContextPolicy(tc.a, tc.b)
   543  		if !reflect.DeepEqual(c, tc.c) {
   544  			t.Errorf("%s - expected %v got %v", tc.name, tc.c, c)
   545  		}
   546  	}
   547  }
   548  
   549  func TestTideQuery_Validate(t *testing.T) {
   550  	testCases := []struct {
   551  		name   string
   552  		t      TideContextPolicy
   553  		failed bool
   554  	}{
   555  		{
   556  			name: "good policy",
   557  			t: TideContextPolicy{
   558  				OptionalContexts: []string{"o1"},
   559  				RequiredContexts: []string{"r1"},
   560  			},
   561  		},
   562  		{
   563  			name: "good policy",
   564  			t: TideContextPolicy{
   565  				OptionalContexts: []string{"c1"},
   566  				RequiredContexts: []string{"c1"},
   567  			},
   568  			failed: true,
   569  		},
   570  		{
   571  			name: "good policy",
   572  			t: TideContextPolicy{
   573  				OptionalContexts: []string{"c1", "c2", "c3", "c4"},
   574  				RequiredContexts: []string{"c1", "c4"},
   575  			},
   576  			failed: true,
   577  		},
   578  	}
   579  	for _, tc := range testCases {
   580  		err := tc.t.Validate()
   581  		failed := err != nil
   582  		if failed != tc.failed {
   583  			t.Errorf("%s - expected %v got %v", tc.name, tc.failed, err)
   584  		}
   585  	}
   586  }
   587  
   588  func TestTideContextPolicy_IsOptional(t *testing.T) {
   589  	testCases := []struct {
   590  		name                string
   591  		skipUnknownContexts bool
   592  		required, optional  []string
   593  		contexts            []string
   594  		results             []bool
   595  	}{
   596  		{
   597  			name:     "only optional contexts registered - skipUnknownContexts false",
   598  			contexts: []string{"c1", "o1", "o2"},
   599  			optional: []string{"o1", "o2"},
   600  			results:  []bool{false, true, true},
   601  		},
   602  		{
   603  			name:     "no contexts registered - skipUnknownContexts false",
   604  			contexts: []string{"t2"},
   605  			results:  []bool{false},
   606  		},
   607  		{
   608  			name:     "only required contexts registered - skipUnknownContexts false",
   609  			required: []string{"c1", "c2", "c3"},
   610  			contexts: []string{"c1", "c2", "c3", "t1"},
   611  			results:  []bool{false, false, false, false},
   612  		},
   613  		{
   614  			name:     "optional and required contexts registered - skipUnknownContexts false",
   615  			optional: []string{"o1", "o2"},
   616  			required: []string{"c1", "c2", "c3"},
   617  			contexts: []string{"o1", "o2", "c1", "c2", "c3", "t1"},
   618  			results:  []bool{true, true, false, false, false, false},
   619  		},
   620  		{
   621  			name:                "only optional contexts registered - skipUnknownContexts true",
   622  			contexts:            []string{"c1", "o1", "o2"},
   623  			optional:            []string{"o1", "o2"},
   624  			skipUnknownContexts: true,
   625  			results:             []bool{true, true, true},
   626  		},
   627  		{
   628  			name:                "no contexts registered - skipUnknownContexts true",
   629  			contexts:            []string{"t2"},
   630  			skipUnknownContexts: true,
   631  			results:             []bool{true},
   632  		},
   633  		{
   634  			name:                "only required contexts registered - skipUnknownContexts true",
   635  			required:            []string{"c1", "c2", "c3"},
   636  			contexts:            []string{"c1", "c2", "c3", "t1"},
   637  			skipUnknownContexts: true,
   638  			results:             []bool{false, false, false, true},
   639  		},
   640  		{
   641  			name:                "optional and required contexts registered - skipUnknownContexts true",
   642  			optional:            []string{"o1", "o2"},
   643  			required:            []string{"c1", "c2", "c3"},
   644  			contexts:            []string{"o1", "o2", "c1", "c2", "c3", "t1"},
   645  			skipUnknownContexts: true,
   646  			results:             []bool{true, true, false, false, false, true},
   647  		},
   648  	}
   649  
   650  	for _, tc := range testCases {
   651  		cp := TideContextPolicy{
   652  			SkipUnknownContexts: &tc.skipUnknownContexts,
   653  			RequiredContexts:    tc.required,
   654  			OptionalContexts:    tc.optional,
   655  		}
   656  		for i, c := range tc.contexts {
   657  			if cp.IsOptional(c) != tc.results[i] {
   658  				t.Errorf("%s - IsOptional for %s should return %t", tc.name, c, tc.results[i])
   659  			}
   660  		}
   661  	}
   662  }
   663  
   664  func TestTideContextPolicy_MissingRequiredContexts(t *testing.T) {
   665  	testCases := []struct {
   666  		name                               string
   667  		skipUnknownContexts                bool
   668  		required, optional                 []string
   669  		existingContexts, expectedContexts []string
   670  	}{
   671  		{
   672  			name:             "no contexts registered",
   673  			existingContexts: []string{"c1", "c2"},
   674  		},
   675  		{
   676  			name:             "optional contexts registered / no missing contexts",
   677  			optional:         []string{"o1", "o2", "o3"},
   678  			existingContexts: []string{"c1", "c2"},
   679  		},
   680  		{
   681  			name:             "required  contexts registered / missing contexts",
   682  			required:         []string{"c1", "c2", "c3"},
   683  			existingContexts: []string{"c1", "c2"},
   684  			expectedContexts: []string{"c3"},
   685  		},
   686  		{
   687  			name:             "required contexts registered / no missing contexts",
   688  			required:         []string{"c1", "c2", "c3"},
   689  			existingContexts: []string{"c1", "c2", "c3"},
   690  		},
   691  		{
   692  			name:             "optional and required contexts registered / missing contexts",
   693  			optional:         []string{"o1", "o2", "o3"},
   694  			required:         []string{"c1", "c2", "c3"},
   695  			existingContexts: []string{"c1", "c2"},
   696  			expectedContexts: []string{"c3"},
   697  		},
   698  		{
   699  			name:             "optional and required contexts registered / no missing contexts",
   700  			optional:         []string{"o1", "o2", "o3"},
   701  			required:         []string{"c1", "c2"},
   702  			existingContexts: []string{"c1", "c2", "c4"},
   703  		},
   704  	}
   705  
   706  	for _, tc := range testCases {
   707  		cp := TideContextPolicy{
   708  			SkipUnknownContexts: &tc.skipUnknownContexts,
   709  			RequiredContexts:    tc.required,
   710  			OptionalContexts:    tc.optional,
   711  		}
   712  		missingContexts := cp.MissingRequiredContexts(tc.existingContexts)
   713  		if !sets.NewString(missingContexts...).Equal(sets.NewString(tc.expectedContexts...)) {
   714  			t.Errorf("%s - expected %v got %v", tc.name, tc.expectedContexts, missingContexts)
   715  		}
   716  	}
   717  }