-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcx_test.go
131 lines (118 loc) · 3.21 KB
/
cx_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package apidCRUD
// this module contains definitions and functions of type testContext.
import (
"testing"
"fmt"
"reflect"
"runtime"
"strings"
"path"
)
// context for printing assertion failure messages including the tab name
// and item number for table-based testcases.
type testContext struct {
t *testing.T
tabName string
testno int
}
// this Errorf() is like the testing package's Errorf(), but
// prefixes the message with info identifying the test.
func (cx *testContext) Errorf(form string, args ...interface{}) {
var prefix string
loc := getTestCaller(2)
testName := cx.t.Name()
if cx.tabName == "" {
prefix = fmt.Sprintf("%s %s: ",
loc, testName)
} else {
prefix = fmt.Sprintf("%s %s #%d %s: ",
loc, testName, cx.testno, cx.tabName)
}
fmt.Printf(prefix + form + "\n", args...)
cx.t.Fail()
}
// advance the test counter
func (cx *testContext) bump() {
cx.testno++
}
// ----- definition of assertions
// assertEqual() fails the test unless exp and act are equal.
func (cx *testContext) assertEqual(exp interface{}, act interface{}, msg string) bool {
if exp != act {
cx.Errorf(`*** Assertion Failed: %s
expected: (%T)<%v>
got: (%T)<%v>`,
msg, exp, exp, act, act)
return false
}
return true
}
// assertEqualObj() fails the test unless exp and act are deeply equal.
func (cx *testContext) assertEqualObj(exp interface{}, act interface{}, msg string) bool {
if !reflect.DeepEqual(exp, act) {
cx.Errorf(`assertion failed: %s
expected: <%s>
got: <%s>`,
msg, exp, act)
return false
}
return true
}
// assertTrue() fails the test unless act is true.
func (cx *testContext) assertTrue(act bool, msg string) bool {
if !act {
cx.Errorf(`assertion failed: %s, is %t; s/b true`,
msg, act)
return false
}
return true
}
// assertErrorNil fails the test unless act is nil.
func (cx *testContext) assertErrorNil(err error, msg string) bool {
if err != nil {
cx.Errorf(`assertion failed: %s, gave error [%s]`,
msg, err)
return false
}
return true
}
// newTestContext() creates a new test context.
// tabName is intended to be a single optional argument.
// if it is specified and nonempty, it signifies that any
// assertion failures will be labelled with the tabName
// and an offset.
func newTestContext(t *testing.T,
opt ...string) *testContext {
tabName := ""
if len(opt) > 0 {
tabName = opt[0]
}
return &testContext{t, tabName, 0}
}
// return the name of the given function
func getFunctionName(f interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
}
// getTestCaller() returns the name of the n-th function up the call
// chain from the caller of "this" function. ie, the function that
// called getTestCaller would be 0; the caller of that function
// would be 1.
// the returned name includes the file and line number of the
// function call.
func getTestCaller(nth int) string {
pc := make([]uintptr, 1)
n := runtime.Callers(nth+2, pc)
if n == 0 {
return "?"
}
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
fn := frame.Function
// skip over the module name if any.
i := strings.LastIndexByte(fn, '.')
if i >= 0 {
fn = fn[i+1:]
}
return fmt.Sprintf("%s@%s:%d",
fn, path.Base(frame.File), frame.Line)
}