Use Go 1.5 vendoring instead of Godeps

Change made by:

- running "gvt fetch" on each of the packages mentioned in
  Godeps/Godeps.json
- `rm -rf Godeps`
- tweaking the build scripts to not mention Godeps
- tweaking the build scripts to test `./lib/...`, `./cmd/...` explicitly
  (to avoid testing vendor)
- tweaking the build scripts to not juggle GOPATH for Godeps and instead
  set GO15VENDOREXPERIMENT.

This also results in some updated packages at the same time I bet.

Building with Go 1.3 and 1.4 still *works* but won't use our vendored
dependencies - the user needs to have the actual packages in their
GOPATH then, which they'll get with a normal "go get". Building with Go
1.6+ will get our vendored dependencies by default even when not using
our build script, which is nice.

By doing this we gain some freedom in that we can pick and choose
manually what to include in vendor, as it's not based on just dependency
analysis of our own code. This is also a risk as we might pick up
dependencies we are unaware of, as the build may work locally with those
packages present in GOPATH. On the other hand the build server will
detect this as it has no packages in it's GOPATH beyond what is included
in the repo.

Recommended tool to manage dependencies is github.com/FiloSottile/gvt.
This commit is contained in:
Jakob Borg
2016-03-05 21:01:58 +01:00
parent 9259425a9a
commit 65aaa607ab
694 changed files with 65763 additions and 3541 deletions

View File

@@ -0,0 +1,55 @@
package spec
func ParallelizedIndexRange(length int, parallelTotal int, parallelNode int) (startIndex int, count int) {
if length == 0 {
return 0, 0
}
// We have more nodes than tests. Trivial case.
if parallelTotal >= length {
if parallelNode > length {
return 0, 0
} else {
return parallelNode - 1, 1
}
}
// This is the minimum amount of tests that a node will be required to run
minTestsPerNode := length / parallelTotal
// This is the maximum amount of tests that a node will be required to run
// The algorithm guarantees that this would be equal to at least the minimum amount
// and at most one more
maxTestsPerNode := minTestsPerNode
if length%parallelTotal != 0 {
maxTestsPerNode++
}
// Number of nodes that will have to run the maximum amount of tests per node
numMaxLoadNodes := length % parallelTotal
// Number of nodes that precede the current node and will have to run the maximum amount of tests per node
var numPrecedingMaxLoadNodes int
if parallelNode > numMaxLoadNodes {
numPrecedingMaxLoadNodes = numMaxLoadNodes
} else {
numPrecedingMaxLoadNodes = parallelNode - 1
}
// Number of nodes that precede the current node and will have to run the minimum amount of tests per node
var numPrecedingMinLoadNodes int
if parallelNode <= numMaxLoadNodes {
numPrecedingMinLoadNodes = 0
} else {
numPrecedingMinLoadNodes = parallelNode - numMaxLoadNodes - 1
}
// Evaluate the test start index and number of tests to run
startIndex = numPrecedingMaxLoadNodes*maxTestsPerNode + numPrecedingMinLoadNodes*minTestsPerNode
if parallelNode > numMaxLoadNodes {
count = minTestsPerNode
} else {
count = maxTestsPerNode
}
return
}

View File

@@ -0,0 +1,149 @@
package spec_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/internal/spec"
. "github.com/onsi/gomega"
)
var _ = Describe("ParallelizedIndexRange", func() {
var startIndex, count int
It("should return the correct index range for 4 tests on 2 nodes", func() {
startIndex, count = ParallelizedIndexRange(4, 2, 1)
Ω(startIndex).Should(Equal(0))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(4, 2, 2)
Ω(startIndex).Should(Equal(2))
Ω(count).Should(Equal(2))
})
It("should return the correct index range for 5 tests on 2 nodes", func() {
startIndex, count = ParallelizedIndexRange(5, 2, 1)
Ω(startIndex).Should(Equal(0))
Ω(count).Should(Equal(3))
startIndex, count = ParallelizedIndexRange(5, 2, 2)
Ω(startIndex).Should(Equal(3))
Ω(count).Should(Equal(2))
})
It("should return the correct index range for 5 tests on 3 nodes", func() {
startIndex, count = ParallelizedIndexRange(5, 3, 1)
Ω(startIndex).Should(Equal(0))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(5, 3, 2)
Ω(startIndex).Should(Equal(2))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(5, 3, 3)
Ω(startIndex).Should(Equal(4))
Ω(count).Should(Equal(1))
})
It("should return the correct index range for 5 tests on 4 nodes", func() {
startIndex, count = ParallelizedIndexRange(5, 4, 1)
Ω(startIndex).Should(Equal(0))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(5, 4, 2)
Ω(startIndex).Should(Equal(2))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 4, 3)
Ω(startIndex).Should(Equal(3))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 4, 4)
Ω(startIndex).Should(Equal(4))
Ω(count).Should(Equal(1))
})
It("should return the correct index range for 5 tests on 5 nodes", func() {
startIndex, count = ParallelizedIndexRange(5, 5, 1)
Ω(startIndex).Should(Equal(0))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 5, 2)
Ω(startIndex).Should(Equal(1))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 5, 3)
Ω(startIndex).Should(Equal(2))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 5, 4)
Ω(startIndex).Should(Equal(3))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 5, 5)
Ω(startIndex).Should(Equal(4))
Ω(count).Should(Equal(1))
})
It("should return the correct index range for 5 tests on 6 nodes", func() {
startIndex, count = ParallelizedIndexRange(5, 6, 1)
Ω(startIndex).Should(Equal(0))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 6, 2)
Ω(startIndex).Should(Equal(1))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 6, 3)
Ω(startIndex).Should(Equal(2))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 6, 4)
Ω(startIndex).Should(Equal(3))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 6, 5)
Ω(startIndex).Should(Equal(4))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(5, 6, 6)
Ω(count).Should(Equal(0))
})
It("should return the correct index range for 5 tests on 7 nodes", func() {
startIndex, count = ParallelizedIndexRange(5, 7, 6)
Ω(count).Should(Equal(0))
startIndex, count = ParallelizedIndexRange(5, 7, 7)
Ω(count).Should(Equal(0))
})
It("should return the correct index range for 11 tests on 7 nodes", func() {
startIndex, count = ParallelizedIndexRange(11, 7, 1)
Ω(startIndex).Should(Equal(0))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(11, 7, 2)
Ω(startIndex).Should(Equal(2))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(11, 7, 3)
Ω(startIndex).Should(Equal(4))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(11, 7, 4)
Ω(startIndex).Should(Equal(6))
Ω(count).Should(Equal(2))
startIndex, count = ParallelizedIndexRange(11, 7, 5)
Ω(startIndex).Should(Equal(8))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(11, 7, 6)
Ω(startIndex).Should(Equal(9))
Ω(count).Should(Equal(1))
startIndex, count = ParallelizedIndexRange(11, 7, 7)
Ω(startIndex).Should(Equal(10))
Ω(count).Should(Equal(1))
})
})

