...

Source file src/k8s.io/kubernetes/cmd/import-boss/main_test.go

Documentation: k8s.io/kubernetes/cmd/import-boss

     1  /*
     2  Copyright 2024 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  	"path/filepath"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  
    25  	"golang.org/x/tools/go/packages"
    26  )
    27  
    28  func TestRemoveLastDir(t *testing.T) {
    29  	table := map[string]struct{ newPath, removedDir string }{
    30  		"a/b/c": {"a/c", "b"},
    31  	}
    32  	for slashInput, expect := range table {
    33  		input := filepath.FromSlash(slashInput)
    34  
    35  		gotPath, gotRemoved := removeLastDir(input)
    36  		if e, a := filepath.FromSlash(expect.newPath), gotPath; e != a {
    37  			t.Errorf("%v: wanted %v, got %v", input, e, a)
    38  		}
    39  		if e, a := filepath.FromSlash(expect.removedDir), gotRemoved; e != a {
    40  			t.Errorf("%v: wanted %v, got %v", input, e, a)
    41  		}
    42  	}
    43  }
    44  
    45  func TestTransitiveClosure(t *testing.T) {
    46  	cases := []struct {
    47  		name     string
    48  		in       map[string][]string
    49  		expected map[string][]string
    50  	}{
    51  		{
    52  			name: "no transition",
    53  			in: map[string][]string{
    54  				"a": {"b"},
    55  				"c": {"d"},
    56  			},
    57  			expected: map[string][]string{
    58  				"a": {"b"},
    59  				"c": {"d"},
    60  			},
    61  		},
    62  		{
    63  			name: "simple",
    64  			in: map[string][]string{
    65  				"a": {"b"},
    66  				"b": {"c"},
    67  				"c": {"d"},
    68  			},
    69  			expected: map[string][]string{
    70  				"a": {"b", "c", "d"},
    71  				"b": {"c", "d"},
    72  				"c": {"d"},
    73  			},
    74  		},
    75  	}
    76  
    77  	for _, c := range cases {
    78  		t.Run(c.name, func(t *testing.T) {
    79  			out := transitiveClosure(c.in)
    80  			if !reflect.DeepEqual(c.expected, out) {
    81  				t.Errorf("expected: %#v, got %#v", c.expected, out)
    82  			}
    83  		})
    84  	}
    85  }
    86  
    87  func TestHasTestFiles(t *testing.T) {
    88  	cases := []struct {
    89  		input  []string
    90  		expect bool
    91  	}{{
    92  		input:  nil,
    93  		expect: false,
    94  	}, {
    95  		input:  []string{},
    96  		expect: false,
    97  	}, {
    98  		input:  []string{"foo.go"},
    99  		expect: false,
   100  	}, {
   101  		input:  []string{"foo.go", "bar.go"},
   102  		expect: false,
   103  	}, {
   104  		input:  []string{"foo_test.go"},
   105  		expect: true,
   106  	}, {
   107  		input:  []string{"foo.go", "foo_test.go"},
   108  		expect: true,
   109  	}, {
   110  		input:  []string{"foo.go", "foo_test.go", "bar.go", "bar_test.go"},
   111  		expect: true,
   112  	}}
   113  
   114  	for _, tc := range cases {
   115  		ret := hasTestFiles(tc.input)
   116  		if ret != tc.expect {
   117  			t.Errorf("expected %v, got %v: %q", tc.expect, ret, tc.input)
   118  		}
   119  	}
   120  }
   121  
   122  func TestPackageDir(t *testing.T) {
   123  	cases := []struct {
   124  		input  *packages.Package
   125  		expect string
   126  	}{{
   127  		input: &packages.Package{
   128  			PkgPath:      "example.com/foo/bar/qux",
   129  			GoFiles:      []string{"/src/prj/file.go"},
   130  			IgnoredFiles: []string{"/otherdir/file.go"},
   131  		},
   132  		expect: "/src/prj",
   133  	}, {
   134  		input: &packages.Package{
   135  			PkgPath:      "example.com/foo/bar/qux",
   136  			IgnoredFiles: []string{"/src/prj/file.go"},
   137  		},
   138  		expect: "/src/prj",
   139  	}, {
   140  		input: &packages.Package{
   141  			PkgPath: "example.com/foo/bar/qux",
   142  		},
   143  		expect: "",
   144  	}}
   145  
   146  	for i, tc := range cases {
   147  		ret := packageDir(tc.input)
   148  		if ret != tc.expect {
   149  			t.Errorf("[%d] expected %v, got %v: %q", i, tc.expect, ret, tc.input)
   150  		}
   151  	}
   152  }
   153  
   154  func TestHasPathPrefix(t *testing.T) {
   155  	cases := []struct {
   156  		base   string
   157  		pfx    string
   158  		expect bool
   159  	}{{
   160  		base:   "",
   161  		pfx:    "",
   162  		expect: true,
   163  	}, {
   164  		base:   "/foo/bar",
   165  		pfx:    "",
   166  		expect: true,
   167  	}, {
   168  		base:   "",
   169  		pfx:    "/foo",
   170  		expect: false,
   171  	}, {
   172  		base:   "/foo",
   173  		pfx:    "/foo",
   174  		expect: true,
   175  	}, {
   176  		base:   "/foo/bar",
   177  		pfx:    "/foo",
   178  		expect: true,
   179  	}, {
   180  		base:   "/foobar/qux",
   181  		pfx:    "/foo",
   182  		expect: false,
   183  	}, {
   184  		base:   "/foo/bar/bat/qux/zrb",
   185  		pfx:    "/foo/bar/bat",
   186  		expect: true,
   187  	}}
   188  
   189  	for _, tc := range cases {
   190  		ret := hasPathPrefix(tc.base, tc.pfx)
   191  		if ret != tc.expect {
   192  			t.Errorf("expected %v, got %v: (%q, %q)", tc.expect, ret, tc.base, tc.pfx)
   193  		}
   194  	}
   195  }
   196  
   197  func checkAllErrorStrings(t *testing.T, errs []error, expect []string) {
   198  	t.Helper()
   199  	if len(errs) != len(expect) {
   200  		t.Fatalf("expected %d errors, got %d: %q", len(expect), len(errs), errs)
   201  	}
   202  
   203  	for _, str := range expect {
   204  		found := false
   205  		for _, err := range errs {
   206  			if strings.HasPrefix(err.Error(), str) {
   207  				found = true
   208  				break
   209  			}
   210  		}
   211  		if !found {
   212  			t.Errorf("did not find error %q", str)
   213  			t.Logf("\tseek: %s\n\t  in:", str)
   214  			for _, err := range errs {
   215  				t.Logf("\t      %s", err.Error())
   216  			}
   217  		}
   218  	}
   219  }
   220  
   221  func TestSimpleForward(t *testing.T) {
   222  	pkgs, err := loadPkgs("./testdata/simple-fwd/aaa")
   223  	if err != nil {
   224  		t.Fatalf("unexpected failure: %v", err)
   225  	}
   226  	if len(pkgs) != 1 {
   227  		t.Fatalf("expected 1 pkg result, got %d", len(pkgs))
   228  	}
   229  	if pkgs[0].PkgPath != "k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/aaa" {
   230  		t.Fatalf("wrong PkgPath: %q", pkgs[0].PkgPath)
   231  	}
   232  
   233  	boss := newBoss(pkgs)
   234  	errs := boss.Verify(pkgs[0])
   235  
   236  	expect := []string{
   237  		`"k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/forbidden" is forbidden`,
   238  		`"k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/forbidden/f1" is forbidden`,
   239  		`"k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/neither" did not match any rule`,
   240  		`"k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/simple-fwd/neither/n1" did not match any rule`,
   241  	}
   242  
   243  	checkAllErrorStrings(t, errs, expect)
   244  }
   245  
   246  func TestNestedForward(t *testing.T) {
   247  	pkgs, err := loadPkgs("./testdata/nested-fwd/aaa")
   248  	if err != nil {
   249  		t.Fatalf("unexpected failure: %v", err)
   250  	}
   251  	if len(pkgs) != 1 {
   252  		t.Fatalf("expected 1 pkg result, got %d", len(pkgs))
   253  	}
   254  	if pkgs[0].PkgPath != "k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/aaa" {
   255  		t.Fatalf("wrong PkgPath: %q", pkgs[0].PkgPath)
   256  	}
   257  
   258  	boss := newBoss(pkgs)
   259  	errs := boss.Verify(pkgs[0])
   260  
   261  	expect := []string{
   262  		`"k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/forbidden-by-both" is forbidden`,
   263  		`"k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/forbidden-by-root" is forbidden`,
   264  		`"k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/forbidden-by-sub" is forbidden`,
   265  		`"k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/aaa" -> "k8s.io/kubernetes/cmd/import-boss/testdata/nested-fwd/neither/n1" did not match any rule`,
   266  	}
   267  
   268  	checkAllErrorStrings(t, errs, expect)
   269  }
   270  
   271  func TestInverse(t *testing.T) {
   272  	pkgs, err := loadPkgs("./testdata/inverse/...")
   273  	if err != nil {
   274  		t.Fatalf("unexpected failure: %v", err)
   275  	}
   276  	if len(pkgs) != 10 {
   277  		t.Fatalf("expected 10 pkg results, got %d", len(pkgs))
   278  	}
   279  
   280  	boss := newBoss(pkgs)
   281  
   282  	var errs []error
   283  	for _, pkg := range pkgs {
   284  		errs = append(errs, boss.Verify(pkg)...)
   285  	}
   286  
   287  	expect := []string{
   288  		`"k8s.io/kubernetes/cmd/import-boss/testdata/inverse/forbidden" <- "k8s.io/kubernetes/cmd/import-boss/testdata/inverse/aaa" is forbidden`,
   289  		`"k8s.io/kubernetes/cmd/import-boss/testdata/inverse/forbidden/f1" <- "k8s.io/kubernetes/cmd/import-boss/testdata/inverse/aaa" is forbidden`,
   290  		`"k8s.io/kubernetes/cmd/import-boss/testdata/inverse/allowed/a2" <- "k8s.io/kubernetes/cmd/import-boss/testdata/inverse/allowed" did not match any rule`,
   291  		`"k8s.io/kubernetes/cmd/import-boss/testdata/inverse/forbidden/f2" <- "k8s.io/kubernetes/cmd/import-boss/testdata/inverse/allowed" did not match any rule`,
   292  	}
   293  
   294  	checkAllErrorStrings(t, errs, expect)
   295  }
   296  
   297  func TestTransitive(t *testing.T) {
   298  	pkgs, err := loadPkgs("./testdata/transitive/...")
   299  	if err != nil {
   300  		t.Fatalf("unexpected failure: %v", err)
   301  	}
   302  	if len(pkgs) != 10 {
   303  		t.Fatalf("expected 10 pkg results, got %d", len(pkgs))
   304  	}
   305  
   306  	boss := newBoss(pkgs)
   307  
   308  	var errs []error
   309  	for _, pkg := range pkgs {
   310  		errs = append(errs, boss.Verify(pkg)...)
   311  	}
   312  
   313  	expect := []string{
   314  		`"k8s.io/kubernetes/cmd/import-boss/testdata/transitive/forbidden" <- "k8s.io/kubernetes/cmd/import-boss/testdata/transitive/aaa" is forbidden`,
   315  		`"k8s.io/kubernetes/cmd/import-boss/testdata/transitive/forbidden/f1" <- "k8s.io/kubernetes/cmd/import-boss/testdata/transitive/aaa" is forbidden`,
   316  		`"k8s.io/kubernetes/cmd/import-boss/testdata/transitive/forbidden/f2" <-- "k8s.io/kubernetes/cmd/import-boss/testdata/transitive/aaa" is forbidden`,
   317  		`"k8s.io/kubernetes/cmd/import-boss/testdata/transitive/allowed/a2" <- "k8s.io/kubernetes/cmd/import-boss/testdata/transitive/allowed" did not match any rule`,
   318  		`"k8s.io/kubernetes/cmd/import-boss/testdata/transitive/forbidden/f2" <- "k8s.io/kubernetes/cmd/import-boss/testdata/transitive/allowed" did not match any rule`,
   319  	}
   320  
   321  	checkAllErrorStrings(t, errs, expect)
   322  }
   323  

View as plain text