File: gojson.go

package info (click to toggle)
golang-github-onsi-ginkgo-v2 2.27.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,340 kB
  • sloc: javascript: 65; makefile: 23; sh: 14
file content (158 lines) | stat: -rw-r--r-- 3,888 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package reporters

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/onsi/ginkgo/v2/types"
	"golang.org/x/tools/go/packages"
)

func ptr[T any](in T) *T {
	return &in
}

type encoder interface {
	Encode(v any) error
}

// gojsonEvent matches the format from go internals
// https://github.com/golang/go/blob/master/src/cmd/internal/test2json/test2json.go#L31-L41
// https://pkg.go.dev/cmd/test2json
type gojsonEvent struct {
	Time        *time.Time `json:",omitempty"`
	Action      GoJSONAction
	Package     string   `json:",omitempty"`
	Test        string   `json:",omitempty"`
	Elapsed     *float64 `json:",omitempty"`
	Output      *string  `json:",omitempty"`
	FailedBuild string   `json:",omitempty"`
}

type GoJSONAction string

const (
	// start  - the test binary is about to be executed
	GoJSONStart GoJSONAction = "start"
	// run    - the test has started running
	GoJSONRun GoJSONAction = "run"
	// pause  - the test has been paused
	GoJSONPause GoJSONAction = "pause"
	// cont   - the test has continued running
	GoJSONCont GoJSONAction = "cont"
	// pass   - the test passed
	GoJSONPass GoJSONAction = "pass"
	// bench  - the benchmark printed log output but did not fail
	GoJSONBench GoJSONAction = "bench"
	// fail   - the test or benchmark failed
	GoJSONFail GoJSONAction = "fail"
	// output - the test printed output
	GoJSONOutput GoJSONAction = "output"
	// skip   - the test was skipped or the package contained no tests
	GoJSONSkip GoJSONAction = "skip"
)

func goJSONActionFromSpecState(state types.SpecState) GoJSONAction {
	switch state {
	case types.SpecStateInvalid:
		return GoJSONFail
	case types.SpecStatePending:
		return GoJSONSkip
	case types.SpecStateSkipped:
		return GoJSONSkip
	case types.SpecStatePassed:
		return GoJSONPass
	case types.SpecStateFailed:
		return GoJSONFail
	case types.SpecStateAborted:
		return GoJSONFail
	case types.SpecStatePanicked:
		return GoJSONFail
	case types.SpecStateInterrupted:
		return GoJSONFail
	case types.SpecStateTimedout:
		return GoJSONFail
	default:
		panic("unexpected state should not happen")
	}
}

// gojsonReport wraps types.Report and calcualtes extra fields requires by gojson
type gojsonReport struct {
	o types.Report
	// Extra calculated fields
	goPkg string
	elapsed float64
}

func newReport(in types.Report) *gojsonReport {
	return &gojsonReport{
		o: in,
	}
}

func (r *gojsonReport) Fill() error {
	// NOTE: could the types.Report include the go package name?
	goPkg, err := suitePathToPkg(r.o.SuitePath)
	if err != nil {
		return err
	}
	r.goPkg = goPkg
	r.elapsed = r.o.RunTime.Seconds()
	return nil
}

// gojsonSpecReport wraps types.SpecReport and calculates extra fields required by gojson
type gojsonSpecReport struct {
	o types.SpecReport
	// extra calculated fields
	testName string
	elapsed float64
	action GoJSONAction
}

func newSpecReport(in types.SpecReport) *gojsonSpecReport {
	return &gojsonSpecReport{
		o: in,
	}
}

func (sr *gojsonSpecReport) Fill() error {
	sr.elapsed = sr.o.RunTime.Seconds()
	sr.testName = createTestName(sr.o)
	sr.action = goJSONActionFromSpecState(sr.o.State)
	return nil
}

func suitePathToPkg(dir string) (string, error) {
	cfg := &packages.Config{
		Mode: packages.NeedFiles | packages.NeedSyntax,
	}
	pkgs, err := packages.Load(cfg, dir)
	if err != nil {
		return "", err
	}
	if len(pkgs) != 1 {
		return "", errors.New("error")
	}
	return pkgs[0].ID, nil
}

func createTestName(spec types.SpecReport) string {
		name := fmt.Sprintf("[%s]", spec.LeafNodeType)
		if spec.FullText() != "" {
			name = name + " " + spec.FullText()
		}
		labels := spec.Labels()
		if len(labels) > 0 {
			name = name + " [" + strings.Join(labels, ", ") + "]"
		}
		semVerConstraints := spec.SemVerConstraints()
		if len(semVerConstraints) > 0 {
			name = name + " [" + strings.Join(semVerConstraints, ", ") + "]"
		}
		name = strings.TrimSpace(name)
		return name
}