197
vendor/github.com/onsi/ginkgo/internal/spec/spec.go generated vendored Normal file
View File

@@ -0,0 +1,197 @@
package spec
import (
"fmt"
"io"
"time"
"github.com/onsi/ginkgo/internal/containernode"
"github.com/onsi/ginkgo/internal/leafnodes"
"github.com/onsi/ginkgo/types"
)
type Spec struct {
subject leafnodes.SubjectNode
focused bool
announceProgress bool
containers []*containernode.ContainerNode
state types.SpecState
runTime time.Duration
failure types.SpecFailure
}
func New(subject leafnodes.SubjectNode, containers []*containernode.ContainerNode, announceProgress bool) *Spec {
spec := &Spec{
subject: subject,
containers: containers,
focused: subject.Flag() == types.FlagTypeFocused,
announceProgress: announceProgress,
}
spec.processFlag(subject.Flag())
for i := len(containers) - 1; i >= 0; i-- {
spec.processFlag(containers[i].Flag())
}
return spec
}
func (spec *Spec) processFlag(flag types.FlagType) {
if flag == types.FlagTypeFocused {
spec.focused = true
} else if flag == types.FlagTypePending {
spec.state = types.SpecStatePending
}
}
func (spec *Spec) Skip() {
spec.state = types.SpecStateSkipped
}
func (spec *Spec) Failed() bool {
return spec.state == types.SpecStateFailed || spec.state == types.SpecStatePanicked || spec.state == types.SpecStateTimedOut
}
func (spec *Spec) Passed() bool {
return spec.state == types.SpecStatePassed
}
func (spec *Spec) Pending() bool {
return spec.state == types.SpecStatePending
}
func (spec *Spec) Skipped() bool {
return spec.state == types.SpecStateSkipped
}
func (spec *Spec) Focused() bool {
return spec.focused
}
func (spec *Spec) IsMeasurement() bool {
return spec.subject.Type() == types.SpecComponentTypeMeasure
}
func (spec *Spec) Summary(suiteID string) *types.SpecSummary {
componentTexts := make([]string, len(spec.containers)+1)
componentCodeLocations := make([]types.CodeLocation, len(spec.containers)+1)
for i, container := range spec.containers {
componentTexts[i] = container.Text()
componentCodeLocations[i] = container.CodeLocation()
}
componentTexts[len(spec.containers)] = spec.subject.Text()
componentCodeLocations[len(spec.containers)] = spec.subject.CodeLocation()
return &types.SpecSummary{
IsMeasurement: spec.IsMeasurement(),
NumberOfSamples: spec.subject.Samples(),
ComponentTexts: componentTexts,
ComponentCodeLocations: componentCodeLocations,
State: spec.state,
RunTime: spec.runTime,
Failure: spec.failure,
Measurements: spec.measurementsReport(),
SuiteID: suiteID,
}
}
func (spec *Spec) ConcatenatedString() string {
s := ""
for _, container := range spec.containers {
s += container.Text() + " "
}
return s + spec.subject.Text()
}
func (spec *Spec) Run(writer io.Writer) {
startTime := time.Now()
defer func() {
spec.runTime = time.Since(startTime)
}()
for sample := 0; sample < spec.subject.Samples(); sample++ {
spec.runSample(sample, writer)
if spec.state != types.SpecStatePassed {
return
}
}
}
func (spec *Spec) runSample(sample int, writer io.Writer) {
spec.state = types.SpecStatePassed
spec.failure = types.SpecFailure{}
innerMostContainerIndexToUnwind := -1
defer func() {
for i := innerMostContainerIndexToUnwind; i >= 0; i-- {
container := spec.containers[i]
for _, afterEach := range container.SetupNodesOfType(types.SpecComponentTypeAfterEach) {
spec.announceSetupNode(writer, "AfterEach", container, afterEach)
afterEachState, afterEachFailure := afterEach.Run()
if afterEachState != types.SpecStatePassed && spec.state == types.SpecStatePassed {
spec.state = afterEachState
spec.failure = afterEachFailure
}
}
}
}()
for i, container := range spec.containers {
innerMostContainerIndexToUnwind = i
for _, beforeEach := range container.SetupNodesOfType(types.SpecComponentTypeBeforeEach) {
spec.announceSetupNode(writer, "BeforeEach", container, beforeEach)
spec.state, spec.failure = beforeEach.Run()
if spec.state != types.SpecStatePassed {
return
}
}
}
for _, container := range spec.containers {
for _, justBeforeEach := range container.SetupNodesOfType(types.SpecComponentTypeJustBeforeEach) {
spec.announceSetupNode(writer, "JustBeforeEach", container, justBeforeEach)
spec.state, spec.failure = justBeforeEach.Run()
if spec.state != types.SpecStatePassed {
return
}
}
}
spec.announceSubject(writer, spec.subject)
spec.state, spec.failure = spec.subject.Run()
}
func (spec *Spec) announceSetupNode(writer io.Writer, nodeType string, container *containernode.ContainerNode, setupNode leafnodes.BasicNode) {
if spec.announceProgress {
s := fmt.Sprintf("[%s] %s\n %s\n", nodeType, container.Text(), setupNode.CodeLocation().String())
writer.Write([]byte(s))
}
}
func (spec *Spec) announceSubject(writer io.Writer, subject leafnodes.SubjectNode) {
if spec.announceProgress {
nodeType := ""
switch subject.Type() {
case types.SpecComponentTypeIt:
nodeType = "It"
case types.SpecComponentTypeMeasure:
nodeType = "Measure"
}
s := fmt.Sprintf("[%s] %s\n %s\n", nodeType, subject.Text(), subject.CodeLocation().String())
writer.Write([]byte(s))
}
}
func (spec *Spec) measurementsReport() map[string]*types.SpecMeasurement {
if !spec.IsMeasurement() || spec.Failed() {
return map[string]*types.SpecMeasurement{}
}
return spec.subject.(*leafnodes.MeasureNode).MeasurementsReport()
}

