diff options
Diffstat (limited to '')
-rw-r--r-- | dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar_test.go | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar_test.go new file mode 100644 index 0000000..ea9f2bf --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar_test.go @@ -0,0 +1,178 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main_test + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "sync" + "testing" +) + +const comment = "This is a txtar archive.\n" + +const testdata = `This is a txtar archive. +-- one.txt -- +one +-- dir/two.txt -- +two +-- $SPECIAL_LOCATION/three.txt -- +three +` + +func TestMain(m *testing.M) { + code := m.Run() + txtarBin.once.Do(func() {}) + if txtarBin.name != "" { + os.Remove(txtarBin.name) + } + os.Exit(code) +} + +func TestRoundTrip(t *testing.T) { + os.Setenv("SPECIAL_LOCATION", "special") + defer os.Unsetenv("SPECIAL_LOCATION") + + // Expand the testdata archive into a temporary directory. + parentDir, err := ioutil.TempDir("", "txtar") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(parentDir) + dir := filepath.Join(parentDir, "dir") + if err := os.Mkdir(dir, 0755); err != nil { + t.Fatal(err) + } + if out, err := txtar(t, dir, testdata, "--extract"); err != nil { + t.Fatal(err) + } else if out != comment { + t.Fatalf("txtar --extract: stdout:\n%s\nwant:\n%s", out, comment) + } + + // Now, re-archive its contents explicitly and ensure that the result matches + // the original. + args := []string{"one.txt", "dir", "$SPECIAL_LOCATION"} + if out, err := txtar(t, dir, comment, args...); err != nil { + t.Fatal(err) + } else if out != testdata { + t.Fatalf("txtar %s: archive:\n%s\n\nwant:\n%s", strings.Join(args, " "), out, testdata) + } +} + +func TestUnsafePaths(t *testing.T) { + // Set up temporary directories for test archives. + parentDir, err := ioutil.TempDir("", "txtar") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(parentDir) + dir := filepath.Join(parentDir, "dir") + if err := os.Mkdir(dir, 0755); err != nil { + t.Fatal(err) + } + + // Test --unsafe option for both absolute and relative paths + testcases := []struct{ name, path string }{ + {"Absolute", filepath.Join(parentDir, "dirSpecial")}, + {"Relative", "../special"}, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + // Set SPECIAL_LOCATION outside the current directory + t.Setenv("SPECIAL_LOCATION", tc.path) + + // Expand the testdata archive into a temporary directory. + + // Should fail without the --unsafe flag + if _, err := txtar(t, dir, testdata, "--extract"); err == nil { + t.Fatalf("txtar --extract: extracts to unsafe paths") + } + + // Should allow paths outside the current dir with the --unsafe flags + out, err := txtar(t, dir, testdata, "--extract", "--unsafe") + if err != nil { + t.Fatal(err) + } + if out != comment { + t.Fatalf("txtar --extract --unsafe: stdout:\n%s\nwant:\n%s", out, comment) + } + + // Now, re-archive its contents explicitly and ensure that the result matches + // the original. + args := []string{"one.txt", "dir", "$SPECIAL_LOCATION"} + out, err = txtar(t, dir, comment, args...) + if err != nil { + t.Fatal(err) + } + if out != testdata { + t.Fatalf("txtar %s: archive:\n%s\n\nwant:\n%s", strings.Join(args, " "), out, testdata) + } + }) + } +} + +// txtar runs the txtar command in the given directory with the given input and +// arguments. +func txtar(t *testing.T, dir, input string, args ...string) (string, error) { + t.Helper() + cmd := exec.Command(txtarName(t), args...) + cmd.Dir = dir + cmd.Env = append(os.Environ(), "PWD="+dir) + cmd.Stdin = strings.NewReader(input) + stderr := new(strings.Builder) + cmd.Stderr = stderr + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, stderr) + } + if stderr.String() != "" { + t.Logf("OK: %s\n%s", strings.Join(cmd.Args, " "), stderr) + } + return string(out), nil +} + +var txtarBin struct { + once sync.Once + name string + err error +} + +// txtarName returns the name of the txtar executable, building it if needed. +func txtarName(t *testing.T) string { + t.Helper() + if _, err := exec.LookPath("go"); err != nil { + t.Skipf("cannot build txtar binary: %v", err) + } + + txtarBin.once.Do(func() { + exe, err := ioutil.TempFile("", "txtar-*.exe") + if err != nil { + txtarBin.err = err + return + } + exe.Close() + txtarBin.name = exe.Name() + + cmd := exec.Command("go", "build", "-o", txtarBin.name, ".") + out, err := cmd.CombinedOutput() + if err != nil { + txtarBin.err = fmt.Errorf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out) + } + }) + + if txtarBin.err != nil { + if runtime.GOOS == "android" { + t.Skipf("skipping test after failing to build txtar binary: go_android_exec may have failed to copy needed dependencies (see https://golang.org/issue/37088)") + } + t.Fatal(txtarBin.err) + } + return txtarBin.name +} |