aboutsummaryrefslogtreecommitdiff
path: root/internal/testutil
diff options
context:
space:
mode:
Diffstat (limited to 'internal/testutil')
-rw-r--r--internal/testutil/exec.go46
-rw-r--r--internal/testutil/exec_test.go55
-rw-r--r--internal/testutil/golden.go63
-rw-r--r--internal/testutil/golden_test.go52
-rw-r--r--internal/testutil/testdata/golden3
5 files changed, 219 insertions, 0 deletions
diff --git a/internal/testutil/exec.go b/internal/testutil/exec.go
new file mode 100644
index 00000000..eee1677b
--- /dev/null
+++ b/internal/testutil/exec.go
@@ -0,0 +1,46 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package testutil
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+// Exec executes "go test" on given helper with supplied environment variables.
+// It is useful to mock "os/exec" functions in tests. When succeeded, it returns
+// the result produced by the test helper.
+// The test helper should:
+// 1. Use WantHelperProcess function to determine if it is being called in helper mode.
+// 2. Call fmt.Fprintln(os.Stdout, ...) to print results for the main test to collect.
+func Exec(helper string, envs ...string) (string, error) {
+ cmd := exec.Command(os.Args[0], "-test.run="+helper, "--")
+ cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
+ cmd.Env = append(cmd.Env, envs...)
+ out, err := cmd.CombinedOutput()
+ str := string(out)
+ if err != nil {
+ return "", fmt.Errorf("%v - %s", err, str)
+ }
+
+ if strings.Contains(str, "no tests to run") {
+ return "", errors.New("no tests to run")
+ } else if !strings.Contains(str, "PASS") {
+ return "", errors.New(str)
+ }
+
+ // Collect helper result
+ result := str[:strings.Index(str, "PASS")]
+ result = strings.TrimSpace(result)
+ return result, nil
+}
+
+// WantHelperProcess returns true if current process is in helper mode.
+func WantHelperProcess() bool {
+ return os.Getenv("GO_WANT_HELPER_PROCESS") == "1"
+}
diff --git a/internal/testutil/exec_test.go b/internal/testutil/exec_test.go
new file mode 100644
index 00000000..679dc9d0
--- /dev/null
+++ b/internal/testutil/exec_test.go
@@ -0,0 +1,55 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package testutil
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestExecHelper(t *testing.T) {
+ if !WantHelperProcess() {
+ return
+ }
+
+ if os.Getenv("PASS") != "1" {
+ fmt.Fprintln(os.Stdout, "tests failed")
+ os.Exit(1)
+ }
+
+ fmt.Fprintln(os.Stdout, "tests succeed")
+}
+
+func TestExec(t *testing.T) {
+ tests := []struct {
+ helper string
+ env string
+ expOut string
+ expErr error
+ }{
+ {
+ helper: "NoTestsToRun",
+ expErr: errors.New("no tests to run"),
+ }, {
+ helper: "TestExecHelper",
+ expErr: errors.New("exit status 1 - tests failed\n"),
+ }, {
+ helper: "TestExecHelper",
+ env: "PASS=1",
+ expOut: "tests succeed",
+ },
+ }
+ for _, test := range tests {
+ t.Run("", func(t *testing.T) {
+ out, err := Exec(test.helper, test.env)
+ assert.Equal(t, test.expErr, err)
+ assert.Equal(t, test.expOut, out)
+ })
+ }
+}
diff --git a/internal/testutil/golden.go b/internal/testutil/golden.go
new file mode 100644
index 00000000..fa584d1b
--- /dev/null
+++ b/internal/testutil/golden.go
@@ -0,0 +1,63 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package testutil
+
+import (
+ "encoding/json"
+ "flag"
+ "io/ioutil"
+ "regexp"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+var updateRegex = flag.String("update", "", "Update testdata of tests matching the given regex")
+
+// Update returns true if update regex mathces given test name.
+func Update(name string) bool {
+ if updateRegex == nil || *updateRegex == "" {
+ return false
+ }
+ return regexp.MustCompile(*updateRegex).MatchString(name)
+}
+
+// AssertGolden compares what's got and what's in the golden file. It updates
+// the golden file on-demand.
+func AssertGolden(t testing.TB, path string, update bool, got interface{}) {
+ t.Helper()
+
+ data := marshal(t, got)
+
+ if update {
+ if err := ioutil.WriteFile(path, data, 0640); err != nil {
+ t.Fatalf("update golden file %q: %s", path, err)
+ }
+ }
+
+ golden, err := ioutil.ReadFile(path)
+ if err != nil {
+ t.Fatalf("read golden file %q: %s", path, err)
+ }
+
+ assert.Equal(t, string(golden), string(data))
+}
+
+func marshal(t testing.TB, v interface{}) []byte {
+ t.Helper()
+
+ switch v2 := v.(type) {
+ case string:
+ return []byte(v2)
+ case []byte:
+ return v2
+ default:
+ data, err := json.MarshalIndent(v, "", " ")
+ if err != nil {
+ t.Fatal(err)
+ }
+ return data
+ }
+}
diff --git a/internal/testutil/golden_test.go b/internal/testutil/golden_test.go
new file mode 100644
index 00000000..05f31399
--- /dev/null
+++ b/internal/testutil/golden_test.go
@@ -0,0 +1,52 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package testutil
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestUpdate(t *testing.T) {
+ before := updateRegex
+ defer func() {
+ updateRegex = before
+ }()
+
+ t.Run("no flag", func(t *testing.T) {
+ updateRegex = nil
+ assert.False(t, Update("TestUpdate"))
+ })
+
+ tests := []struct {
+ regex string
+ name string
+ want bool
+ }{
+ {regex: "", name: "TestUpdate", want: false},
+ {regex: "TestNotFound", name: "TestUpdate", want: false},
+
+ {regex: ".*", name: "TestUpdate", want: true},
+ }
+ for _, test := range tests {
+ t.Run("", func(t *testing.T) {
+ updateRegex = &test.regex
+ assert.Equal(t, test.want, Update(test.name))
+ })
+ }
+}
+
+func TestAssertGolden(t *testing.T) {
+ // Make sure it does not blow up
+ AssertGolden(t, filepath.Join("testdata", "golden"), false, "{\n \"Message\": \"This is a golden file.\"\n}")
+ AssertGolden(t, filepath.Join("testdata", "golden"), false, []byte("{\n \"Message\": \"This is a golden file.\"\n}"))
+
+ type T struct {
+ Message string
+ }
+ AssertGolden(t, filepath.Join("testdata", "golden"), false, T{"This is a golden file."})
+}
diff --git a/internal/testutil/testdata/golden b/internal/testutil/testdata/golden
new file mode 100644
index 00000000..b0336818
--- /dev/null
+++ b/internal/testutil/testdata/golden
@@ -0,0 +1,3 @@
+{
+ "Message": "This is a golden file."
+} \ No newline at end of file