Skip to content

Commit

Permalink
assert: ensure message is always displayed & fix under bazel (#276)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Nephin <dnephin@gmail.com>
  • Loading branch information
cstrahan and dnephin committed Oct 12, 2023
1 parent 81cea1a commit 1fa4ef3
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 9 deletions.
17 changes: 8 additions & 9 deletions internal/assert/assert.go
Expand Up @@ -87,19 +87,18 @@ func logFailureFromBool(t LogT, msgAndArgs ...interface{}) {
args, err := source.CallExprArgs(stackIndex)
if err != nil {
t.Log(err.Error())
return
}

var msg string
const comparisonArgIndex = 1 // Assert(t, comparison)
if len(args) <= comparisonArgIndex {
t.Log(failureMessage + "but assert failed to find the expression to print")
return
}

msg, err := boolFailureMessage(args[comparisonArgIndex])
if err != nil {
t.Log(err.Error())
msg = "expression is false"
msg = "but assert failed to find the expression to print"
} else {
msg, err = boolFailureMessage(args[comparisonArgIndex])
if err != nil {
t.Log(err.Error())
msg = "expression is false"
}
}

t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...))
Expand Down
51 changes: 51 additions & 0 deletions internal/source/bazel.go
@@ -0,0 +1,51 @@
package source

import (
"fmt"
"os"
"path/filepath"
)

// These Bazel env vars are documented here:
// https://bazel.build/reference/test-encyclopedia

// Signifies test executable is being driven by `bazel test`.
//
// Due to Bazel's compilation and sandboxing strategy,
// some care is required to handle resolving the original *.go source file.
var inBazelTest = os.Getenv("BAZEL_TEST") == "1"

// The name of the target being tested (ex: //some_package:some_package_test)
var bazelTestTarget = os.Getenv("TEST_TARGET")

// Absolute path to the base of the runfiles tree
var bazelTestSrcdir = os.Getenv("TEST_SRCDIR")

// The local repository's workspace name (ex: __main__)
var bazelTestWorkspace = os.Getenv("TEST_WORKSPACE")

func bazelSourcePath(filename string) (string, error) {
// Use the env vars to resolve the test source files,
// which must be provided as test data in the respective go_test target.
filename = filepath.Join(bazelTestSrcdir, bazelTestWorkspace, filename)

_, err := os.Stat(filename)
if os.IsNotExist(err) {
return "", fmt.Errorf(bazelMissingSourceMsg, filename, bazelTestTarget)
}
return filename, nil
}

var bazelMissingSourceMsg = `
the test source file does not exist: %s
It appears that you are running this test under Bazel (target: %s).
Check that your test source files are added as test data in your go_test targets.
Example:
go_test(
name = "your_package_test",
srcs = ["your_test.go"],
deps = ["@tools_gotest_v3//assert"],
data = glob(["*_test.go"])
)"
`
14 changes: 14 additions & 0 deletions internal/source/source.go
Expand Up @@ -10,6 +10,7 @@ import (
"go/parser"
"go/token"
"os"
"path/filepath"
"runtime"
)

Expand All @@ -35,6 +36,19 @@ func CallExprArgs(stackIndex int) ([]ast.Expr, error) {
}
debug("call stack position: %s:%d", filename, line)

// Normally, `go` will compile programs with absolute paths in
// the debug metadata. However, in the name of reproducibility,
// Bazel uses a compilation strategy that results in relative paths
// (otherwise, since Bazel uses a random tmp dir for compile and sandboxing,
// the resulting binaries would change across compiles/test runs).
if inBazelTest && !filepath.IsAbs(filename) {
var err error
filename, err = bazelSourcePath(filename)
if err != nil {
return nil, err
}
}

fileset := token.NewFileSet()
astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors)
if err != nil {
Expand Down

0 comments on commit 1fa4ef3

Please sign in to comment.