View File

@@ -0,0 +1,13 @@
package spec_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestSpec(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Spec Suite")
}

View File

@@ -0,0 +1,626 @@
package spec_test
import (
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
. "github.com/onsi/ginkgo/internal/spec"
"github.com/onsi/ginkgo/internal/codelocation"
"github.com/onsi/ginkgo/internal/containernode"
Failer "github.com/onsi/ginkgo/internal/failer"
"github.com/onsi/ginkgo/internal/leafnodes"
"github.com/onsi/ginkgo/types"
)
var noneFlag = types.FlagTypeNone
var focusedFlag = types.FlagTypeFocused
var pendingFlag = types.FlagTypePending
var _ = Describe("Spec", func() {
var (
failer *Failer.Failer
codeLocation types.CodeLocation
nodesThatRan []string
spec *Spec
buffer *gbytes.Buffer
)
newBody := func(text string, fail bool) func() {
return func() {
nodesThatRan = append(nodesThatRan, text)
if fail {
failer.Fail(text, codeLocation)
}
}
}
newIt := func(text string, flag types.FlagType, fail bool) *leafnodes.ItNode {
return leafnodes.NewItNode(text, newBody(text, fail), flag, codeLocation, 0, failer, 0)
}
newItWithBody := func(text string, body interface{}) *leafnodes.ItNode {
return leafnodes.NewItNode(text, body, noneFlag, codeLocation, 0, failer, 0)
}
newMeasure := func(text string, flag types.FlagType, fail bool, samples int) *leafnodes.MeasureNode {
return leafnodes.NewMeasureNode(text, func(Benchmarker) {
nodesThatRan = append(nodesThatRan, text)
if fail {
failer.Fail(text, codeLocation)
}
}, flag, codeLocation, samples, failer, 0)
}
newBef := func(text string, fail bool) leafnodes.BasicNode {
return leafnodes.NewBeforeEachNode(newBody(text, fail), codeLocation, 0, failer, 0)
}
newAft := func(text string, fail bool) leafnodes.BasicNode {
return leafnodes.NewAfterEachNode(newBody(text, fail), codeLocation, 0, failer, 0)
}
newJusBef := func(text string, fail bool) leafnodes.BasicNode {
return leafnodes.NewJustBeforeEachNode(newBody(text, fail), codeLocation, 0, failer, 0)
}
newContainer := func(text string, flag types.FlagType, setupNodes ...leafnodes.BasicNode) *containernode.ContainerNode {
c := containernode.New(text, flag, codeLocation)
for _, node := range setupNodes {
c.PushSetupNode(node)
}
return c
}
containers := func(containers ...*containernode.ContainerNode) []*containernode.ContainerNode {
return containers
}
BeforeEach(func() {
buffer = gbytes.NewBuffer()
failer = Failer.New()
codeLocation = codelocation.New(0)
nodesThatRan = []string{}
})
Describe("marking specs focused and pending", func() {
It("should satisfy various caes", func() {
cases := []struct {
ContainerFlags []types.FlagType
SubjectFlag types.FlagType
Pending bool
Focused bool
}{
{[]types.FlagType{}, noneFlag, false, false},
{[]types.FlagType{}, focusedFlag, false, true},
{[]types.FlagType{}, pendingFlag, true, false},
{[]types.FlagType{noneFlag}, noneFlag, false, false},
{[]types.FlagType{focusedFlag}, noneFlag, false, true},
{[]types.FlagType{pendingFlag}, noneFlag, true, false},
{[]types.FlagType{noneFlag}, focusedFlag, false, true},
{[]types.FlagType{focusedFlag}, focusedFlag, false, true},
{[]types.FlagType{pendingFlag}, focusedFlag, true, true},
{[]types.FlagType{noneFlag}, pendingFlag, true, false},
{[]types.FlagType{focusedFlag}, pendingFlag, true, true},
{[]types.FlagType{pendingFlag}, pendingFlag, true, false},
{[]types.FlagType{focusedFlag, noneFlag}, noneFlag, false, true},
{[]types.FlagType{noneFlag, focusedFlag}, noneFlag, false, true},
{[]types.FlagType{pendingFlag, noneFlag}, noneFlag, true, false},
{[]types.FlagType{noneFlag, pendingFlag}, noneFlag, true, false},
{[]types.FlagType{focusedFlag, pendingFlag}, noneFlag, true, true},
}
for i, c := range cases {
subject := newIt("it node", c.SubjectFlag, false)
containers := []*containernode.ContainerNode{}
for _, flag := range c.ContainerFlags {
containers = append(containers, newContainer("container", flag))
}
spec := New(subject, containers, false)
Ω(spec.Pending()).Should(Equal(c.Pending), "Case %d: %#v", i, c)
Ω(spec.Focused()).Should(Equal(c.Focused), "Case %d: %#v", i, c)
if c.Pending {
Ω(spec.Summary("").State).Should(Equal(types.SpecStatePending))
}
}
})
})
Describe("Skip", func() {
It("should be skipped", func() {
spec := New(newIt("it node", noneFlag, false), containers(newContainer("container", noneFlag)), false)
Ω(spec.Skipped()).Should(BeFalse())
spec.Skip()
Ω(spec.Skipped()).Should(BeTrue())
Ω(spec.Summary("").State).Should(Equal(types.SpecStateSkipped))
})
})
Describe("IsMeasurement", func() {
It("should be true if the subject is a measurement node", func() {
spec := New(newIt("it node", noneFlag, false), containers(newContainer("container", noneFlag)), false)
Ω(spec.IsMeasurement()).Should(BeFalse())
Ω(spec.Summary("").IsMeasurement).Should(BeFalse())
Ω(spec.Summary("").NumberOfSamples).Should(Equal(1))
spec = New(newMeasure("measure node", noneFlag, false, 10), containers(newContainer("container", noneFlag)), false)
Ω(spec.IsMeasurement()).Should(BeTrue())
Ω(spec.Summary("").IsMeasurement).Should(BeTrue())
Ω(spec.Summary("").NumberOfSamples).Should(Equal(10))
})
})
Describe("Passed", func() {
It("should pass when the subject passed", func() {
spec := New(newIt("it node", noneFlag, false), containers(), false)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeTrue())
Ω(spec.Failed()).Should(BeFalse())
Ω(spec.Summary("").State).Should(Equal(types.SpecStatePassed))
Ω(spec.Summary("").Failure).Should(BeZero())
})
})
Describe("Failed", func() {
It("should be failed if the failure was panic", func() {
spec := New(newItWithBody("panicky it", func() {
panic("bam")
}), containers(), false)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(spec.Summary("").State).Should(Equal(types.SpecStatePanicked))
Ω(spec.Summary("").Failure.Message).Should(Equal("Test Panicked"))
Ω(spec.Summary("").Failure.ForwardedPanic).Should(Equal("bam"))
})
It("should be failed if the failure was a timeout", func() {
spec := New(newItWithBody("sleepy it", func(done Done) {}), containers(), false)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(spec.Summary("").State).Should(Equal(types.SpecStateTimedOut))
Ω(spec.Summary("").Failure.Message).Should(Equal("Timed out"))
})
It("should be failed if the failure was... a failure", func() {
spec := New(newItWithBody("failing it", func() {
failer.Fail("bam", codeLocation)
}), containers(), false)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(spec.Summary("").State).Should(Equal(types.SpecStateFailed))
Ω(spec.Summary("").Failure.Message).Should(Equal("bam"))
})
})
Describe("Concatenated string", func() {
It("should concatenate the texts of the containers and the subject", func() {
spec := New(
newIt("it node", noneFlag, false),
containers(
newContainer("outer container", noneFlag),
newContainer("inner container", noneFlag),
),
false,
)
Ω(spec.ConcatenatedString()).Should(Equal("outer container inner container it node"))
})
})
Describe("running it specs", func() {
Context("with just an it", func() {
Context("that succeeds", func() {
It("should run the it and report on its success", func() {
spec := New(newIt("it node", noneFlag, false), containers(), false)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeTrue())
Ω(spec.Failed()).Should(BeFalse())
Ω(nodesThatRan).Should(Equal([]string{"it node"}))
})
})
Context("that fails", func() {
It("should run the it and report on its success", func() {
spec := New(newIt("it node", noneFlag, true), containers(), false)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(spec.Summary("").Failure.Message).Should(Equal("it node"))
Ω(nodesThatRan).Should(Equal([]string{"it node"}))
})
})
})
Context("with a full set of setup nodes", func() {
var failingNodes map[string]bool
BeforeEach(func() {
failingNodes = map[string]bool{}
})
JustBeforeEach(func() {
spec = New(
newIt("it node", noneFlag, failingNodes["it node"]),
containers(
newContainer("outer container", noneFlag,
newBef("outer bef A", failingNodes["outer bef A"]),
newBef("outer bef B", failingNodes["outer bef B"]),
newJusBef("outer jusbef A", failingNodes["outer jusbef A"]),
newJusBef("outer jusbef B", failingNodes["outer jusbef B"]),
newAft("outer aft A", failingNodes["outer aft A"]),
newAft("outer aft B", failingNodes["outer aft B"]),
),
newContainer("inner container", noneFlag,
newBef("inner bef A", failingNodes["inner bef A"]),
newBef("inner bef B", failingNodes["inner bef B"]),
newJusBef("inner jusbef A", failingNodes["inner jusbef A"]),
newJusBef("inner jusbef B", failingNodes["inner jusbef B"]),
newAft("inner aft A", failingNodes["inner aft A"]),
newAft("inner aft B", failingNodes["inner aft B"]),
),
),
false,
)
spec.Run(buffer)
})
Context("that all pass", func() {
It("should walk through the nodes in the correct order", func() {
Ω(spec.Passed()).Should(BeTrue())
Ω(spec.Failed()).Should(BeFalse())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"inner bef A",
"inner bef B",
"outer jusbef A",
"outer jusbef B",
"inner jusbef A",
"inner jusbef B",
"it node",
"inner aft A",
"inner aft B",
"outer aft A",
"outer aft B",
}))
})
})
Context("when the subject fails", func() {
BeforeEach(func() {
failingNodes["it node"] = true
})
It("should run the afters", func() {
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"inner bef A",
"inner bef B",
"outer jusbef A",
"outer jusbef B",
"inner jusbef A",
"inner jusbef B",
"it node",
"inner aft A",
"inner aft B",
"outer aft A",
"outer aft B",
}))
Ω(spec.Summary("").Failure.Message).Should(Equal("it node"))
})
})
Context("when an inner before fails", func() {
BeforeEach(func() {
failingNodes["inner bef A"] = true
})
It("should not run any other befores, but it should run the subsequent afters", func() {
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"inner bef A",
"inner aft A",
"inner aft B",
"outer aft A",
"outer aft B",
}))
Ω(spec.Summary("").Failure.Message).Should(Equal("inner bef A"))
})
})
Context("when an outer before fails", func() {
BeforeEach(func() {
failingNodes["outer bef B"] = true
})
It("should not run any other befores, but it should run the subsequent afters", func() {
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"outer aft A",
"outer aft B",
}))
Ω(spec.Summary("").Failure.Message).Should(Equal("outer bef B"))
})
})
Context("when an after fails", func() {
BeforeEach(func() {
failingNodes["inner aft B"] = true
})
It("should run all other afters, but mark the test as failed", func() {
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"inner bef A",
"inner bef B",
"outer jusbef A",
"outer jusbef B",
"inner jusbef A",
"inner jusbef B",
"it node",
"inner aft A",
"inner aft B",
"outer aft A",
"outer aft B",
}))
Ω(spec.Summary("").Failure.Message).Should(Equal("inner aft B"))
})
})
Context("when a just before each fails", func() {
BeforeEach(func() {
failingNodes["outer jusbef B"] = true
})
It("should run the afters, but not the subject", func() {
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"inner bef A",
"inner bef B",
"outer jusbef A",
"outer jusbef B",
"inner aft A",
"inner aft B",
"outer aft A",
"outer aft B",
}))
Ω(spec.Summary("").Failure.Message).Should(Equal("outer jusbef B"))
})
})
Context("when an after fails after an earlier node has failed", func() {
BeforeEach(func() {
failingNodes["it node"] = true
failingNodes["inner aft B"] = true
})
It("should record the earlier failure", func() {
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"outer bef A",
"outer bef B",
"inner bef A",
"inner bef B",
"outer jusbef A",
"outer jusbef B",
"inner jusbef A",
"inner jusbef B",
"it node",
"inner aft A",
"inner aft B",
"outer aft A",
"outer aft B",
}))
Ω(spec.Summary("").Failure.Message).Should(Equal("it node"))
})
})
})
})
Describe("running measurement specs", func() {
Context("when the measurement succeeds", func() {
It("should run N samples", func() {
spec = New(
newMeasure("measure node", noneFlag, false, 3),
containers(
newContainer("container", noneFlag,
newBef("bef A", false),
newJusBef("jusbef A", false),
newAft("aft A", false),
),
),
false,
)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeTrue())
Ω(spec.Failed()).Should(BeFalse())
Ω(nodesThatRan).Should(Equal([]string{
"bef A",
"jusbef A",
"measure node",
"aft A",
"bef A",
"jusbef A",
"measure node",
"aft A",
"bef A",
"jusbef A",
"measure node",
"aft A",
}))
})
})
Context("when the measurement fails", func() {
It("should bail after the failure occurs", func() {
spec = New(
newMeasure("measure node", noneFlag, true, 3),
containers(
newContainer("container", noneFlag,
newBef("bef A", false),
newJusBef("jusbef A", false),
newAft("aft A", false),
),
),
false,
)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeFalse())
Ω(spec.Failed()).Should(BeTrue())
Ω(nodesThatRan).Should(Equal([]string{
"bef A",
"jusbef A",
"measure node",
"aft A",
}))
})
})
})
Describe("Summary", func() {
var (
subjectCodeLocation types.CodeLocation
outerContainerCodeLocation types.CodeLocation
innerContainerCodeLocation types.CodeLocation
summary *types.SpecSummary
)
BeforeEach(func() {
subjectCodeLocation = codelocation.New(0)
outerContainerCodeLocation = codelocation.New(0)
innerContainerCodeLocation = codelocation.New(0)
spec = New(
leafnodes.NewItNode("it node", func() {
time.Sleep(10 * time.Millisecond)
}, noneFlag, subjectCodeLocation, 0, failer, 0),
containers(
containernode.New("outer container", noneFlag, outerContainerCodeLocation),
containernode.New("inner container", noneFlag, innerContainerCodeLocation),
),
false,
)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeTrue())
summary = spec.Summary("suite id")
})
It("should have the suite id", func() {
Ω(summary.SuiteID).Should(Equal("suite id"))
})
It("should have the component texts and code locations", func() {
Ω(summary.ComponentTexts).Should(Equal([]string{"outer container", "inner container", "it node"}))
Ω(summary.ComponentCodeLocations).Should(Equal([]types.CodeLocation{outerContainerCodeLocation, innerContainerCodeLocation, subjectCodeLocation}))
})
It("should have a runtime", func() {
Ω(summary.RunTime).Should(BeNumerically(">=", 10*time.Millisecond))
})
It("should not be a measurement, or have a measurement summary", func() {
Ω(summary.IsMeasurement).Should(BeFalse())
Ω(summary.Measurements).Should(BeEmpty())
})
})
Describe("Summaries for measurements", func() {
var summary *types.SpecSummary
BeforeEach(func() {
spec = New(leafnodes.NewMeasureNode("measure node", func(b Benchmarker) {
b.RecordValue("a value", 7, "some info")
}, noneFlag, codeLocation, 4, failer, 0), containers(), false)
spec.Run(buffer)
Ω(spec.Passed()).Should(BeTrue())
summary = spec.Summary("suite id")
})
It("should include the number of samples", func() {
Ω(summary.NumberOfSamples).Should(Equal(4))
})
It("should be a measurement", func() {
Ω(summary.IsMeasurement).Should(BeTrue())
})
It("should have the measurements report", func() {
Ω(summary.Measurements).Should(HaveKey("a value"))
report := summary.Measurements["a value"]
Ω(report.Name).Should(Equal("a value"))
Ω(report.Info).Should(Equal("some info"))
Ω(report.Results).Should(Equal([]float64{7, 7, 7, 7}))
})
})
Describe("When told to emit progress", func() {
It("should emit progress to the writer as it runs Befores, JustBefores, Afters, and Its", func() {
spec = New(
newIt("it node", noneFlag, false),
containers(
newContainer("outer container", noneFlag,
newBef("outer bef A", false),
newJusBef("outer jusbef A", false),
newAft("outer aft A", false),
),
newContainer("inner container", noneFlag,
newBef("inner bef A", false),
newJusBef("inner jusbef A", false),
newAft("inner aft A", false),
),
),
true,
)
spec.Run(buffer)
Ω(buffer).Should(gbytes.Say(`\[BeforeEach\] outer container`))
Ω(buffer).Should(gbytes.Say(`\[BeforeEach\] inner container`))
Ω(buffer).Should(gbytes.Say(`\[JustBeforeEach\] outer container`))
Ω(buffer).Should(gbytes.Say(`\[JustBeforeEach\] inner container`))
Ω(buffer).Should(gbytes.Say(`\[It\] it node`))
Ω(buffer).Should(gbytes.Say(`\[AfterEach\] inner container`))
Ω(buffer).Should(gbytes.Say(`\[AfterEach\] outer container`))
})
It("should emit progress to the writer as it runs Befores, JustBefores, Afters, and Measures", func() {
spec = New(
newMeasure("measure node", noneFlag, false, 2),
containers(),
true,
)
spec.Run(buffer)
Ω(buffer).Should(gbytes.Say(`\[Measure\] measure node`))
Ω(buffer).Should(gbytes.Say(`\[Measure\] measure node`))
})
})
})

