Skip to content

Commit

Permalink
add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tjons committed Jun 7, 2024
1 parent 9ae22f0 commit 32341ef
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
115 changes: 115 additions & 0 deletions cmd/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2002,3 +2002,118 @@ foo contains __local1__1 if {
})
}
}

// TestBuildWithFollowSymlinks tests that the build command follows symlinks when building a bundle.
// This test uses a local tmp filesystem to create a directory with a symlink to a file in it's root
// and a local file in the bundle directory, and verifies that the built bundle contains both the symlink
// and the regular file.
// There's probably some common utilities that could be extracted at some point but for now this code is
// local to the test until we need to reuse it elsewhere.
func TestBuildWithFollowSymlinks(t *testing.T) {
rootDir, err := os.MkdirTemp("", "build-follow-symlinks")
if err != nil {
t.Fatal(err)
}
defer func() {
if err := os.RemoveAll(rootDir); err != nil {
t.Fatal(err)
}
}()
bundleDir := path.Join(rootDir, "bundle")
err = os.Mkdir(bundleDir, 0777)
if err != nil {
t.Fatal(err)
}

// create a regular file in our temp bundle directory
err = os.WriteFile(filepath.Join(bundleDir, "foo.rego"), []byte("package foo\none = 1"), 0777)
if err != nil {
t.Fatal(err)
}

// create a regular file in the root directory of our tmp directory that we will symlink into the bundle directory later
err = os.WriteFile(filepath.Join(rootDir, "bar.rego"), []byte("package foo\ntwo = 2"), 0777)
if err != nil {
t.Fatal(err)
}

// create a symlink in the bundle directory to the file in the root directory
err = os.Symlink(filepath.Join(rootDir, "bar.rego"), filepath.Join(bundleDir, "bar.rego"))
if err != nil {
t.Fatal(err)
}

params := newBuildParams()
params.outputFile = path.Join(rootDir, "test.tar.gz")
params.bundleMode = true
params.followSymlinks = true

err = dobuild(params, []string{bundleDir})
if err != nil {
t.Fatal(err)
}

// verify that the bundle is a loadable bundle
_, err = loader.NewFileLoader().AsBundle(params.outputFile)
if err != nil {
t.Fatal(err)
}

f, err := os.Open(params.outputFile)
if err != nil {
t.Fatal(err)
}
defer f.Close()

gr, err := gzip.NewReader(f)
if err != nil {
t.Fatal(err)
}

tr := tar.NewReader(gr)

// map of file name -> file content
expectedFiles := map[string]string{
bundleDir + "/foo.rego": "package foo\n\none = 1",
bundleDir + "/bar.rego": "package foo\n\ntwo = 2",
"/.manifest": `{"revision":"","roots":[""],"rego_version":0}`,
"/data.json": "{}",
}

foundFiles := make(map[string]string, 4)
for f, err := tr.Next(); err != io.EOF; f, err = tr.Next() {
if err != nil {
t.Fatal(err)
}

// ensure that all the files are regular files in the bundle
// and that no symlinks were copied
if mode := f.FileInfo().Mode(); !mode.IsRegular() {
t.Fatalf("expected regular file for file %s but got %s", f.FileInfo().Name(), mode.String())
}
// read the file content
data, err := io.ReadAll(tr)
if err != nil {
t.Fatalf("failed to read file %s: %v", f.FileInfo().Name(), err)
}
foundFiles[f.Name] = string(data)
}

if len(foundFiles) != 4 {
t.Fatalf("expected four files in bundle but got %d", len(foundFiles))
}

for name, contents := range foundFiles {
// trim added whitespace because it's annoying and makes the test less readable
contents := strings.Trim(contents, "\n")
// check that the file content matches the expected content
expectedContent, ok := expectedFiles[name]
if !ok {
t.Fatalf("unexpected file %s in bundle", name)
}

if string(contents) != expectedContent {
t.Fatalf("expected file %s to contain:\n\n%v\n\ngot:\n\n%v", name, expectedContent, contents)
}
}
}
13 changes: 13 additions & 0 deletions util/test/tempfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func MakeTempFS(root, prefix string, files map[string]string) (rootDir string, c
return rootDir, cleanup, nil
}

// TODO(tjons): WithTestFS should be refactored to just accept fstest.MapFile objects instead of strings
// WithTestFS creates a temporary file system of `files` in memory
// if `inMemoryFS` is true and invokes `f“ with that filesystem
func WithTestFS(files map[string]string, inMemoryFS bool, f func(string, fs.FS)) {
Expand All @@ -88,3 +89,15 @@ func WithTestFS(files map[string]string, inMemoryFS bool, f func(string, fs.FS))
f(rootDir, nil)
}
}

// Need a variant of the above that allows us to create a temporary file system of
// `files` in memory and invokes `f` with that filesystem BUT the files NEED to be
// fstest.MapFile objects so we can set mode for testing symlinks
func WithTestFSRich(files map[string]*fstest.MapFile, f func(string, fs.FS)) {
fsys := make(fstest.MapFS)
rootDir := "."
for k, v := range files {
fsys[filepath.Join(rootDir, k)] = v
}
f(rootDir, fsys)
}

0 comments on commit 32341ef

Please sign in to comment.