k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/experiment/gerrit-onboarder/onboarder_test.go (about)

     1  /*
     2  Copyright 2021 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 main
    18  
    19  import (
    20  	"regexp"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	"github.com/google/go-cmp/cmp/cmpopts"
    26  )
    27  
    28  func TestMapToGroups(t *testing.T) {
    29  	cases := []struct {
    30  		name         string
    31  		groupsMap    map[string]string
    32  		groupsString string
    33  		orderedIDs   []string
    34  	}{
    35  		{
    36  			name:         "empty map",
    37  			groupsMap:    map[string]string{},
    38  			groupsString: "# UUID\tGroup Name\n",
    39  			orderedIDs:   []string{},
    40  		},
    41  		{
    42  			name: "all uuids same size",
    43  			groupsMap: map[string]string{
    44  				"123456": "Test Project 1",
    45  				"567890": "Test Project 2",
    46  			},
    47  			groupsString: "# UUID\tGroup Name\n123456\tTest Project 1\n567890\tTest Project 2\n",
    48  			orderedIDs:   []string{"123456", "567890"},
    49  		},
    50  		{
    51  			name: "different sized uuid",
    52  			groupsMap: map[string]string{
    53  				"1234":      "Test Project 1",
    54  				"123456789": "Test Project 2",
    55  			},
    56  			groupsString: "# UUID   \tGroup Name\n1234     \tTest Project 1\n123456789\tTest Project 2\n",
    57  			orderedIDs:   []string{"1234", "123456789"},
    58  		},
    59  		{
    60  			name: "Keeps comments",
    61  			groupsMap: map[string]string{
    62  				"1234":      "Test Project 1",
    63  				"123456789": "Test Project 2",
    64  			},
    65  			groupsString: "# UUID   \tGroup Name\n#\n1234     \tTest Project 1\n123456789\tTest Project 2\n",
    66  			orderedIDs:   []string{"#", "1234", "123456789"},
    67  		},
    68  	}
    69  
    70  	for _, tc := range cases {
    71  		t.Run(tc.name, func(t *testing.T) {
    72  			if diff := cmp.Diff(tc.groupsString, mapToGroups(tc.groupsMap, tc.orderedIDs)); diff != "" {
    73  				t.Errorf("mapToGroup returned unexpected value (-want +got):\n%s", diff)
    74  			}
    75  		})
    76  	}
    77  
    78  }
    79  
    80  func TestGroupsToMap(t *testing.T) {
    81  	cases := []struct {
    82  		name         string
    83  		groupsMap    map[string]string
    84  		groupsString string
    85  		orderedIDs   []string
    86  	}{
    87  		{
    88  			name:         "empty groups",
    89  			groupsMap:    map[string]string{},
    90  			groupsString: "# UUID\tGroup Name\n",
    91  			orderedIDs:   []string{},
    92  		},
    93  		{
    94  			name: "all uuids same size",
    95  			groupsMap: map[string]string{
    96  				"123456": "Test Project 1",
    97  				"567890": "Test Project 2",
    98  			},
    99  			groupsString: "# UUID\tGroup Name\n123456\tTest Project 1\n567890\tTest Project 2\n",
   100  			orderedIDs:   []string{"123456", "567890"},
   101  		},
   102  		{
   103  			name: "different sized uuid",
   104  			groupsMap: map[string]string{
   105  				"1234":      "Test Project 1",
   106  				"123456789": "Test Project 2",
   107  			},
   108  			groupsString: "# UUID   \tGroup Name\n1234     \tTest Project 1\n123456789\tTest Project 2\n",
   109  			orderedIDs:   []string{"1234", "123456789"},
   110  		},
   111  		{
   112  			name: "keeps comments",
   113  			groupsMap: map[string]string{
   114  				"1234":      "Test Project 1",
   115  				"123456789": "Test Project 2",
   116  			},
   117  			groupsString: "# UUID   \tGroup Name\n#\n1234     \tTest Project 1\n123456789\tTest Project 2\n",
   118  			orderedIDs:   []string{"#", "1234", "123456789"},
   119  		},
   120  	}
   121  
   122  	for _, tc := range cases {
   123  		t.Run(tc.name, func(t *testing.T) {
   124  			groupsMap, orderedKeys := groupsToMap(tc.groupsString)
   125  			if diff := cmp.Diff(tc.groupsMap, groupsMap, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" {
   126  				t.Errorf("groupsToMap returned unexpected map value(-want +got):\n%s", diff)
   127  			}
   128  
   129  			if diff := cmp.Diff(tc.orderedIDs, orderedKeys); diff != "" {
   130  				t.Errorf("groupsToMap returned unexpected ordered keys value (-want +got):\n%s", diff)
   131  			}
   132  		})
   133  	}
   134  }
   135  
   136  func TestConfigToMap(t *testing.T) {
   137  	cases := []struct {
   138  		name         string
   139  		configMap    map[string][]string
   140  		configString string
   141  		orderedIDs   []string
   142  	}{
   143  		{
   144  			name:         "empty config",
   145  			configMap:    map[string][]string{},
   146  			configString: "",
   147  			orderedIDs:   []string{},
   148  		},
   149  		{
   150  			name:         "one section",
   151  			configMap:    map[string][]string{"[access]": {"\towner = group Test Group"}},
   152  			configString: "[access]\n\towner = group Test Group",
   153  			orderedIDs:   []string{"[access]"},
   154  		},
   155  		{
   156  			name:         "multiple sections and lines",
   157  			configMap:    map[string][]string{"[access]": {"\towner = group Test Group", "\towner = group Test Group 2"}, "[access \"refs/*\"]": {"\tread = group Test Group 3"}},
   158  			configString: "[access]\n\towner = group Test Group\n\towner = group Test Group 2\n[access \"refs/*\"]\n\tread = group Test Group 3",
   159  			orderedIDs:   []string{"[access]", "[access \"refs/*\"]"},
   160  		},
   161  		{
   162  			name:         "empty line end of file",
   163  			configString: "[access]\n\towner=group Test Group\n",
   164  			configMap:    map[string][]string{"[access]": {"\towner=group Test Group"}},
   165  			orderedIDs:   []string{"[access]"},
   166  		},
   167  	}
   168  	for _, tc := range cases {
   169  		t.Run(tc.name, func(t *testing.T) {
   170  			configMap, orderedKeys := configToMap(tc.configString)
   171  			if diff := cmp.Diff(tc.configMap, configMap, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" {
   172  				t.Errorf("configToMap returned unexpected map value(-want +got):\n%s", diff)
   173  			}
   174  			if diff := cmp.Diff(tc.orderedIDs, orderedKeys, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" {
   175  				t.Errorf("configToMap returned unexpected ordredKeys value(-want +got):\n%s", diff)
   176  			}
   177  		})
   178  	}
   179  }
   180  
   181  func TestMapToConfig(t *testing.T) {
   182  	cases := []struct {
   183  		name         string
   184  		configMap    map[string][]string
   185  		configString string
   186  		orderedIDs   []string
   187  	}{
   188  		{
   189  			name:         "empty config",
   190  			configMap:    map[string][]string{},
   191  			configString: "",
   192  			orderedIDs:   []string{},
   193  		},
   194  		{
   195  			name:         "one section",
   196  			configMap:    map[string][]string{"[access]": {"\towner = group Test Group"}},
   197  			configString: "[access]\n\towner = group Test Group\n",
   198  			orderedIDs:   []string{"[access]"},
   199  		},
   200  		{
   201  			name:         "multiple sections and lines",
   202  			configMap:    map[string][]string{"[access]": {"\towner = group Test Group", "\towner = group Test Group 2"}, "[access \"refs/*\"]": {"\tread = group Test Group 3"}},
   203  			configString: "[access]\n\towner = group Test Group\n\towner = group Test Group 2\n[access \"refs/*\"]\n\tread = group Test Group 3\n",
   204  			orderedIDs:   []string{"[access]", "[access \"refs/*\"]"},
   205  		},
   206  	}
   207  	for _, tc := range cases {
   208  		t.Run(tc.name, func(t *testing.T) {
   209  			config := mapToConfig(tc.configMap, tc.orderedIDs)
   210  			if diff := cmp.Diff(tc.configString, config); diff != "" {
   211  				t.Errorf("mapToConfig returned unexpected value(-want +got):\n%s", diff)
   212  			}
   213  		})
   214  	}
   215  }
   216  
   217  func TestEnsureUUID(t *testing.T) {
   218  	cases := []struct {
   219  		name           string
   220  		id             string
   221  		group          string
   222  		groupsString   string
   223  		expectedString string
   224  		err            bool
   225  	}{
   226  		{
   227  			name:           "already exists",
   228  			id:             "123456",
   229  			group:          "Test Project 1",
   230  			groupsString:   "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n",
   231  			expectedString: "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n",
   232  			err:            false,
   233  		},
   234  		{
   235  			name:           "add new ID with new spacing",
   236  			id:             "123456789",
   237  			group:          "Test Project 3",
   238  			groupsString:   "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n",
   239  			expectedString: "# UUID   \tGroup Name\n#\n123456   \tTest Project 1\n567890   \tTest Project 2\n123456789\tTest Project 3\n",
   240  			err:            false,
   241  		},
   242  		{
   243  			name:           "conflicting ID",
   244  			id:             "123456",
   245  			group:          "Test Project 3",
   246  			groupsString:   "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n",
   247  			expectedString: "",
   248  			err:            true,
   249  		},
   250  		{
   251  			name:           "conflicting groupName",
   252  			id:             "12345678",
   253  			group:          "Test Project 1",
   254  			groupsString:   "# UUID\tGroup Name\n#\n123456\tTest Project 1\n567890\tTest Project 2\n",
   255  			expectedString: "",
   256  			err:            true,
   257  		},
   258  	}
   259  	for _, tc := range cases {
   260  		t.Run(tc.name, func(t *testing.T) {
   261  			res, err := ensureUUID(tc.groupsString, tc.id, tc.group)
   262  			if err != nil && !tc.err {
   263  				t.Errorf("expected no error but got %v", err)
   264  			}
   265  			if err == nil && tc.err {
   266  				t.Error("expected error but got none")
   267  			}
   268  			if diff := cmp.Diff(tc.expectedString, res); diff != "" {
   269  				t.Errorf("ensureUUID returned unexpected value (-want +got):\n%s", diff)
   270  			}
   271  		})
   272  	}
   273  }
   274  
   275  func TestGetInheritedRepo(t *testing.T) {
   276  	cases := []struct {
   277  		name      string
   278  		configMap map[string][]string
   279  		expected  string
   280  	}{
   281  		{
   282  			name:      "no inheritance",
   283  			configMap: map[string][]string{"[access]": {"\towner = group Test Group"}},
   284  			expected:  "",
   285  		},
   286  		{
   287  			name:      "inherits",
   288  			configMap: map[string][]string{"[access]": {"\towner = group Test Group", "/tinheritFrom = All-Projects"}},
   289  			expected:  "All-Projects",
   290  		},
   291  	}
   292  	for _, tc := range cases {
   293  		t.Run(tc.name, func(t *testing.T) {
   294  			res := getInheritedRepo(tc.configMap)
   295  			if diff := cmp.Diff(tc.expected, res); diff != "" {
   296  				t.Errorf("getInheritedRepo returned unexpected value(-want +got):\n%s", diff)
   297  			}
   298  		})
   299  	}
   300  
   301  }
   302  
   303  func TestLineInMatchingHeaderFunc(t *testing.T) {
   304  	sampleConfig := map[string][]string{
   305  		"[access]":                     {"\towner = group Test Group 2", "\towner = group Test Group 3"},
   306  		"[access \"refs/*\"]":          {"\tread = group Test Group 1"},
   307  		"[access \"refs/for/master\"]": {"\tread = group Test Group 4"},
   308  	}
   309  	cases := []struct {
   310  		name      string
   311  		configMap map[string][]string
   312  		line      string
   313  		expected  bool
   314  		regex     *regexp.Regexp
   315  	}{
   316  		{
   317  			name:      "empty config",
   318  			configMap: map[string][]string{},
   319  			line:      "owner = group Test Group",
   320  			expected:  false,
   321  			regex:     accessRefsRegex,
   322  		},
   323  		{
   324  			name:      "line in config",
   325  			configMap: sampleConfig,
   326  			line:      "read = group Test Group 1",
   327  			expected:  true,
   328  			regex:     accessRefsRegex,
   329  		},
   330  		{
   331  			name:      "line not under header",
   332  			configMap: sampleConfig,
   333  			line:      "owner = group Test Group 2",
   334  			expected:  false,
   335  			regex:     accessRefsRegex,
   336  		},
   337  		{
   338  			name:      "header more complicated",
   339  			configMap: sampleConfig,
   340  			line:      "read = group Test Group 4",
   341  			expected:  true,
   342  			regex:     accessRefsRegex,
   343  		},
   344  	}
   345  	for _, tc := range cases {
   346  		t.Run(tc.name, func(t *testing.T) {
   347  			resFunc := lineInMatchingHeaderFunc(tc.regex, tc.line)
   348  			res := resFunc(tc.configMap)
   349  			if diff := cmp.Diff(tc.expected, res); diff != "" {
   350  				t.Errorf("lineInMatchingHeaderFunc returned unexpected value(-want +got):\n%s", diff)
   351  			}
   352  		})
   353  	}
   354  }
   355  
   356  func TestLabelExists(t *testing.T) {
   357  	cases := []struct {
   358  		name      string
   359  		configMap map[string][]string
   360  		expected  bool
   361  	}{
   362  		{
   363  			name:      "empty config",
   364  			configMap: map[string][]string{},
   365  			expected:  false,
   366  		},
   367  		{
   368  			name:      "header not in config",
   369  			configMap: map[string][]string{"[access]": {"\towner = group Test Group"}},
   370  			expected:  false,
   371  		},
   372  		{
   373  			name:      "header in config",
   374  			configMap: map[string][]string{labelHeader: {"\towner = group Test Group"}},
   375  			expected:  true,
   376  		},
   377  	}
   378  	for _, tc := range cases {
   379  		t.Run(tc.name, func(t *testing.T) {
   380  			// labelExists always returns nil error
   381  			res := labelExists(tc.configMap)
   382  			if diff := cmp.Diff(tc.expected, res); diff != "" {
   383  				t.Errorf("lineInConfig returned unexpected value(-want +got):\n%s", diff)
   384  			}
   385  		})
   386  	}
   387  }
   388  
   389  func TestLabelAccessExistsFunc(t *testing.T) {
   390  	cases := []struct {
   391  		name      string
   392  		configMap map[string][]string
   393  		groupName string
   394  		expected  bool
   395  	}{
   396  		{
   397  			name:      "empty config",
   398  			configMap: map[string][]string{},
   399  			groupName: "Test Group",
   400  			expected:  false,
   401  		},
   402  		{
   403  			name:      "line in config",
   404  			configMap: map[string][]string{"[access]": {"\tlabel-Verified = -1..+1 group Test Group"}},
   405  			groupName: "Test Group",
   406  			expected:  true,
   407  		},
   408  		{
   409  			name:      "different values in config",
   410  			configMap: map[string][]string{"[access]": {"\tlabel-Verified = -2..+2 group Test Group"}},
   411  			groupName: "Test Group",
   412  			expected:  true,
   413  		},
   414  		{
   415  			name:      "Different group",
   416  			configMap: map[string][]string{"[access]": {"\tlabel-Verified = -1..+1 group Not Test Group"}},
   417  			groupName: "Test Group",
   418  			expected:  false,
   419  		},
   420  	}
   421  	for _, tc := range cases {
   422  		t.Run(tc.name, func(t *testing.T) {
   423  			resFunc := labelAccessExistsFunc(tc.groupName)
   424  			res := resFunc(tc.configMap)
   425  			if diff := cmp.Diff(tc.expected, res); diff != "" {
   426  				t.Errorf("lineInConfig returned unexpected value(-want +got):\n%s", diff)
   427  			}
   428  		})
   429  	}
   430  }
   431  
   432  func TestAddSection(t *testing.T) {
   433  	cases := []struct {
   434  		name        string
   435  		configMap   map[string][]string
   436  		orderedIDs  []string
   437  		header      string
   438  		adding      []string
   439  		expectedMap map[string][]string
   440  		expectedIDs []string
   441  	}{
   442  		{
   443  			name:        "empty config",
   444  			configMap:   map[string][]string{},
   445  			orderedIDs:  []string{},
   446  			header:      "[access]",
   447  			adding:      []string{"test1", "test2"},
   448  			expectedMap: map[string][]string{"[access]": {"\ttest1", "\ttest2"}},
   449  			expectedIDs: []string{"[access]"},
   450  		},
   451  		{
   452  			name:        "add to already existing section",
   453  			configMap:   map[string][]string{"[access]": {"\towner = group Test Group"}},
   454  			orderedIDs:  []string{"[access]"},
   455  			header:      "[access]",
   456  			adding:      []string{"test1", "test2"},
   457  			expectedMap: map[string][]string{"[access]": {"\towner = group Test Group", "\ttest1", "\ttest2"}},
   458  			expectedIDs: []string{"[access]"},
   459  		},
   460  		{
   461  			name:        "add to already existing section",
   462  			configMap:   map[string][]string{"[access]": {"\towner = group Test Group"}},
   463  			orderedIDs:  []string{"[access]"},
   464  			header:      "[test]",
   465  			adding:      []string{"test1", "test2"},
   466  			expectedMap: map[string][]string{"[access]": {"\towner = group Test Group"}, "[test]": {"\ttest1", "\ttest2"}},
   467  			expectedIDs: []string{"[access]", "[test]"},
   468  		},
   469  	}
   470  	for _, tc := range cases {
   471  		t.Run(tc.name, func(t *testing.T) {
   472  			configMap, orderedKeys := addSection(tc.header, tc.configMap, tc.orderedIDs, tc.adding)
   473  			if diff := cmp.Diff(tc.expectedMap, configMap, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" {
   474  				t.Errorf("configToMap returned unexpected map value(-want +got):\n%s", diff)
   475  			}
   476  			if diff := cmp.Diff(tc.expectedIDs, orderedKeys, cmpopts.SortSlices(func(x, y string) bool { return strings.Compare(x, y) > 0 })); diff != "" {
   477  				t.Errorf("configToMap returned unexpected ordredKeys value(-want +got):\n%s", diff)
   478  			}
   479  		})
   480  	}
   481  }
   482  
   483  func TestGetRepoClonedName(t *testing.T) {
   484  	cases := []struct {
   485  		name     string
   486  		repo     string
   487  		expected string
   488  	}{
   489  		{
   490  			name:     "No slashes",
   491  			repo:     "test-infra",
   492  			expected: "test-infra",
   493  		},
   494  		{
   495  			name:     "empty",
   496  			repo:     "",
   497  			expected: "",
   498  		},
   499  		{
   500  			name:     "one slash",
   501  			repo:     "testing/test-infra",
   502  			expected: "test-infra",
   503  		},
   504  		{
   505  			name:     "multiple slashes",
   506  			repo:     "testing/two/test-infra",
   507  			expected: "test-infra",
   508  		},
   509  	}
   510  	for _, tc := range cases {
   511  		t.Run(tc.name, func(t *testing.T) {
   512  			workdir := getRepoClonedName(tc.repo)
   513  			if diff := cmp.Diff(workdir, tc.expected); diff != "" {
   514  				t.Errorf("configToMap returned unexpected map value(-want +got):\n%s", diff)
   515  			}
   516  		})
   517  	}
   518  }