-
Notifications
You must be signed in to change notification settings - Fork 17
/
test.go
170 lines (144 loc) · 5.66 KB
/
test.go
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
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
package testevent
import (
"encoding/json"
"fmt"
"time"
"github.com/linuxboot/contest/pkg/event"
"github.com/linuxboot/contest/pkg/event/internal/querytools"
"github.com/linuxboot/contest/pkg/target"
"github.com/linuxboot/contest/pkg/types"
"github.com/linuxboot/contest/pkg/xcontext"
)
// Header models the header of a test event, which consists in metadata that defines the
// emitter of the events. The Header is under ConTest control and cannot be manipulated
// by the TestStep
type Header struct {
JobID types.JobID
RunID types.RunID
TestName string
TestAttempt uint32
TestStepLabel string
}
// Data models the data of a test event. It is populated by the TestStep
type Data struct {
Target *target.Target
EventName event.Name
Payload *json.RawMessage
}
// Event models an event object that can be emitted by a TestStep
type Event struct {
// SequenceID represents an ordering parameter between events of the same job
SequenceID uint64
EmitTime time.Time
Header *Header
Data *Data
}
// New creates a new Event with zero value header and data
func New(header *Header, data *Data) Event {
return Event{Header: header, Data: data}
}
// Query wraps information that are used to build queries for
// test events, on top of the common EventQuery fields
type Query struct {
event.Query
RunID types.RunID
TestName string
TestStepLabel string
}
// QueryField defines a function type used to set a field's value on Query objects
type QueryField interface {
queryFieldPointer(query *Query) interface{}
}
// QueryFields is a set of field values for a Query object
type QueryFields []QueryField
// BuildQuery compiles a Query from scratch using values of queryFields.
// It does basically just creates an empty query an applies queryFields to it.
func (queryFields QueryFields) BuildQuery() (*Query, error) {
query := &Query{}
for idx, queryField := range queryFields {
if err := querytools.ApplyQueryField(queryField.queryFieldPointer(query), queryField); err != nil {
return nil, fmt.Errorf("unable to apply field %d:%T(%v): %w", idx, queryField, queryField, err)
}
}
return query, nil
}
// BuildQuery compiles a Query from scratch using values of queryFields.
// It does basically just creates an empty query an applies queryFields to it.
func BuildQuery(queryFields ...QueryField) (*Query, error) {
return QueryFields(queryFields).BuildQuery()
}
type queryFieldJobID types.JobID
type queryFieldEventNames []event.Name
type queryFieldEmittedStartTime time.Time
type queryFieldEmittedEndTime time.Time
type queryFieldTestName string
type queryFieldTestStepLabel string
type queryFieldRunID types.RunID
// QueryJobID sets the JobID field of the Query object
func QueryJobID(jobID types.JobID) QueryField { return queryFieldJobID(jobID) }
func (value queryFieldJobID) queryFieldPointer(query *Query) interface{} { return &query.JobID }
// QueryEventNames the EventNames field of the Query object
func QueryEventNames(eventNames []event.Name) QueryField { return queryFieldEventNames(eventNames) }
func (value queryFieldEventNames) queryFieldPointer(query *Query) interface{} {
return &query.EventNames
}
// QueryEventName sets a single EventName field in the Query objec
func QueryEventName(eventName event.Name) QueryField { return queryFieldEventNames{eventName} }
// QueryEmittedStartTime sets the EmittedStartTime field of the Query object
func QueryEmittedStartTime(emittedStartTime time.Time) QueryField {
return queryFieldEmittedStartTime(emittedStartTime)
}
func (value queryFieldEmittedStartTime) queryFieldPointer(query *Query) interface{} {
return &query.EmittedStartTime
}
// QueryEmittedEndTime sets the EmittedEndTime field of the Query object
func QueryEmittedEndTime(emittedEndTime time.Time) QueryField {
return queryFieldEmittedEndTime(emittedEndTime)
}
func (value queryFieldEmittedEndTime) queryFieldPointer(query *Query) interface{} {
return &query.EmittedEndTime
}
// QueryTestName sets the TestName field of the Query object
func QueryTestName(testName string) QueryField {
return queryFieldTestName(testName)
}
func (value queryFieldTestName) queryFieldPointer(query *Query) interface{} { return &query.TestName }
// QueryTestStepLabel sets the TestStepLabel field of the Query object
func QueryTestStepLabel(testStepLabel string) QueryField {
return queryFieldTestStepLabel(testStepLabel)
}
func (value queryFieldTestStepLabel) queryFieldPointer(query *Query) interface{} {
return &query.TestStepLabel
}
// QueryRunID sets the RunID field of the Query object
func QueryRunID(runID types.RunID) QueryField {
return queryFieldRunID(runID)
}
func (value queryFieldRunID) queryFieldPointer(query *Query) interface{} { return &query.RunID }
// Emitter defines the interface that emitter objects must implement
type Emitter interface {
Emit(ctx xcontext.Context, event Data) error
}
// Fetcher defines the interface that fetcher objects must implement
type Fetcher interface {
Fetch(ctx xcontext.Context, fields ...QueryField) ([]Event, error)
}
// EmitterFetcher defines the interface that objects supporting emitting and fetching events must implement
type EmitterFetcher interface {
Emitter
Fetcher
}
func (h *Header) String() string {
return fmt.Sprintf("[%d %d %s %d %s]", h.JobID, h.RunID, h.TestName, h.TestAttempt, h.TestStepLabel)
}
func (d *Data) String() string {
ps := ""
if d.Payload != nil {
ps = fmt.Sprintf(" %q", d.Payload) //nolint SA5009 - works fine
}
return fmt.Sprintf("[%s %s%s]", d.Target, d.EventName, ps)
}