mirror of
https://github.com/zrepl/zrepl.git
synced 2025-06-18 15:56:45 +02:00
platformtest: harness: refactor + support SkipNow
This commit is contained in:
parent
e7aa08564b
commit
ddd7acec49
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -17,12 +18,25 @@ import (
|
|||||||
"github.com/zrepl/zrepl/platformtest/tests"
|
"github.com/zrepl/zrepl/platformtest/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
var bold = color.New(color.Bold)
|
||||||
|
var boldRed = color.New(color.Bold, color.FgHiRed)
|
||||||
|
var boldGreen = color.New(color.Bold, color.FgHiGreen)
|
||||||
|
|
||||||
var args struct {
|
var args struct {
|
||||||
createArgs platformtest.ZpoolCreateArgs
|
createArgs platformtest.ZpoolCreateArgs
|
||||||
stopAndKeepPoolOnFail bool
|
stopAndKeepPoolOnFail bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := doMain(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var exitWithErr = fmt.Errorf("exit with error")
|
||||||
|
|
||||||
|
func doMain() error {
|
||||||
|
|
||||||
flag.StringVar(&args.createArgs.PoolName, "poolname", "", "")
|
flag.StringVar(&args.createArgs.PoolName, "poolname", "", "")
|
||||||
flag.StringVar(&args.createArgs.ImagePath, "imagepath", "", "")
|
flag.StringVar(&args.createArgs.ImagePath, "imagepath", "", "")
|
||||||
flag.Int64Var(&args.createArgs.ImageSize, "imagesize", 100*(1<<20), "")
|
flag.Int64Var(&args.createArgs.ImageSize, "imagesize", 100*(1<<20), "")
|
||||||
@ -50,48 +64,83 @@ func main() {
|
|||||||
ctx := platformtest.WithLogger(context.Background(), logger)
|
ctx := platformtest.WithLogger(context.Background(), logger)
|
||||||
ex := platformtest.NewEx(logger)
|
ex := platformtest.NewEx(logger)
|
||||||
|
|
||||||
bold := color.New(color.Bold)
|
|
||||||
boldRed := color.New(color.Bold, color.FgHiRed)
|
|
||||||
boldGreen := color.New(color.Bold, color.FgHiGreen)
|
|
||||||
for _, c := range tests.Cases {
|
for _, c := range tests.Cases {
|
||||||
// ATTENTION future parallelism must pass c by value into closure!
|
|
||||||
err := func() (err error) {
|
|
||||||
var oErr = &err
|
|
||||||
bold.Printf("BEGIN TEST CASE %s\n", c)
|
bold.Printf("BEGIN TEST CASE %s\n", c)
|
||||||
|
|
||||||
pool, err := platformtest.CreateOrReplaceZpool(ctx, ex, args.createArgs)
|
pool, err := platformtest.CreateOrReplaceZpool(ctx, ex, args.createArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "create test pool")
|
panic(errors.Wrap(err, "create test pool"))
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
*oErr = errors.Errorf("panic while running test: %v", err) // shadow
|
|
||||||
if args.stopAndKeepPoolOnFail {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// fallthrough
|
|
||||||
}
|
|
||||||
if err := pool.Destroy(ctx, ex); err != nil {
|
|
||||||
fmt.Printf("error destroying test pool: %s", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
ctx := &platformtest.Context{
|
ctx := &platformtest.Context{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
RootDataset: filepath.Join(pool.Name(), "rootds"),
|
RootDataset: filepath.Join(pool.Name(), "rootds"),
|
||||||
}
|
}
|
||||||
c(ctx)
|
|
||||||
return nil
|
res := runTestCase(ctx, ex, c)
|
||||||
}()
|
if res.failed {
|
||||||
if err != nil {
|
fmt.Printf("%+v\n", res.failedStack) // print with stack trace
|
||||||
boldRed.Printf("TEST CASE FAILED WITH ERROR:\n")
|
|
||||||
fmt.Printf("%+v\n", err) // print with stack trace
|
|
||||||
if args.stopAndKeepPoolOnFail {
|
|
||||||
bold.Printf("STOPPING TEST RUN AT FAILING TEST PER USER REQUEST\n")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
boldGreen.Printf("DONE TEST CASE %s\n", c)
|
if res.failed && args.stopAndKeepPoolOnFail {
|
||||||
|
boldRed.Printf("STOPPING TEST RUN AT FAILING TEST PER USER REQUEST\n")
|
||||||
|
return exitWithErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := pool.Destroy(ctx, ex); err != nil {
|
||||||
|
panic(fmt.Sprintf("error destroying test pool: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.failed {
|
||||||
|
boldRed.Printf("TEST FAILED\n")
|
||||||
|
} else if res.skipped {
|
||||||
|
bold.Printf("TEST SKIPPED\n")
|
||||||
|
} else if res.succeeded {
|
||||||
|
boldGreen.Printf("TEST PASSED\n")
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type testCaseResult struct {
|
||||||
|
// oneof
|
||||||
|
failed, skipped, succeeded bool
|
||||||
|
|
||||||
|
failedStack error // has stack inside, valid if failed=true
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTestCase(ctx *platformtest.Context, ex platformtest.Execer, c tests.Case) testCaseResult {
|
||||||
|
|
||||||
|
// run case
|
||||||
|
var paniced = false
|
||||||
|
var panicValue interface{} = nil
|
||||||
|
var panicStack error
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
if item := recover(); item != nil {
|
||||||
|
panicValue = item
|
||||||
|
paniced = true
|
||||||
|
panicStack = errors.Errorf("panic while running test: %v", panicValue)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
c(ctx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if paniced {
|
||||||
|
switch panicValue {
|
||||||
|
case platformtest.SkipNowSentinel:
|
||||||
|
return testCaseResult{skipped: true}
|
||||||
|
case platformtest.FailNowSentinel:
|
||||||
|
return testCaseResult{failed: true, failedStack: panicStack}
|
||||||
|
default:
|
||||||
|
return testCaseResult{failed: true, failedStack: panicStack}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return testCaseResult{succeeded: true}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ type Context struct {
|
|||||||
|
|
||||||
var FailNowSentinel = fmt.Errorf("platformtest: FailNow called on context")
|
var FailNowSentinel = fmt.Errorf("platformtest: FailNow called on context")
|
||||||
|
|
||||||
|
var SkipNowSentinel = fmt.Errorf("platformtest: SkipNow called on context")
|
||||||
|
|
||||||
var _ assert.TestingT = (*Context)(nil)
|
var _ assert.TestingT = (*Context)(nil)
|
||||||
var _ require.TestingT = (*Context)(nil)
|
var _ require.TestingT = (*Context)(nil)
|
||||||
|
|
||||||
@ -25,3 +27,7 @@ func (c *Context) Errorf(format string, args ...interface{}) {
|
|||||||
func (c *Context) FailNow() {
|
func (c *Context) FailNow() {
|
||||||
panic(FailNowSentinel)
|
panic(FailNowSentinel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Context) SkipNow() {
|
||||||
|
panic(SkipNowSentinel)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user