122
vendor/github.com/onsi/ginkgo/internal/spec/specs.go generated vendored Normal file
View File

@@ -0,0 +1,122 @@
package spec
import (
"math/rand"
"regexp"
"sort"
)
type Specs struct {
specs []*Spec
numberOfOriginalSpecs int
hasProgrammaticFocus bool
}
func NewSpecs(specs []*Spec) *Specs {
return &Specs{
specs: specs,
numberOfOriginalSpecs: len(specs),
}
}
func (e *Specs) Specs() []*Spec {
return e.specs
}
func (e *Specs) NumberOfOriginalSpecs() int {
return e.numberOfOriginalSpecs
}
func (e *Specs) HasProgrammaticFocus() bool {
return e.hasProgrammaticFocus
}
func (e *Specs) Shuffle(r *rand.Rand) {
sort.Sort(e)
permutation := r.Perm(len(e.specs))
shuffledSpecs := make([]*Spec, len(e.specs))
for i, j := range permutation {
shuffledSpecs[i] = e.specs[j]
}
e.specs = shuffledSpecs
}
func (e *Specs) ApplyFocus(description string, focusString string, skipString string) {
if focusString == "" && skipString == "" {
e.applyProgrammaticFocus()
} else {
e.applyRegExpFocus(description, focusString, skipString)
}
}
func (e *Specs) applyProgrammaticFocus() {
e.hasProgrammaticFocus = false
for _, spec := range e.specs {
if spec.Focused() && !spec.Pending() {
e.hasProgrammaticFocus = true
break
}
}
if e.hasProgrammaticFocus {
for _, spec := range e.specs {
if !spec.Focused() {
spec.Skip()
}
}
}
}
func (e *Specs) applyRegExpFocus(description string, focusString string, skipString string) {
for _, spec := range e.specs {
matchesFocus := true
matchesSkip := false
toMatch := []byte(description + " " + spec.ConcatenatedString())
if focusString != "" {
focusFilter := regexp.MustCompile(focusString)
matchesFocus = focusFilter.Match([]byte(toMatch))
}
if skipString != "" {
skipFilter := regexp.MustCompile(skipString)
matchesSkip = skipFilter.Match([]byte(toMatch))
}
if !matchesFocus || matchesSkip {
spec.Skip()
}
}
}
func (e *Specs) SkipMeasurements() {
for _, spec := range e.specs {
if spec.IsMeasurement() {
spec.Skip()
}
}
}
func (e *Specs) TrimForParallelization(total int, node int) {
startIndex, count := ParallelizedIndexRange(len(e.specs), total, node)
if count == 0 {
e.specs = make([]*Spec, 0)
} else {
e.specs = e.specs[startIndex : startIndex+count]
}
}
//sort.Interface
func (e *Specs) Len() int {
return len(e.specs)
}
func (e *Specs) Less(i, j int) bool {
return e.specs[i].ConcatenatedString() < e.specs[j].ConcatenatedString()
}
func (e *Specs) Swap(i, j int) {
e.specs[i], e.specs[j] = e.specs[j], e.specs[i]
}

