forked from NYANDEV/forgejo
104 lines
2.4 KiB
Go
104 lines
2.4 KiB
Go
|
package convey
|
||
|
|
||
|
type actionSpecifier uint8
|
||
|
|
||
|
const (
|
||
|
noSpecifier actionSpecifier = iota
|
||
|
skipConvey
|
||
|
focusConvey
|
||
|
)
|
||
|
|
||
|
type suite struct {
|
||
|
Situation string
|
||
|
Test t
|
||
|
Focus bool
|
||
|
Func func(C) // nil means skipped
|
||
|
FailMode FailureMode
|
||
|
}
|
||
|
|
||
|
func newSuite(situation string, failureMode FailureMode, f func(C), test t, specifier actionSpecifier) *suite {
|
||
|
ret := &suite{
|
||
|
Situation: situation,
|
||
|
Test: test,
|
||
|
Func: f,
|
||
|
FailMode: failureMode,
|
||
|
}
|
||
|
switch specifier {
|
||
|
case skipConvey:
|
||
|
ret.Func = nil
|
||
|
case focusConvey:
|
||
|
ret.Focus = true
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
func discover(items []interface{}) *suite {
|
||
|
name, items := parseName(items)
|
||
|
test, items := parseGoTest(items)
|
||
|
failure, items := parseFailureMode(items)
|
||
|
action, items := parseAction(items)
|
||
|
specifier, items := parseSpecifier(items)
|
||
|
|
||
|
if len(items) != 0 {
|
||
|
conveyPanic(parseError)
|
||
|
}
|
||
|
|
||
|
return newSuite(name, failure, action, test, specifier)
|
||
|
}
|
||
|
func item(items []interface{}) interface{} {
|
||
|
if len(items) == 0 {
|
||
|
conveyPanic(parseError)
|
||
|
}
|
||
|
return items[0]
|
||
|
}
|
||
|
func parseName(items []interface{}) (string, []interface{}) {
|
||
|
if name, parsed := item(items).(string); parsed {
|
||
|
return name, items[1:]
|
||
|
}
|
||
|
conveyPanic(parseError)
|
||
|
panic("never get here")
|
||
|
}
|
||
|
func parseGoTest(items []interface{}) (t, []interface{}) {
|
||
|
if test, parsed := item(items).(t); parsed {
|
||
|
return test, items[1:]
|
||
|
}
|
||
|
return nil, items
|
||
|
}
|
||
|
func parseFailureMode(items []interface{}) (FailureMode, []interface{}) {
|
||
|
if mode, parsed := item(items).(FailureMode); parsed {
|
||
|
return mode, items[1:]
|
||
|
}
|
||
|
return FailureInherits, items
|
||
|
}
|
||
|
func parseAction(items []interface{}) (func(C), []interface{}) {
|
||
|
switch x := item(items).(type) {
|
||
|
case nil:
|
||
|
return nil, items[1:]
|
||
|
case func(C):
|
||
|
return x, items[1:]
|
||
|
case func():
|
||
|
return func(C) { x() }, items[1:]
|
||
|
}
|
||
|
conveyPanic(parseError)
|
||
|
panic("never get here")
|
||
|
}
|
||
|
func parseSpecifier(items []interface{}) (actionSpecifier, []interface{}) {
|
||
|
if len(items) == 0 {
|
||
|
return noSpecifier, items
|
||
|
}
|
||
|
if spec, ok := items[0].(actionSpecifier); ok {
|
||
|
return spec, items[1:]
|
||
|
}
|
||
|
conveyPanic(parseError)
|
||
|
panic("never get here")
|
||
|
}
|
||
|
|
||
|
// This interface allows us to pass the *testing.T struct
|
||
|
// throughout the internals of this package without ever
|
||
|
// having to import the "testing" package.
|
||
|
type t interface {
|
||
|
Fail()
|
||
|
}
|
||
|
|
||
|
const parseError = "You must provide a name (string), then a *testing.T (if in outermost scope), an optional FailureMode, and then an action (func())."
|