github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/internal/util/pkgutil/pkgutil_test.go (about)

     1  // Copyright 2021 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package pkgutil_test
    16  
    17  import (
    18  	"os"
    19  	"path/filepath"
    20  	"sort"
    21  	"testing"
    22  
    23  	"github.com/GoogleContainerTools/kpt/internal/pkg"
    24  	"github.com/GoogleContainerTools/kpt/internal/testutil"
    25  	"github.com/GoogleContainerTools/kpt/internal/testutil/pkgbuilder"
    26  	"github.com/GoogleContainerTools/kpt/internal/util/pkgutil"
    27  	kptfilev1 "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1"
    28  	"github.com/stretchr/testify/assert"
    29  )
    30  
    31  func TestWalkPackage(t *testing.T) {
    32  	testCases := map[string]struct {
    33  		pkg      *pkgbuilder.RootPkg
    34  		expected []string
    35  	}{
    36  		"walks subdirectories of a package": {
    37  			pkg: pkgbuilder.NewRootPkg().
    38  				WithFile("abc.yaml", "42").
    39  				WithFile("test.txt", "Hello, World!").
    40  				WithSubPackages(
    41  					pkgbuilder.NewSubPkg("foo").
    42  						WithFile("def.yaml", "123"),
    43  				),
    44  			expected: []string{
    45  				".",
    46  				"abc.yaml",
    47  				"foo",
    48  				"foo/def.yaml",
    49  				"test.txt",
    50  			},
    51  		},
    52  		"ignores .git folder": {
    53  			pkg: pkgbuilder.NewRootPkg().
    54  				WithFile("abc.yaml", "42").
    55  				WithSubPackages(
    56  					pkgbuilder.NewSubPkg(".git").
    57  						WithFile("INDEX", "ABC123"),
    58  				),
    59  			expected: []string{
    60  				".",
    61  				"abc.yaml",
    62  			},
    63  		},
    64  		"ignores subpackages": {
    65  			pkg: pkgbuilder.NewRootPkg().
    66  				WithFile("abc.yaml", "42").
    67  				WithFile("test.txt", "Hello, World!").
    68  				WithSubPackages(
    69  					pkgbuilder.NewSubPkg("foo").
    70  						WithKptfile().
    71  						WithFile("def.yaml", "123"),
    72  				),
    73  			expected: []string{
    74  				".",
    75  				"abc.yaml",
    76  				"test.txt",
    77  			},
    78  		},
    79  	}
    80  
    81  	for tn, tc := range testCases {
    82  		t.Run(tn, func(t *testing.T) {
    83  			pkgPath := tc.pkg.ExpandPkg(t, testutil.EmptyReposInfo)
    84  
    85  			var visited []string
    86  			if err := pkgutil.WalkPackage(pkgPath, func(s string, info os.FileInfo, err error) error {
    87  				if err != nil {
    88  					return err
    89  				}
    90  
    91  				relPath, err := filepath.Rel(pkgPath, s)
    92  				if err != nil {
    93  					return err
    94  				}
    95  				visited = append(visited, relPath)
    96  				return nil
    97  			}); !assert.NoError(t, err) {
    98  				t.FailNow()
    99  			}
   100  
   101  			sort.Strings(visited)
   102  
   103  			assert.Equal(t, tc.expected, visited)
   104  		})
   105  	}
   106  }
   107  
   108  func TestCopyPackage(t *testing.T) {
   109  	testCases := map[string]struct {
   110  		pkg               *pkgbuilder.RootPkg
   111  		copyRootKptfile   bool
   112  		subpackageMatcher pkg.SubpackageMatcher
   113  		expected          []string
   114  	}{
   115  		"subpackages without root kptfile": {
   116  			pkg: pkgbuilder.NewRootPkg().
   117  				WithFile("abc.yaml", "42").
   118  				WithFile("test.txt", "Hello, World!").
   119  				WithSubPackages(
   120  					pkgbuilder.NewSubPkg("foo").
   121  						WithKptfile().
   122  						WithFile("def.yaml", "123"),
   123  				),
   124  			copyRootKptfile:   false,
   125  			subpackageMatcher: pkg.Local,
   126  			expected: []string{
   127  				".",
   128  				"abc.yaml",
   129  				"foo",
   130  				"foo/Kptfile",
   131  				"foo/def.yaml",
   132  				"test.txt",
   133  			},
   134  		},
   135  		"ignores .git folder": {
   136  			pkg: pkgbuilder.NewRootPkg().
   137  				WithFile("abc.yaml", "42").
   138  				WithSubPackages(
   139  					pkgbuilder.NewSubPkg(".git").
   140  						WithFile("INDEX", "ABC123"),
   141  				),
   142  			subpackageMatcher: pkg.None,
   143  			expected: []string{
   144  				".",
   145  				"abc.yaml",
   146  			},
   147  		},
   148  		"ignore subpackages": {
   149  			pkg: pkgbuilder.NewRootPkg().
   150  				WithKptfile().
   151  				WithFile("abc.yaml", "42").
   152  				WithFile("test.txt", "Hello, World!").
   153  				WithSubPackages(
   154  					pkgbuilder.NewSubPkg("foo").
   155  						WithKptfile().
   156  						WithFile("def.yaml", "123"),
   157  				),
   158  			copyRootKptfile:   true,
   159  			subpackageMatcher: pkg.None,
   160  			expected: []string{
   161  				".",
   162  				"Kptfile",
   163  				"abc.yaml",
   164  				"test.txt",
   165  			},
   166  		},
   167  		"include all subpackages": {
   168  			pkg: pkgbuilder.NewRootPkg().
   169  				WithKptfile().
   170  				WithFile("abc.yaml", "42").
   171  				WithFile("test.txt", "Hello, World!").
   172  				WithSubPackages(
   173  					pkgbuilder.NewSubPkg("foo").
   174  						WithKptfile().
   175  						WithFile("def.yaml", "123"),
   176  					pkgbuilder.NewSubPkg("bar").
   177  						WithKptfile(pkgbuilder.NewKptfile().WithUpstream("", "", "", "")).
   178  						WithFile("def.yaml", "123"),
   179  				),
   180  			copyRootKptfile:   true,
   181  			subpackageMatcher: pkg.All,
   182  			expected: []string{
   183  				".",
   184  				"Kptfile",
   185  				"abc.yaml",
   186  				"bar",
   187  				"bar/Kptfile",
   188  				"bar/def.yaml",
   189  				"foo",
   190  				"foo/Kptfile",
   191  				"foo/def.yaml",
   192  				"test.txt",
   193  			},
   194  		},
   195  		"include only local subpackages": {
   196  			pkg: pkgbuilder.NewRootPkg().
   197  				WithKptfile().
   198  				WithFile("abc.yaml", "42").
   199  				WithFile("test.txt", "Hello, World!").
   200  				WithSubPackages(
   201  					pkgbuilder.NewSubPkg("foo").
   202  						WithKptfile().
   203  						WithFile("def.yaml", "123"),
   204  					pkgbuilder.NewSubPkg("bar").
   205  						WithKptfile(pkgbuilder.NewKptfile().WithUpstream("", "", "", "")).
   206  						WithFile("def.yaml", "123"),
   207  				),
   208  			copyRootKptfile:   true,
   209  			subpackageMatcher: pkg.Local,
   210  			expected: []string{
   211  				".",
   212  				"Kptfile",
   213  				"abc.yaml",
   214  				"foo",
   215  				"foo/Kptfile",
   216  				"foo/def.yaml",
   217  				"test.txt",
   218  			},
   219  		},
   220  		"include only remote subpackages": {
   221  			pkg: pkgbuilder.NewRootPkg().
   222  				WithKptfile().
   223  				WithFile("abc.yaml", "42").
   224  				WithFile("test.txt", "Hello, World!").
   225  				WithSubPackages(
   226  					pkgbuilder.NewSubPkg("foo").
   227  						WithKptfile().
   228  						WithFile("def.yaml", "123"),
   229  					pkgbuilder.NewSubPkg("bar").
   230  						WithKptfile(pkgbuilder.NewKptfile().WithUpstream("", "", "", "")).
   231  						WithFile("def.yaml", "123"),
   232  				),
   233  			copyRootKptfile:   true,
   234  			subpackageMatcher: pkg.Remote,
   235  			expected: []string{
   236  				".",
   237  				"Kptfile",
   238  				"abc.yaml",
   239  				"bar",
   240  				"bar/Kptfile",
   241  				"bar/def.yaml",
   242  				"test.txt",
   243  			},
   244  		},
   245  		"include local subpackage with remote child": {
   246  			pkg: pkgbuilder.NewRootPkg().
   247  				WithKptfile().
   248  				WithFile("abc.yaml", "42").
   249  				WithFile("test.txt", "Hello, World!").
   250  				WithSubPackages(
   251  					pkgbuilder.NewSubPkg("foo").
   252  						WithKptfile().
   253  						WithFile("def.yaml", "123").WithSubPackages(
   254  						pkgbuilder.NewSubPkg("bar").
   255  							WithKptfile(pkgbuilder.NewKptfile().WithUpstream("", "", "", "")).
   256  							WithFile("def.yaml", "123"),
   257  					),
   258  				),
   259  			copyRootKptfile:   true,
   260  			subpackageMatcher: pkg.Local,
   261  			expected: []string{
   262  				".",
   263  				"Kptfile",
   264  				"abc.yaml",
   265  				"foo",
   266  				"foo/Kptfile",
   267  				"foo/bar",
   268  				"foo/bar/Kptfile",
   269  				"foo/bar/def.yaml",
   270  				"foo/def.yaml",
   271  				"test.txt",
   272  			},
   273  		},
   274  		"include local subpackage with local child": {
   275  			pkg: pkgbuilder.NewRootPkg().
   276  				WithKptfile().
   277  				WithFile("abc.yaml", "42").
   278  				WithFile("test.txt", "Hello, World!").
   279  				WithSubPackages(
   280  					pkgbuilder.NewSubPkg("foo").
   281  						WithKptfile().
   282  						WithFile("def.yaml", "123").WithSubPackages(
   283  						pkgbuilder.NewSubPkg("bar").
   284  							WithKptfile().
   285  							WithFile("def.yaml", "123"),
   286  					),
   287  				),
   288  			copyRootKptfile:   true,
   289  			subpackageMatcher: pkg.Local,
   290  			expected: []string{
   291  				".",
   292  				"Kptfile",
   293  				"abc.yaml",
   294  				"foo",
   295  				"foo/Kptfile",
   296  				"foo/bar",
   297  				"foo/bar/Kptfile",
   298  				"foo/bar/def.yaml",
   299  				"foo/def.yaml",
   300  				"test.txt",
   301  			},
   302  		},
   303  		"include remote subpackage with local child": {
   304  			pkg: pkgbuilder.NewRootPkg().
   305  				WithKptfile().
   306  				WithFile("abc.yaml", "42").
   307  				WithFile("test.txt", "Hello, World!").
   308  				WithSubPackages(
   309  					pkgbuilder.NewSubPkg("foo").
   310  						WithKptfile(pkgbuilder.NewKptfile().WithUpstream("", "", "", "")).
   311  						WithFile("def.yaml", "123").WithSubPackages(
   312  						pkgbuilder.NewSubPkg("bar").
   313  							WithKptfile().
   314  							WithFile("def.yaml", "123"),
   315  					),
   316  				),
   317  			copyRootKptfile:   true,
   318  			subpackageMatcher: pkg.Remote,
   319  			expected: []string{
   320  				".",
   321  				"Kptfile",
   322  				"abc.yaml",
   323  				"foo",
   324  				"foo/Kptfile",
   325  				"foo/def.yaml",
   326  				"foo/bar",
   327  				"foo/bar/Kptfile",
   328  				"foo/bar/def.yaml",
   329  				"test.txt",
   330  			},
   331  		},
   332  		"include remote subpackage with remote child": {
   333  			pkg: pkgbuilder.NewRootPkg().
   334  				WithKptfile().
   335  				WithFile("abc.yaml", "42").
   336  				WithFile("test.txt", "Hello, World!").
   337  				WithSubPackages(
   338  					pkgbuilder.NewSubPkg("foo").
   339  						WithKptfile(pkgbuilder.NewKptfile().WithUpstream("", "", "", "")).
   340  						WithFile("def.yaml", "123").WithSubPackages(
   341  						pkgbuilder.NewSubPkg("bar").
   342  							WithKptfile(pkgbuilder.NewKptfile().WithUpstream("", "", "", "")).
   343  							WithFile("def.yaml", "123"),
   344  					),
   345  				),
   346  			copyRootKptfile:   true,
   347  			subpackageMatcher: pkg.Remote,
   348  			expected: []string{
   349  				".",
   350  				"Kptfile",
   351  				"abc.yaml",
   352  				"foo",
   353  				"foo/Kptfile",
   354  				"foo/def.yaml",
   355  				"foo/bar",
   356  				"foo/bar/Kptfile",
   357  				"foo/bar/def.yaml",
   358  				"test.txt",
   359  			},
   360  		},
   361  	}
   362  
   363  	for tn, tc := range testCases {
   364  		t.Run(tn, func(t *testing.T) {
   365  			pkgPath := tc.pkg.ExpandPkg(t, testutil.EmptyReposInfo)
   366  			dest := t.TempDir()
   367  
   368  			err := pkgutil.CopyPackage(pkgPath, dest, tc.copyRootKptfile, tc.subpackageMatcher)
   369  			if !assert.NoError(t, err) {
   370  				t.FailNow()
   371  			}
   372  
   373  			var visited []string
   374  			if err = filepath.Walk(dest, func(s string, info os.FileInfo, err error) error {
   375  				if err != nil {
   376  					return err
   377  				}
   378  
   379  				relPath, err := filepath.Rel(dest, s)
   380  				if err != nil {
   381  					return err
   382  				}
   383  				visited = append(visited, relPath)
   384  				return nil
   385  			}); !assert.NoError(t, err) {
   386  				t.FailNow()
   387  			}
   388  
   389  			sort.Strings(visited)
   390  
   391  			assert.ElementsMatch(t, tc.expected, visited)
   392  		})
   393  	}
   394  }
   395  
   396  func TestFindLocalRecursiveSubpackagesForPaths(t *testing.T) {
   397  	testCases := map[string]struct {
   398  		pkgs     []*pkgbuilder.RootPkg
   399  		expected []string
   400  	}{
   401  		"does not include remote subpackages": {
   402  			pkgs: []*pkgbuilder.RootPkg{
   403  				pkgbuilder.NewRootPkg().
   404  					WithResource(pkgbuilder.DeploymentResource).
   405  					WithSubPackages(
   406  						pkgbuilder.NewSubPkg("foo").
   407  							WithKptfile(
   408  								pkgbuilder.NewKptfile().
   409  									WithUpstream("github.com/GoogleContainerTools/kpt",
   410  										"/", "main", string(kptfilev1.ResourceMerge)),
   411  							).
   412  							WithResource(pkgbuilder.ConfigMapResource),
   413  					),
   414  			},
   415  			expected: []string{},
   416  		},
   417  		"includes local subpackages": {
   418  			pkgs: []*pkgbuilder.RootPkg{
   419  				pkgbuilder.NewRootPkg().
   420  					WithResource(pkgbuilder.DeploymentResource).
   421  					WithSubPackages(
   422  						pkgbuilder.NewSubPkg("foo").
   423  							WithKptfile().
   424  							WithResource(pkgbuilder.ConfigMapResource),
   425  					),
   426  			},
   427  			expected: []string{
   428  				"foo",
   429  			},
   430  		},
   431  		"includes root package": {
   432  			pkgs: []*pkgbuilder.RootPkg{
   433  				pkgbuilder.NewRootPkg().
   434  					WithKptfile().
   435  					WithResource(pkgbuilder.DeploymentResource),
   436  			},
   437  			expected: []string{},
   438  		},
   439  		"does not include nested remote subpackages": {
   440  			pkgs: []*pkgbuilder.RootPkg{
   441  				pkgbuilder.NewRootPkg().
   442  					WithResource(pkgbuilder.DeploymentResource).
   443  					WithSubPackages(
   444  						pkgbuilder.NewSubPkg("foo").
   445  							WithKptfile(
   446  								pkgbuilder.NewKptfile().
   447  									WithUpstream("github.com/GoogleContainerTools/kpt",
   448  										"/", "main", string(kptfilev1.ResourceMerge)),
   449  							).
   450  							WithResource(pkgbuilder.ConfigMapResource).
   451  							WithSubPackages(
   452  								pkgbuilder.NewSubPkg("bar").
   453  									WithSubPackages(
   454  										pkgbuilder.NewSubPkg("zork").
   455  											WithKptfile(
   456  												pkgbuilder.NewKptfile().
   457  													WithUpstream("github.com/GoogleContainerTools/kpt",
   458  														"/", "main", string(kptfilev1.ResourceMerge)),
   459  											).
   460  											WithResource(pkgbuilder.ConfigMapResource),
   461  									),
   462  							),
   463  					),
   464  			},
   465  			expected: []string{},
   466  		},
   467  		"includes nested local subpackages": {
   468  			pkgs: []*pkgbuilder.RootPkg{
   469  				pkgbuilder.NewRootPkg().
   470  					WithResource(pkgbuilder.DeploymentResource).
   471  					WithSubPackages(
   472  						pkgbuilder.NewSubPkg("foo").
   473  							WithKptfile().
   474  							WithResource(pkgbuilder.ConfigMapResource).
   475  							WithSubPackages(
   476  								pkgbuilder.NewSubPkg("zork").
   477  									WithKptfile().
   478  									WithResource(pkgbuilder.ConfigMapResource),
   479  							),
   480  						pkgbuilder.NewSubPkg("subpkg").
   481  							WithKptfile(),
   482  					),
   483  			},
   484  			expected: []string{
   485  				"foo",
   486  				"foo/zork",
   487  				"subpkg",
   488  			},
   489  		},
   490  		"multiple packages": {
   491  			pkgs: []*pkgbuilder.RootPkg{
   492  				pkgbuilder.NewRootPkg().
   493  					WithResource(pkgbuilder.DeploymentResource).
   494  					WithSubPackages(
   495  						pkgbuilder.NewSubPkg("foo").
   496  							WithKptfile().
   497  							WithResource(pkgbuilder.ConfigMapResource).
   498  							WithSubPackages(
   499  								pkgbuilder.NewSubPkg("zork").
   500  									WithKptfile().
   501  									WithResource(pkgbuilder.ConfigMapResource),
   502  							),
   503  						pkgbuilder.NewSubPkg("subpkg").
   504  							WithKptfile(),
   505  					),
   506  				pkgbuilder.NewRootPkg().
   507  					WithKptfile().
   508  					WithSubPackages(
   509  						pkgbuilder.NewSubPkg("foo").
   510  							WithKptfile(),
   511  					),
   512  				pkgbuilder.NewRootPkg().
   513  					WithKptfile().
   514  					WithSubPackages(
   515  						pkgbuilder.NewSubPkg("bar").
   516  							WithKptfile(),
   517  						pkgbuilder.NewSubPkg("remotebar").
   518  							WithKptfile(
   519  								pkgbuilder.NewKptfile().
   520  									WithUpstream("github.com/GoogleContainerTools/kpt",
   521  										"/", "main", string(kptfilev1.ResourceMerge)),
   522  							),
   523  					),
   524  			},
   525  			expected: []string{
   526  				"bar",
   527  				"foo",
   528  				"foo/zork",
   529  				"subpkg",
   530  			},
   531  		},
   532  	}
   533  
   534  	for tn, tc := range testCases {
   535  		t.Run(tn, func(t *testing.T) {
   536  			var pkgPaths []string
   537  			for _, p := range tc.pkgs {
   538  				pkgPaths = append(pkgPaths, p.ExpandPkg(t, testutil.EmptyReposInfo))
   539  			}
   540  
   541  			paths, err := pkgutil.FindSubpackagesForPaths(pkg.Local, true, pkgPaths...)
   542  			if !assert.NoError(t, err) {
   543  				t.FailNow()
   544  			}
   545  
   546  			sort.Strings(paths)
   547  
   548  			assert.Equal(t, tc.expected, paths)
   549  		})
   550  	}
   551  }