github.com/abayer/test-infra@v0.0.5/mungegithub/features/repo-updates_test.go (about)

     1  /*
     2  Copyright 2015 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 features
    18  
    19  import (
    20  	"fmt"
    21  	"path/filepath"
    22  	"reflect"
    23  	"runtime"
    24  	"testing"
    25  
    26  	"github.com/golang/glog"
    27  	"github.com/google/go-github/github"
    28  	"k8s.io/apimachinery/pkg/util/sets"
    29  )
    30  
    31  var (
    32  	_ = fmt.Printf
    33  	_ = glog.Errorf
    34  )
    35  
    36  const (
    37  	baseDir        = ""
    38  	leafDir        = "a/b/c"
    39  	nonExistentDir = "DELETED_DIR"
    40  )
    41  
    42  func getTestRepo() *RepoInfo {
    43  	testRepo := RepoInfo{enableMdYaml: false, useReviewers: false}
    44  	approvers := map[string]sets.String{}
    45  	baseApprovers := sets.NewString("Alice", "Bob")
    46  	leafApprovers := sets.NewString("Carl", "Dave")
    47  	approvers[baseDir] = baseApprovers
    48  	approvers[leafDir] = leafApprovers
    49  	testRepo.approvers = approvers
    50  	testRepo.labels = map[string]sets.String{
    51  		baseDir: sets.NewString("sig/godzilla"),
    52  		leafDir: sets.NewString("wg/save-tokyo"),
    53  	}
    54  
    55  	return &testRepo
    56  }
    57  
    58  func TestGetApprovers(t *testing.T) {
    59  	testFile0 := filepath.Join(baseDir, "testFile.md")
    60  	testFile1 := filepath.Join(leafDir, "testFile.md")
    61  	testFile2 := filepath.Join(nonExistentDir, "testFile.md")
    62  	TestRepo := getTestRepo()
    63  	tests := []struct {
    64  		testName           string
    65  		testFile           *github.CommitFile
    66  		expectedOwnersPath string
    67  		expectedLeafOwners sets.String
    68  		expectedAllOwners  sets.String
    69  	}{
    70  		{
    71  			testName:           "Modified Base Dir Only",
    72  			testFile:           &github.CommitFile{Filename: &testFile0},
    73  			expectedOwnersPath: baseDir,
    74  			expectedLeafOwners: TestRepo.approvers[baseDir],
    75  			expectedAllOwners:  TestRepo.approvers[baseDir],
    76  		},
    77  		{
    78  			testName:           "Modified Leaf Dir Only",
    79  			testFile:           &github.CommitFile{Filename: &testFile1},
    80  			expectedOwnersPath: leafDir,
    81  			expectedLeafOwners: TestRepo.approvers[leafDir],
    82  			expectedAllOwners:  TestRepo.approvers[leafDir].Union(TestRepo.approvers[baseDir]),
    83  		},
    84  		{
    85  			testName:           "Modified Nonexistent Dir (Default to Base)",
    86  			testFile:           &github.CommitFile{Filename: &testFile2},
    87  			expectedOwnersPath: baseDir,
    88  			expectedLeafOwners: TestRepo.approvers[baseDir],
    89  			expectedAllOwners:  TestRepo.approvers[baseDir],
    90  		},
    91  	}
    92  	for testNum, test := range tests {
    93  		foundLeafApprovers := TestRepo.LeafApprovers(*test.testFile.Filename)
    94  		foundApprovers := TestRepo.Approvers(*test.testFile.Filename)
    95  		foundOwnersPath := TestRepo.FindApproverOwnersForPath(*test.testFile.Filename)
    96  		if !foundLeafApprovers.Equal(test.expectedLeafOwners) {
    97  			t.Errorf("The Leaf Approvers Found Do Not Match Expected For Test %d: %s", testNum, test.testName)
    98  			t.Errorf("\tExpected Owners: %v\tFound Owners: %v ", test.expectedLeafOwners, foundLeafApprovers)
    99  		}
   100  		if !foundApprovers.Equal(test.expectedAllOwners) {
   101  			t.Errorf("The Approvers Found Do Not Match Expected For Test %d: %s", testNum, test.testName)
   102  			t.Errorf("\tExpected Owners: %v\tFound Owners: %v ", test.expectedAllOwners, foundApprovers)
   103  		}
   104  		if foundOwnersPath != test.expectedOwnersPath {
   105  			t.Errorf("The Owners Path Found Does Not Match Expected For Test %d: %s", testNum, test.testName)
   106  			t.Errorf("\tExpected Owners: %v\tFound Owners: %v ", test.expectedOwnersPath, foundOwnersPath)
   107  		}
   108  	}
   109  }
   110  
   111  func TestLabels(t *testing.T) {
   112  	tests := []struct {
   113  		testName       string
   114  		inputPath      string
   115  		expectedLabels sets.String
   116  	}{
   117  		{
   118  			testName:       "base 1",
   119  			inputPath:      "foo.txt",
   120  			expectedLabels: sets.NewString("sig/godzilla"),
   121  		}, {
   122  			testName:       "base 2",
   123  			inputPath:      "./foo.txt",
   124  			expectedLabels: sets.NewString("sig/godzilla"),
   125  		}, {
   126  			testName:       "base 3",
   127  			inputPath:      "",
   128  			expectedLabels: sets.NewString("sig/godzilla"),
   129  		}, {
   130  			testName:       "base 4",
   131  			inputPath:      ".",
   132  			expectedLabels: sets.NewString("sig/godzilla"),
   133  		}, {
   134  			testName:       "leaf 1",
   135  			inputPath:      "a/b/c/foo.txt",
   136  			expectedLabels: sets.NewString("sig/godzilla", "wg/save-tokyo"),
   137  		}, {
   138  			testName:       "leaf 2",
   139  			inputPath:      "a/b/foo.txt",
   140  			expectedLabels: sets.NewString("sig/godzilla"),
   141  		},
   142  	}
   143  
   144  	TestRepo := getTestRepo()
   145  	for _, tt := range tests {
   146  		got := TestRepo.FindLabelsForPath(tt.inputPath)
   147  		if !got.Equal(tt.expectedLabels) {
   148  			t.Errorf("%v: expected %v, got %v", tt.testName, tt.expectedLabels, got)
   149  		}
   150  	}
   151  }
   152  
   153  func TestCanonical(t *testing.T) {
   154  
   155  	tests := []struct {
   156  		testName     string
   157  		inputPath    string
   158  		expectedPath string
   159  	}{
   160  		{
   161  			testName:     "Empty String",
   162  			inputPath:    "",
   163  			expectedPath: "",
   164  		},
   165  		{
   166  			testName:     "Dot (.) as Path",
   167  			inputPath:    ".",
   168  			expectedPath: "",
   169  		},
   170  		{
   171  			testName:     "Github Style Input (No Root)",
   172  			inputPath:    "a/b/c/d.txt",
   173  			expectedPath: "a/b/c/d.txt",
   174  		},
   175  		{
   176  			testName:     "Preceding Slash and Trailing Slash",
   177  			inputPath:    "/a/b/",
   178  			expectedPath: "/a/b",
   179  		},
   180  		{
   181  			testName:     "Trailing Slash",
   182  			inputPath:    "foo/bar/baz/",
   183  			expectedPath: "foo/bar/baz",
   184  		},
   185  	}
   186  	for _, test := range tests {
   187  		if test.expectedPath != canonicalize(test.inputPath) {
   188  			t.Errorf("Expected the canonical path for %v to be %v.  Found %v instead", test.inputPath, test.expectedPath, canonicalize(test.inputPath))
   189  		}
   190  	}
   191  }
   192  
   193  var (
   194  	lowerCaseAliases = []byte(`
   195  aliases:
   196    team/t1:
   197      - u1
   198      - u2
   199    team/t2:
   200      - u1
   201      - u3`)
   202  	mixedCaseAliases = []byte(`
   203  aliases:
   204    TEAM/T1:
   205      - U1
   206      - U2`)
   207  )
   208  
   209  type aliasTest struct {
   210  	data []byte
   211  }
   212  
   213  func (a *aliasTest) read() ([]byte, error) {
   214  	return a.data, nil
   215  }
   216  
   217  func TestCalculateAliasDelta(t *testing.T) {
   218  	runtime.GOMAXPROCS(runtime.NumCPU())
   219  
   220  	tests := []struct {
   221  		name      string
   222  		aliasData []byte
   223  		approvers sets.String
   224  		reviewers sets.String
   225  		expectedA sets.String
   226  		expectedR sets.String
   227  	}{
   228  		{
   229  			name:      "No expansions.",
   230  			aliasData: lowerCaseAliases,
   231  			approvers: sets.NewString("abc", "def"),
   232  			expectedA: sets.NewString("abc", "def"),
   233  			reviewers: sets.NewString("abcr", "defr"),
   234  			expectedR: sets.NewString("abcr", "defr"),
   235  		},
   236  		{
   237  			name:      "One alias to be expanded",
   238  			aliasData: lowerCaseAliases,
   239  			approvers: sets.NewString("abc", "team/t1"),
   240  			expectedA: sets.NewString("abc", "u1", "u2"),
   241  			reviewers: sets.NewString("abcr", "team/t2"),
   242  			expectedR: sets.NewString("abcr", "u1", "u3"),
   243  		},
   244  		{
   245  			name:      "Duplicates inside and outside alias.",
   246  			aliasData: lowerCaseAliases,
   247  			approvers: sets.NewString("u1", "team/t1"),
   248  			expectedA: sets.NewString("u1", "u2"),
   249  			reviewers: sets.NewString("u3", "team/t2"),
   250  			expectedR: sets.NewString("u3", "u1"),
   251  		},
   252  		{
   253  			name:      "Duplicates in multiple aliases.",
   254  			aliasData: lowerCaseAliases,
   255  			approvers: sets.NewString("u1", "team/t1", "team/t2"),
   256  			expectedA: sets.NewString("u1", "u2", "u3"),
   257  			reviewers: sets.NewString("u1", "team/t1", "team/t2"),
   258  			expectedR: sets.NewString("u1", "u2", "u3"),
   259  		},
   260  		{
   261  			name:      "Mixed casing in aliases.",
   262  			aliasData: mixedCaseAliases,
   263  			approvers: sets.NewString("team/t1"),
   264  			expectedA: sets.NewString("u1", "u2"),
   265  			reviewers: sets.NewString("team/t1"),
   266  			expectedR: sets.NewString("u1", "u2"),
   267  		},
   268  	}
   269  
   270  	for _, test := range tests {
   271  		info := RepoInfo{
   272  			aliasFile: "dummy.file",
   273  			aliasData: &aliasData{},
   274  			aliasReader: &aliasTest{
   275  				data: test.aliasData,
   276  			},
   277  			approvers: map[string]sets.String{
   278  				"fake": test.approvers,
   279  			},
   280  			reviewers: map[string]sets.String{
   281  				"fake": test.reviewers,
   282  			},
   283  		}
   284  
   285  		if err := info.updateRepoAliases(); err != nil {
   286  			t.Fatalf("%v", err)
   287  		}
   288  
   289  		info.expandAllAliases()
   290  		if expected, got := test.expectedA, info.approvers["fake"]; !reflect.DeepEqual(expected, got) {
   291  			t.Errorf("%s: expected approvers: %#v, got: %#v", test.name, expected, got)
   292  		}
   293  		if expected, got := test.expectedR, info.reviewers["fake"]; !reflect.DeepEqual(expected, got) {
   294  			t.Errorf("%s: expected reviewers: %#v, got: %#v", test.name, expected, got)
   295  		}
   296  	}
   297  }
   298  
   299  func TestResolveAlias(t *testing.T) {
   300  	tests := []struct {
   301  		name         string
   302  		knownAliases map[string][]string
   303  		user         string
   304  		expected     []string
   305  	}{
   306  		{
   307  			name:         "no known aliases",
   308  			knownAliases: map[string][]string{},
   309  			user:         "bob",
   310  			expected:     []string{},
   311  		},
   312  		{
   313  			name:         "no applicable aliases",
   314  			knownAliases: map[string][]string{"jim": {"james"}},
   315  			user:         "bob",
   316  			expected:     []string{},
   317  		},
   318  		{
   319  			name:         "applicable aliases",
   320  			knownAliases: map[string][]string{"bob": {"robert"}},
   321  			user:         "bob",
   322  			expected:     []string{"robert"},
   323  		},
   324  	}
   325  
   326  	for _, test := range tests {
   327  		info := RepoInfo{
   328  			aliasData: &aliasData{
   329  				AliasMap: test.knownAliases,
   330  			},
   331  		}
   332  
   333  		if expected, got := test.expected, info.resolveAlias(test.user); !reflect.DeepEqual(expected, got) {
   334  			t.Errorf("%s: expected: %#v, got: %#v", test.name, expected, got)
   335  		}
   336  	}
   337  }