View File

@@ -0,0 +1,335 @@
package spec_test
import (
"math/rand"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/internal/spec"
. "github.com/onsi/gomega"
"github.com/onsi/ginkgo/internal/codelocation"
"github.com/onsi/ginkgo/internal/containernode"
"github.com/onsi/ginkgo/internal/leafnodes"
"github.com/onsi/ginkgo/types"
)
var _ = Describe("Specs", func() {
var specs *Specs
newSpec := func(text string, flag types.FlagType) *Spec {
subject := leafnodes.NewItNode(text, func() {}, flag, codelocation.New(0), 0, nil, 0)
return New(subject, []*containernode.ContainerNode{}, false)
}
newMeasureSpec := func(text string, flag types.FlagType) *Spec {
subject := leafnodes.NewMeasureNode(text, func(Benchmarker) {}, flag, codelocation.New(0), 0, nil, 0)
return New(subject, []*containernode.ContainerNode{}, false)
}
newSpecs := func(args ...interface{}) *Specs {
specs := []*Spec{}
for index := 0; index < len(args)-1; index += 2 {
specs = append(specs, newSpec(args[index].(string), args[index+1].(types.FlagType)))
}
return NewSpecs(specs)
}
specTexts := func(specs *Specs) []string {
texts := []string{}
for _, spec := range specs.Specs() {
texts = append(texts, spec.ConcatenatedString())
}
return texts
}
willRunTexts := func(specs *Specs) []string {
texts := []string{}
for _, spec := range specs.Specs() {
if !(spec.Skipped() || spec.Pending()) {
texts = append(texts, spec.ConcatenatedString())
}
}
return texts
}
skippedTexts := func(specs *Specs) []string {
texts := []string{}
for _, spec := range specs.Specs() {
if spec.Skipped() {
texts = append(texts, spec.ConcatenatedString())
}
}
return texts
}
pendingTexts := func(specs *Specs) []string {
texts := []string{}
for _, spec := range specs.Specs() {
if spec.Pending() {
texts = append(texts, spec.ConcatenatedString())
}
}
return texts
}
Describe("Shuffling specs", func() {
It("should shuffle the specs using the passed in randomizer", func() {
specs17 := newSpecs("C", noneFlag, "A", noneFlag, "B", noneFlag)
specs17.Shuffle(rand.New(rand.NewSource(17)))
texts17 := specTexts(specs17)
specs17Again := newSpecs("C", noneFlag, "A", noneFlag, "B", noneFlag)
specs17Again.Shuffle(rand.New(rand.NewSource(17)))
texts17Again := specTexts(specs17Again)
specs15 := newSpecs("C", noneFlag, "A", noneFlag, "B", noneFlag)
specs15.Shuffle(rand.New(rand.NewSource(15)))
texts15 := specTexts(specs15)
specsUnshuffled := newSpecs("C", noneFlag, "A", noneFlag, "B", noneFlag)
textsUnshuffled := specTexts(specsUnshuffled)
Ω(textsUnshuffled).Should(Equal([]string{"C", "A", "B"}))
Ω(texts17).Should(Equal(texts17Again))
Ω(texts17).ShouldNot(Equal(texts15))
Ω(texts17).ShouldNot(Equal(textsUnshuffled))
Ω(texts15).ShouldNot(Equal(textsUnshuffled))
Ω(texts17).Should(HaveLen(3))
Ω(texts17).Should(ContainElement("A"))
Ω(texts17).Should(ContainElement("B"))
Ω(texts17).Should(ContainElement("C"))
Ω(texts15).Should(HaveLen(3))
Ω(texts15).Should(ContainElement("A"))
Ω(texts15).Should(ContainElement("B"))
Ω(texts15).Should(ContainElement("C"))
})
})
Describe("with no programmatic focus", func() {
BeforeEach(func() {
specs = newSpecs("A1", noneFlag, "A2", noneFlag, "B1", noneFlag, "B2", pendingFlag)
specs.ApplyFocus("", "", "")
})
It("should not report as having programmatic specs", func() {
Ω(specs.HasProgrammaticFocus()).Should(BeFalse())
})
})
Describe("Applying focus/skip", func() {
var description, focusString, skipString string
BeforeEach(func() {
description, focusString, skipString = "", "", ""
})
JustBeforeEach(func() {
specs = newSpecs("A1", focusedFlag, "A2", noneFlag, "B1", focusedFlag, "B2", pendingFlag)
specs.ApplyFocus(description, focusString, skipString)
})
Context("with neither a focus string nor a skip string", func() {
It("should apply the programmatic focus", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"A1", "B1"}))
Ω(skippedTexts(specs)).Should(Equal([]string{"A2", "B2"}))
Ω(pendingTexts(specs)).Should(BeEmpty())
})
It("should report as having programmatic specs", func() {
Ω(specs.HasProgrammaticFocus()).Should(BeTrue())
})
})
Context("with a focus regexp", func() {
BeforeEach(func() {
focusString = "A"
})
It("should override the programmatic focus", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"A1", "A2"}))
Ω(skippedTexts(specs)).Should(Equal([]string{"B1", "B2"}))
Ω(pendingTexts(specs)).Should(BeEmpty())
})
It("should not report as having programmatic specs", func() {
Ω(specs.HasProgrammaticFocus()).Should(BeFalse())
})
})
Context("with a focus regexp", func() {
BeforeEach(func() {
focusString = "B"
})
It("should not override any pendings", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"B1"}))
Ω(skippedTexts(specs)).Should(Equal([]string{"A1", "A2"}))
Ω(pendingTexts(specs)).Should(Equal([]string{"B2"}))
})
})
Context("with a description", func() {
BeforeEach(func() {
description = "C"
focusString = "C"
})
It("should include the description in the focus determination", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"A1", "A2", "B1"}))
Ω(skippedTexts(specs)).Should(BeEmpty())
Ω(pendingTexts(specs)).Should(Equal([]string{"B2"}))
})
})
Context("with a description", func() {
BeforeEach(func() {
description = "C"
skipString = "C"
})
It("should include the description in the focus determination", func() {
Ω(willRunTexts(specs)).Should(BeEmpty())
Ω(skippedTexts(specs)).Should(Equal([]string{"A1", "A2", "B1", "B2"}))
Ω(pendingTexts(specs)).Should(BeEmpty())
})
})
Context("with a skip regexp", func() {
BeforeEach(func() {
skipString = "A"
})
It("should override the programmatic focus", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"B1"}))
Ω(skippedTexts(specs)).Should(Equal([]string{"A1", "A2"}))
Ω(pendingTexts(specs)).Should(Equal([]string{"B2"}))
})
It("should not report as having programmatic specs", func() {
Ω(specs.HasProgrammaticFocus()).Should(BeFalse())
})
})
Context("with both a focus and a skip regexp", func() {
BeforeEach(func() {
focusString = "1"
skipString = "B"
})
It("should AND the two", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"A1"}))
Ω(skippedTexts(specs)).Should(Equal([]string{"A2", "B1", "B2"}))
Ω(pendingTexts(specs)).Should(BeEmpty())
})
It("should not report as having programmatic specs", func() {
Ω(specs.HasProgrammaticFocus()).Should(BeFalse())
})
})
})
Describe("With a focused spec within a pending context and a pending spec within a focused context", func() {
BeforeEach(func() {
pendingInFocused := New(
leafnodes.NewItNode("PendingInFocused", func() {}, pendingFlag, codelocation.New(0), 0, nil, 0),
[]*containernode.ContainerNode{
containernode.New("", focusedFlag, codelocation.New(0)),
}, false)
focusedInPending := New(
leafnodes.NewItNode("FocusedInPending", func() {}, focusedFlag, codelocation.New(0), 0, nil, 0),
[]*containernode.ContainerNode{
containernode.New("", pendingFlag, codelocation.New(0)),
}, false)
specs = NewSpecs([]*Spec{
newSpec("A", noneFlag),
newSpec("B", noneFlag),
pendingInFocused,
focusedInPending,
})
specs.ApplyFocus("", "", "")
})
It("should not have a programmatic focus and should run all tests", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"A", "B"}))
Ω(skippedTexts(specs)).Should(BeEmpty())
Ω(pendingTexts(specs)).Should(ConsistOf(ContainSubstring("PendingInFocused"), ContainSubstring("FocusedInPending")))
})
})
Describe("skipping measurements", func() {
BeforeEach(func() {
specs = NewSpecs([]*Spec{
newSpec("A", noneFlag),
newSpec("B", noneFlag),
newSpec("C", pendingFlag),
newMeasureSpec("measurementA", noneFlag),
newMeasureSpec("measurementB", pendingFlag),
})
})
It("should skip measurements", func() {
Ω(willRunTexts(specs)).Should(Equal([]string{"A", "B", "measurementA"}))
Ω(skippedTexts(specs)).Should(BeEmpty())
Ω(pendingTexts(specs)).Should(Equal([]string{"C", "measurementB"}))
specs.SkipMeasurements()
Ω(willRunTexts(specs)).Should(Equal([]string{"A", "B"}))
Ω(skippedTexts(specs)).Should(Equal([]string{"measurementA", "measurementB"}))
Ω(pendingTexts(specs)).Should(Equal([]string{"C"}))
})
})
Describe("when running tests in parallel", func() {
It("should select out a subset of the tests", func() {
specsNode1 := newSpecs("A", noneFlag, "B", noneFlag, "C", noneFlag, "D", noneFlag, "E", noneFlag)
specsNode2 := newSpecs("A", noneFlag, "B", noneFlag, "C", noneFlag, "D", noneFlag, "E", noneFlag)
specsNode3 := newSpecs("A", noneFlag, "B", noneFlag, "C", noneFlag, "D", noneFlag, "E", noneFlag)
specsNode1.TrimForParallelization(3, 1)
specsNode2.TrimForParallelization(3, 2)
specsNode3.TrimForParallelization(3, 3)
Ω(willRunTexts(specsNode1)).Should(Equal([]string{"A", "B"}))
Ω(willRunTexts(specsNode2)).Should(Equal([]string{"C", "D"}))
Ω(willRunTexts(specsNode3)).Should(Equal([]string{"E"}))
Ω(specsNode1.Specs()).Should(HaveLen(2))
Ω(specsNode2.Specs()).Should(HaveLen(2))
Ω(specsNode3.Specs()).Should(HaveLen(1))
Ω(specsNode1.NumberOfOriginalSpecs()).Should(Equal(5))
Ω(specsNode2.NumberOfOriginalSpecs()).Should(Equal(5))
Ω(specsNode3.NumberOfOriginalSpecs()).Should(Equal(5))
})
Context("when way too many nodes are used", func() {
It("should return 0 specs", func() {
specsNode1 := newSpecs("A", noneFlag, "B", noneFlag)
specsNode2 := newSpecs("A", noneFlag, "B", noneFlag)
specsNode3 := newSpecs("A", noneFlag, "B", noneFlag)
specsNode1.TrimForParallelization(3, 1)
specsNode2.TrimForParallelization(3, 2)
specsNode3.TrimForParallelization(3, 3)
Ω(willRunTexts(specsNode1)).Should(Equal([]string{"A"}))
Ω(willRunTexts(specsNode2)).Should(Equal([]string{"B"}))
Ω(willRunTexts(specsNode3)).Should(BeEmpty())
Ω(specsNode1.Specs()).Should(HaveLen(1))
Ω(specsNode2.Specs()).Should(HaveLen(1))
Ω(specsNode3.Specs()).Should(HaveLen(0))
Ω(specsNode1.NumberOfOriginalSpecs()).Should(Equal(2))
Ω(specsNode2.NumberOfOriginalSpecs()).Should(Equal(2))
Ω(specsNode3.NumberOfOriginalSpecs()).Should(Equal(2))
})
})
})
})