File: report_entry.go

package info (click to toggle)
golang-github-onsi-ginkgo-v2 2.15.0-1~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 4,112 kB
  • sloc: javascript: 59; sh: 14; makefile: 7
file content (190 lines) | stat: -rw-r--r-- 5,709 bytes parent folder | download | duplicates (2)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package types

import (
	"encoding/json"
	"fmt"
	"time"
)

// ReportEntryValue wraps a report entry's value ensuring it can be encoded and decoded safely into reports
// and across the network connection when running in parallel
type ReportEntryValue struct {
	raw            interface{} //unexported to prevent gob from freaking out about unregistered structs
	AsJSON         string
	Representation string
}

func WrapEntryValue(value interface{}) ReportEntryValue {
	return ReportEntryValue{
		raw: value,
	}
}

func (rev ReportEntryValue) GetRawValue() interface{} {
	return rev.raw
}

func (rev ReportEntryValue) String() string {
	if rev.raw == nil {
		return ""
	}
	if colorableStringer, ok := rev.raw.(ColorableStringer); ok {
		return colorableStringer.ColorableString()
	}

	if stringer, ok := rev.raw.(fmt.Stringer); ok {
		return stringer.String()
	}
	if rev.Representation != "" {
		return rev.Representation
	}
	return fmt.Sprintf("%+v", rev.raw)
}

func (rev ReportEntryValue) MarshalJSON() ([]byte, error) {
	//All this to capture the representation at encoding-time, not creating time
	//This way users can Report on pointers and get their final values at reporting-time
	out := struct {
		AsJSON         string
		Representation string
	}{
		Representation: rev.String(),
	}
	asJSON, err := json.Marshal(rev.raw)
	if err != nil {
		return nil, err
	}
	out.AsJSON = string(asJSON)

	return json.Marshal(out)
}

func (rev *ReportEntryValue) UnmarshalJSON(data []byte) error {
	in := struct {
		AsJSON         string
		Representation string
	}{}
	err := json.Unmarshal(data, &in)
	if err != nil {
		return err
	}
	rev.AsJSON = in.AsJSON
	rev.Representation = in.Representation
	return json.Unmarshal([]byte(in.AsJSON), &(rev.raw))
}

func (rev ReportEntryValue) GobEncode() ([]byte, error) {
	return rev.MarshalJSON()
}

func (rev *ReportEntryValue) GobDecode(data []byte) error {
	return rev.UnmarshalJSON(data)
}

// ReportEntry captures information attached to `SpecReport` via `AddReportEntry`
type ReportEntry struct {
	// Visibility captures the visibility policy for this ReportEntry
	Visibility ReportEntryVisibility
	// Location captures the location of the AddReportEntry call
	Location CodeLocation

	Time             time.Time //need this for backwards compatibility
	TimelineLocation TimelineLocation

	// Name captures the name of this report
	Name string
	// Value captures the (optional) object passed into AddReportEntry - this can be
	// anything the user wants.  The value passed to AddReportEntry is wrapped in a ReportEntryValue to make
	// encoding/decoding the value easier.  To access the raw value call entry.GetRawValue()
	Value ReportEntryValue
}

// ColorableStringer is an interface that ReportEntry values can satisfy.  If they do then ColorableString() is used to generate their representation.
type ColorableStringer interface {
	ColorableString() string
}

// StringRepresentation() returns the string representation of the value associated with the ReportEntry --
// if value is nil, empty string is returned
// if value is a `ColorableStringer` then `Value.ColorableString()` is returned
// if value is a `fmt.Stringer` then `Value.String()` is returned
// otherwise the value is formatted with "%+v"
func (entry ReportEntry) StringRepresentation() string {
	return entry.Value.String()
}

// GetRawValue returns the Value object that was passed to AddReportEntry
// If called in-process this will be the same object that was passed into AddReportEntry.
// If used from a rehydrated JSON file _or_ in a ReportAfterSuite when running in parallel this will be
// a JSON-decoded {}interface.  If you want to reconstitute your original object you can decode the entry.Value.AsJSON
// field yourself.
func (entry ReportEntry) GetRawValue() interface{} {
	return entry.Value.GetRawValue()
}

func (entry ReportEntry) GetTimelineLocation() TimelineLocation {
	return entry.TimelineLocation
}

type ReportEntries []ReportEntry

func (re ReportEntries) HasVisibility(visibilities ...ReportEntryVisibility) bool {
	for _, entry := range re {
		if entry.Visibility.Is(visibilities...) {
			return true
		}
	}
	return false
}

func (re ReportEntries) WithVisibility(visibilities ...ReportEntryVisibility) ReportEntries {
	out := ReportEntries{}

	for _, entry := range re {
		if entry.Visibility.Is(visibilities...) {
			out = append(out, entry)
		}
	}

	return out
}

// ReportEntryVisibility governs the visibility of ReportEntries in Ginkgo's console reporter
type ReportEntryVisibility uint

const (
	// Always print out this ReportEntry
	ReportEntryVisibilityAlways ReportEntryVisibility = iota
	// Only print out this ReportEntry if the spec fails or if the test is run with -v
	ReportEntryVisibilityFailureOrVerbose
	// Never print out this ReportEntry (note that ReportEntrys are always encoded in machine readable reports (e.g. JSON, JUnit, etc.))
	ReportEntryVisibilityNever
)

var revEnumSupport = NewEnumSupport(map[uint]string{
	uint(ReportEntryVisibilityAlways):           "always",
	uint(ReportEntryVisibilityFailureOrVerbose): "failure-or-verbose",
	uint(ReportEntryVisibilityNever):            "never",
})

func (rev ReportEntryVisibility) String() string {
	return revEnumSupport.String(uint(rev))
}
func (rev *ReportEntryVisibility) UnmarshalJSON(b []byte) error {
	out, err := revEnumSupport.UnmarshJSON(b)
	*rev = ReportEntryVisibility(out)
	return err
}
func (rev ReportEntryVisibility) MarshalJSON() ([]byte, error) {
	return revEnumSupport.MarshJSON(uint(rev))
}

func (v ReportEntryVisibility) Is(visibilities ...ReportEntryVisibility) bool {
	for _, visibility := range visibilities {
		if v == visibility {
			return true
		}
	}

	return false
}