| // 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 := txtar(t, dir, testdata, "--extract"); 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 := txtar(t, dir, comment, args...); 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 { |
| t.Helper() |
| cmd := exec.Command(txtarName(t), args...) |
| cmd.Dir = dir |
| cmd.Stdin = strings.NewReader(input) |
| stderr := new(strings.Builder) |
| cmd.Stderr = stderr |
| out, err := cmd.Output() |
| if err != nil { |
| t.Fatalf("%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) |
| } |
| |
| 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 |
| } |