mirror of
https://github.com/zrepl/zrepl.git
synced 2025-02-17 19:01:12 +01:00
platformtest: add QueueSubtest functionality
Use it from a top-level test case to queue the execution of sub-tests after this test case is complete. Note that the testing harness executes the subtest _after_ the current top-level test. Hence, the subtest cannot use any ZFS state of the top-level test.
This commit is contained in:
parent
89f7c76c4e
commit
7769263c2e
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"container/list"
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -53,6 +54,40 @@ type HarnessArgs struct {
|
|||||||
Run string
|
Run string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type invocation struct {
|
||||||
|
runFunc tests.Case
|
||||||
|
idstring string
|
||||||
|
result *testCaseResult
|
||||||
|
children map[string]*invocation
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInvocation(runFunc tests.Case, id string) *invocation {
|
||||||
|
return &invocation{
|
||||||
|
runFunc: runFunc,
|
||||||
|
idstring: id,
|
||||||
|
children: make(map[string]*invocation),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *invocation) String() string {
|
||||||
|
idsuffix := ""
|
||||||
|
if i.idstring != "" {
|
||||||
|
idsuffix = fmt.Sprintf(": %s", i.idstring)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s%s", i.runFunc.String(), idsuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *invocation) RegisterChild(c *invocation) error {
|
||||||
|
if c.idstring == "" {
|
||||||
|
return fmt.Errorf("child must have id string")
|
||||||
|
}
|
||||||
|
if oc := i.children[c.idstring]; oc != nil {
|
||||||
|
return fmt.Errorf("idstring %q is already taken by %s", c.idstring, oc)
|
||||||
|
}
|
||||||
|
i.children[c.idstring] = c
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func HarnessRun(args HarnessArgs) error {
|
func HarnessRun(args HarnessArgs) error {
|
||||||
|
|
||||||
runRE := regexp.MustCompile(args.Run)
|
runRE := regexp.MustCompile(args.Run)
|
||||||
@ -79,21 +114,19 @@ func HarnessRun(args HarnessArgs) error {
|
|||||||
ctx = logging.WithLoggers(ctx, logging.SubsystemLoggersWithUniversalLogger(logger))
|
ctx = logging.WithLoggers(ctx, logging.SubsystemLoggersWithUniversalLogger(logger))
|
||||||
ex := platformtest.NewEx(logger)
|
ex := platformtest.NewEx(logger)
|
||||||
|
|
||||||
type invocation struct {
|
testQueue := list.New()
|
||||||
runFunc tests.Case
|
|
||||||
result *testCaseResult
|
|
||||||
}
|
|
||||||
|
|
||||||
invocations := make([]*invocation, 0, len(tests.Cases))
|
|
||||||
for _, c := range tests.Cases {
|
for _, c := range tests.Cases {
|
||||||
if runRE.MatchString(c.String()) {
|
if runRE.MatchString(c.String()) {
|
||||||
invocations = append(invocations, &invocation{runFunc: c})
|
testQueue.PushBack(newInvocation(c, ""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, inv := range invocations {
|
completedTests := list.New()
|
||||||
|
|
||||||
bold.Printf("BEGIN TEST CASE %s\n", inv.runFunc.String())
|
for testQueue.Len() > 0 {
|
||||||
|
inv := testQueue.Remove(testQueue.Front()).(*invocation)
|
||||||
|
|
||||||
|
bold.Printf("BEGIN TEST CASE %s\n", inv)
|
||||||
|
|
||||||
pool, err := platformtest.CreateOrReplaceZpool(ctx, ex, args.CreateArgs)
|
pool, err := platformtest.CreateOrReplaceZpool(ctx, ex, args.CreateArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -103,6 +136,15 @@ func HarnessRun(args HarnessArgs) error {
|
|||||||
ctx := &platformtest.Context{
|
ctx := &platformtest.Context{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
RootDataset: filepath.Join(pool.Name(), "rootds"),
|
RootDataset: filepath.Join(pool.Name(), "rootds"),
|
||||||
|
QueueSubtest: func(id string, stf func(*platformtest.Context)) {
|
||||||
|
stinv := newInvocation(stf, id)
|
||||||
|
err := inv.RegisterChild(stinv)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
bold.Printf(" QUEUING SUBTEST %q\n", id)
|
||||||
|
testQueue.PushFront(stinv)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
res := runTestCase(ctx, ex, inv.runFunc)
|
res := runTestCase(ctx, ex, inv.runFunc)
|
||||||
@ -120,6 +162,8 @@ func HarnessRun(args HarnessArgs) error {
|
|||||||
panic(fmt.Sprintf("error destroying test pool: %s", err))
|
panic(fmt.Sprintf("error destroying test pool: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
completedTests.PushBack(inv)
|
||||||
|
|
||||||
if res.failed {
|
if res.failed {
|
||||||
boldRed.Printf("TEST FAILED\n")
|
boldRed.Printf("TEST FAILED\n")
|
||||||
} else if res.skipped {
|
} else if res.skipped {
|
||||||
@ -136,7 +180,8 @@ func HarnessRun(args HarnessArgs) error {
|
|||||||
var summary struct {
|
var summary struct {
|
||||||
succ, fail, skip []*invocation
|
succ, fail, skip []*invocation
|
||||||
}
|
}
|
||||||
for _, inv := range invocations {
|
for completedTests.Len() > 0 {
|
||||||
|
inv := completedTests.Remove(completedTests.Front()).(*invocation)
|
||||||
var bucket *[]*invocation
|
var bucket *[]*invocation
|
||||||
if inv.result.failed {
|
if inv.result.failed {
|
||||||
bucket = &summary.fail
|
bucket = &summary.fail
|
||||||
@ -157,7 +202,7 @@ func HarnessRun(args HarnessArgs) error {
|
|||||||
}
|
}
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
for _, inv := range bucket {
|
for _, inv := range bucket {
|
||||||
fmt.Printf(" %s\n", inv.runFunc.String())
|
fmt.Printf(" %s\n", inv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printBucket("PASSING TESTS", boldGreen, summary.succ)
|
printBucket("PASSING TESTS", boldGreen, summary.succ)
|
||||||
|
@ -11,6 +11,13 @@ import (
|
|||||||
type Context struct {
|
type Context struct {
|
||||||
context.Context
|
context.Context
|
||||||
RootDataset string
|
RootDataset string
|
||||||
|
// Use this callback from a top-level test case to queue the
|
||||||
|
// execution of sub-tests after this test case is complete.
|
||||||
|
//
|
||||||
|
// Note that the testing harness executes the subtest
|
||||||
|
// _after_ the current top-level test. Hence, the subtest
|
||||||
|
// cannot use any ZFS state of the top-level test.
|
||||||
|
QueueSubtest func(id string, stf func(*Context))
|
||||||
}
|
}
|
||||||
|
|
||||||
var FailNowSentinel = fmt.Errorf("platformtest: FailNow called on context")
|
var FailNowSentinel = fmt.Errorf("platformtest: FailNow called on context")
|
||||||
|
Loading…
Reference in New Issue
Block a user