401 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			401 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
| Copyright 2020 Google LLC
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package filesystem
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"reflect"
 | |
| 	"sort"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/GoogleContainerTools/kaniko/pkg/util"
 | |
| )
 | |
| 
 | |
| func Test_ResolvePaths(t *testing.T) {
 | |
| 	validateResults := func(
 | |
| 		t *testing.T,
 | |
| 		actualFiles,
 | |
| 		expectedFiles []string,
 | |
| 		err error,
 | |
| 	) {
 | |
| 		if err != nil {
 | |
| 			t.Errorf("expected err to be nil but was %s", err)
 | |
| 		}
 | |
| 
 | |
| 		// Sort so that comparison is against consistent order
 | |
| 		sort.Strings(actualFiles)
 | |
| 		sort.Strings(expectedFiles)
 | |
| 
 | |
| 		if !reflect.DeepEqual(actualFiles, expectedFiles) {
 | |
| 			t.Errorf("expected files to equal %s but was %s",
 | |
| 				expectedFiles, actualFiles,
 | |
| 			)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	t.Run("list of files", func(t *testing.T) {
 | |
| 		dir, err := ioutil.TempDir("", "snapshot-test")
 | |
| 		if err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		defer os.RemoveAll(dir)
 | |
| 
 | |
| 		files := []string{
 | |
| 			"/foo/bar.txt",
 | |
| 			"/baz/boom.txt",
 | |
| 		}
 | |
| 
 | |
| 		t.Run("all are symlinks", func(t *testing.T) {
 | |
| 			for _, f := range files {
 | |
| 				fLink := filepath.Join(dir, "link", f)
 | |
| 				fTarget := filepath.Join(dir, "target", f)
 | |
| 
 | |
| 				if err := os.MkdirAll(filepath.Dir(fTarget), 0777); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 
 | |
| 				if err := ioutil.WriteFile(fTarget, []byte{}, 0777); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 
 | |
| 				if err := os.MkdirAll(filepath.Dir(fLink), 0777); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 
 | |
| 				if err := os.Symlink(fTarget, fLink); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			t.Run("none are ignored", func(t *testing.T) {
 | |
| 				wl := []util.IgnoreListEntry{}
 | |
| 
 | |
| 				inputFiles := []string{}
 | |
| 				expectedFiles := []string{}
 | |
| 
 | |
| 				for _, f := range files {
 | |
| 					link := filepath.Join(dir, "link", f)
 | |
| 					expectedFiles = append(expectedFiles, link)
 | |
| 					inputFiles = append(inputFiles, link)
 | |
| 
 | |
| 					target := filepath.Join(dir, "target", f)
 | |
| 					expectedFiles = append(expectedFiles, target)
 | |
| 				}
 | |
| 
 | |
| 				expectedFiles = filesWithParentDirs(expectedFiles)
 | |
| 
 | |
| 				files, err := ResolvePaths(inputFiles, wl)
 | |
| 
 | |
| 				validateResults(t, files, expectedFiles, err)
 | |
| 			})
 | |
| 
 | |
| 			t.Run("some are ignored", func(t *testing.T) {
 | |
| 				wl := []util.IgnoreListEntry{
 | |
| 					{
 | |
| 						Path: filepath.Join(dir, "link", "baz"),
 | |
| 					},
 | |
| 					{
 | |
| 						Path: filepath.Join(dir, "target", "foo"),
 | |
| 					},
 | |
| 				}
 | |
| 
 | |
| 				expectedFiles := []string{}
 | |
| 				inputFiles := []string{}
 | |
| 
 | |
| 				for _, f := range files {
 | |
| 					link := filepath.Join(dir, "link", f)
 | |
| 					inputFiles = append(inputFiles, link)
 | |
| 
 | |
| 					if util.IsInProvidedIgnoreList(link, wl) {
 | |
| 						t.Logf("skipping %s", link)
 | |
| 						continue
 | |
| 					}
 | |
| 
 | |
| 					expectedFiles = append(expectedFiles, link)
 | |
| 
 | |
| 					target := filepath.Join(dir, "target", f)
 | |
| 
 | |
| 					if util.IsInProvidedIgnoreList(target, wl) {
 | |
| 						t.Logf("skipping %s", target)
 | |
| 						continue
 | |
| 					}
 | |
| 
 | |
| 					expectedFiles = append(expectedFiles, target)
 | |
| 				}
 | |
| 
 | |
| 				link := filepath.Join(dir, "link", "zoom/")
 | |
| 
 | |
| 				target := filepath.Join(dir, "target", "zaam/")
 | |
| 				if err := os.MkdirAll(target, 0777); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 
 | |
| 				if err := ioutil.WriteFile(filepath.Join(target, "meow.txt"), []byte{}, 0777); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 
 | |
| 				if err := os.Symlink(target, link); err != nil {
 | |
| 					t.Fatal(err)
 | |
| 				}
 | |
| 
 | |
| 				file := filepath.Join(link, "meow.txt")
 | |
| 				inputFiles = append(inputFiles, file)
 | |
| 
 | |
| 				expectedFiles = append(expectedFiles, link)
 | |
| 
 | |
| 				targetFile := filepath.Join(target, "meow.txt")
 | |
| 				expectedFiles = append(expectedFiles, targetFile)
 | |
| 
 | |
| 				expectedFiles = filesWithParentDirs(expectedFiles)
 | |
| 
 | |
| 				files, err := ResolvePaths(inputFiles, wl)
 | |
| 
 | |
| 				validateResults(t, files, expectedFiles, err)
 | |
| 			})
 | |
| 		})
 | |
| 	})
 | |
| 
 | |
| 	t.Run("empty set of files", func(t *testing.T) {
 | |
| 		inputFiles := []string{}
 | |
| 		expectedFiles := []string{}
 | |
| 
 | |
| 		wl := []util.IgnoreListEntry{}
 | |
| 
 | |
| 		files, err := ResolvePaths(inputFiles, wl)
 | |
| 
 | |
| 		validateResults(t, files, expectedFiles, err)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func Test_resolveSymlinkAncestor(t *testing.T) {
 | |
| 	setupDirs := func(t *testing.T) (string, string) {
 | |
| 		testDir, err := ioutil.TempDir("", "")
 | |
| 		if err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		targetDir := filepath.Join(testDir, "bar", "baz")
 | |
| 
 | |
| 		if err := os.MkdirAll(targetDir, 0777); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		targetPath := filepath.Join(targetDir, "bam.txt")
 | |
| 
 | |
| 		if err := ioutil.WriteFile(targetPath, []byte("meow"), 0777); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		return testDir, targetPath
 | |
| 	}
 | |
| 
 | |
| 	t.Run("path is a symlink", func(t *testing.T) {
 | |
| 		testDir, targetPath := setupDirs(t)
 | |
| 		defer os.RemoveAll(testDir)
 | |
| 
 | |
| 		linkDir := filepath.Join(testDir, "foo", "buzz")
 | |
| 
 | |
| 		if err := os.MkdirAll(linkDir, 0777); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		linkPath := filepath.Join(linkDir, "zoom.txt")
 | |
| 
 | |
| 		if err := os.Symlink(targetPath, linkPath); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		expected := linkPath
 | |
| 
 | |
| 		actual, err := resolveSymlinkAncestor(linkPath)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("expected err to be nil but was %s", err)
 | |
| 		}
 | |
| 
 | |
| 		if actual != expected {
 | |
| 			t.Errorf("expected result to be %s not %s", expected, actual)
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	t.Run("dir ends with / is not a symlink", func(t *testing.T) {
 | |
| 		testDir, _ := setupDirs(t)
 | |
| 		defer os.RemoveAll(testDir)
 | |
| 
 | |
| 		linkDir := filepath.Join(testDir, "var", "www")
 | |
| 		if err := os.MkdirAll(linkDir, 0777); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		expected := linkDir
 | |
| 
 | |
| 		actual, err := resolveSymlinkAncestor(fmt.Sprintf("%s/", linkDir))
 | |
| 		if err != nil {
 | |
| 			t.Errorf("expected err to be nil but was %s", err)
 | |
| 		}
 | |
| 
 | |
| 		if actual != expected {
 | |
| 			t.Errorf("expected result to be %s not %s", expected, actual)
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	t.Run("path is a dead symlink", func(t *testing.T) {
 | |
| 		testDir, targetPath := setupDirs(t)
 | |
| 		defer os.RemoveAll(testDir)
 | |
| 
 | |
| 		linkDir := filepath.Join(testDir, "foo", "buzz")
 | |
| 
 | |
| 		if err := os.MkdirAll(linkDir, 0777); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		linkPath := filepath.Join(linkDir, "zoom.txt")
 | |
| 
 | |
| 		if err := os.Symlink(targetPath, linkPath); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		if err := os.Remove(targetPath); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		expected := linkPath
 | |
| 
 | |
| 		actual, err := resolveSymlinkAncestor(linkPath)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("expected err to be nil but was %s", err)
 | |
| 		}
 | |
| 
 | |
| 		if actual != expected {
 | |
| 			t.Errorf("expected result to be %s not %s", expected, actual)
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	t.Run("path is not a symlink", func(t *testing.T) {
 | |
| 		testDir, targetPath := setupDirs(t)
 | |
| 		defer os.RemoveAll(testDir)
 | |
| 
 | |
| 		expected := targetPath
 | |
| 
 | |
| 		actual, err := resolveSymlinkAncestor(targetPath)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("expected err to be nil but was %s", err)
 | |
| 		}
 | |
| 
 | |
| 		if actual != expected {
 | |
| 			t.Errorf("expected result to be %s not %s", expected, actual)
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	t.Run("parent of path is a symlink", func(t *testing.T) {
 | |
| 		testDir, targetPath := setupDirs(t)
 | |
| 		defer os.RemoveAll(testDir)
 | |
| 
 | |
| 		targetDir := filepath.Dir(targetPath)
 | |
| 
 | |
| 		linkDir := filepath.Join(testDir, "foo")
 | |
| 
 | |
| 		if err := os.MkdirAll(linkDir, 0777); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		linkDir = filepath.Join(linkDir, "gaz")
 | |
| 
 | |
| 		if err := os.Symlink(targetDir, linkDir); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		linkPath := filepath.Join(linkDir, filepath.Base(targetPath))
 | |
| 
 | |
| 		expected := linkDir
 | |
| 
 | |
| 		actual, err := resolveSymlinkAncestor(linkPath)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("expected err to be nil but was %s", err)
 | |
| 		}
 | |
| 
 | |
| 		if actual != expected {
 | |
| 			t.Errorf("expected result to be %s not %s", expected, actual)
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	t.Run("parent of path is a dead symlink", func(t *testing.T) {
 | |
| 		testDir, targetPath := setupDirs(t)
 | |
| 		defer os.RemoveAll(testDir)
 | |
| 
 | |
| 		targetDir := filepath.Dir(targetPath)
 | |
| 
 | |
| 		linkDir := filepath.Join(testDir, "foo")
 | |
| 
 | |
| 		if err := os.MkdirAll(linkDir, 0777); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		linkDir = filepath.Join(linkDir, "gaz")
 | |
| 
 | |
| 		if err := os.Symlink(targetDir, linkDir); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		if err := os.RemoveAll(targetDir); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		linkPath := filepath.Join(linkDir, filepath.Base(targetPath))
 | |
| 
 | |
| 		_, err := resolveSymlinkAncestor(linkPath)
 | |
| 		if err == nil {
 | |
| 			t.Error("expected err to not be nil")
 | |
| 		}
 | |
| 	})
 | |
| 
 | |
| 	t.Run("great grandparent of path is a symlink", func(t *testing.T) {
 | |
| 		testDir, targetPath := setupDirs(t)
 | |
| 		defer os.RemoveAll(testDir)
 | |
| 
 | |
| 		targetDir := filepath.Dir(targetPath)
 | |
| 
 | |
| 		linkDir := filepath.Join(testDir, "foo")
 | |
| 
 | |
| 		if err := os.Symlink(filepath.Dir(targetDir), linkDir); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		linkPath := filepath.Join(
 | |
| 			linkDir,
 | |
| 			filepath.Join(
 | |
| 				filepath.Base(targetDir),
 | |
| 				filepath.Base(targetPath),
 | |
| 			),
 | |
| 		)
 | |
| 
 | |
| 		expected := linkDir
 | |
| 
 | |
| 		actual, err := resolveSymlinkAncestor(linkPath)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("expected err to be nil but was %s", err)
 | |
| 		}
 | |
| 
 | |
| 		if actual != expected {
 | |
| 			t.Errorf("expected result to be %s not %s", expected, actual)
 | |
| 		}
 | |
| 	})
 | |
| }
 |