summaryrefslogtreecommitdiff
path: root/vendor/github.com/onsi/ginkgo/internal/spec/spec.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/onsi/ginkgo/internal/spec/spec.go')
-rw-r--r--vendor/github.com/onsi/ginkgo/internal/spec/spec.go247
1 files changed, 247 insertions, 0 deletions
diff --git a/vendor/github.com/onsi/ginkgo/internal/spec/spec.go b/vendor/github.com/onsi/ginkgo/internal/spec/spec.go
new file mode 100644
index 000000000..7fd68ee8e
--- /dev/null
+++ b/vendor/github.com/onsi/ginkgo/internal/spec/spec.go
@@ -0,0 +1,247 @@
+package spec
+
+import (
+ "fmt"
+ "io"
+ "time"
+
+ "sync"
+
+ "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
+ startTime time.Time
+ failure types.SpecFailure
+ previousFailures bool
+
+ stateMutex *sync.Mutex
+}
+
+func New(subject leafnodes.SubjectNode, containers []*containernode.ContainerNode, announceProgress bool) *Spec {
+ spec := &Spec{
+ subject: subject,
+ containers: containers,
+ focused: subject.Flag() == types.FlagTypeFocused,
+ announceProgress: announceProgress,
+ stateMutex: &sync.Mutex{},
+ }
+
+ 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.setState(types.SpecStatePending)
+ }
+}
+
+func (spec *Spec) Skip() {
+ spec.setState(types.SpecStateSkipped)
+}
+
+func (spec *Spec) Failed() bool {
+ return spec.getState() == types.SpecStateFailed || spec.getState() == types.SpecStatePanicked || spec.getState() == types.SpecStateTimedOut
+}
+
+func (spec *Spec) Passed() bool {
+ return spec.getState() == types.SpecStatePassed
+}
+
+func (spec *Spec) Flaked() bool {
+ return spec.getState() == types.SpecStatePassed && spec.previousFailures
+}
+
+func (spec *Spec) Pending() bool {
+ return spec.getState() == types.SpecStatePending
+}
+
+func (spec *Spec) Skipped() bool {
+ return spec.getState() == 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()
+
+ runTime := spec.runTime
+ if runTime == 0 && !spec.startTime.IsZero() {
+ runTime = time.Since(spec.startTime)
+ }
+
+ return &types.SpecSummary{
+ IsMeasurement: spec.IsMeasurement(),
+ NumberOfSamples: spec.subject.Samples(),
+ ComponentTexts: componentTexts,
+ ComponentCodeLocations: componentCodeLocations,
+ State: spec.getState(),
+ RunTime: 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) {
+ if spec.getState() == types.SpecStateFailed {
+ spec.previousFailures = true
+ }
+
+ spec.startTime = time.Now()
+ defer func() {
+ spec.runTime = time.Since(spec.startTime)
+ }()
+
+ for sample := 0; sample < spec.subject.Samples(); sample++ {
+ spec.runSample(sample, writer)
+
+ if spec.getState() != types.SpecStatePassed {
+ return
+ }
+ }
+}
+
+func (spec *Spec) getState() types.SpecState {
+ spec.stateMutex.Lock()
+ defer spec.stateMutex.Unlock()
+ return spec.state
+}
+
+func (spec *Spec) setState(state types.SpecState) {
+ spec.stateMutex.Lock()
+ defer spec.stateMutex.Unlock()
+ spec.state = state
+}
+
+func (spec *Spec) runSample(sample int, writer io.Writer) {
+ spec.setState(types.SpecStatePassed)
+ spec.failure = types.SpecFailure{}
+ innerMostContainerIndexToUnwind := -1
+
+ defer func() {
+ for i := innerMostContainerIndexToUnwind; i >= 0; i-- {
+ container := spec.containers[i]
+ for _, justAfterEach := range container.SetupNodesOfType(types.SpecComponentTypeJustAfterEach) {
+ spec.announceSetupNode(writer, "JustAfterEach", container, justAfterEach)
+ justAfterEachState, justAfterEachFailure := justAfterEach.Run()
+ if justAfterEachState != types.SpecStatePassed && spec.state == types.SpecStatePassed {
+ spec.state = justAfterEachState
+ spec.failure = justAfterEachFailure
+ }
+ }
+ }
+
+ 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.getState() == types.SpecStatePassed {
+ spec.setState(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)
+ s, f := beforeEach.Run()
+ spec.failure = f
+ spec.setState(s)
+ if spec.getState() != types.SpecStatePassed {
+ return
+ }
+ }
+ }
+
+ for _, container := range spec.containers {
+ for _, justBeforeEach := range container.SetupNodesOfType(types.SpecComponentTypeJustBeforeEach) {
+ spec.announceSetupNode(writer, "JustBeforeEach", container, justBeforeEach)
+ s, f := justBeforeEach.Run()
+ spec.failure = f
+ spec.setState(s)
+ if spec.getState() != types.SpecStatePassed {
+ return
+ }
+ }
+ }
+
+ spec.announceSubject(writer, spec.subject)
+ s, f := spec.subject.Run()
+ spec.failure = f
+ spec.setState(s)
+}
+
+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()
+}