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
|
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package db
import (
"time"
"cloud.google.com/go/spanner"
)
type Series struct {
ID string `spanner:"ID"`
ExtID string `spanner:"ExtID"`
AuthorName string `spanner:"AuthorName"`
AuthorEmail string `spanner:"AuthorEmail"`
Title string `spanner:"Title"`
Link string `spanner:"Link"`
Version int64 `spanner:"Version"`
// In LKML patches, there are often hints at the target tree for the patch.
SubjectTags []string `spanner:"SubjectTags"`
PublishedAt time.Time `spanner:"PublishedAt"`
// TODO: we could ger rid of the field by using slightly more complicated SQL queries.
LatestSessionID spanner.NullString `spanner:"LatestSessionID"`
Cc []string `spanner:"Cc"`
}
func (s *Series) SetLatestSession(session *Session) {
s.LatestSessionID = spanner.NullString{StringVal: session.ID, Valid: true}
}
type Patch struct {
ID string `spanner:"ID"`
Seq int64 `spanner:"Seq"`
SeriesID string `spanner:"SeriesID"`
Title string `spanner:"Title"`
Link string `spanner:"Link"`
BodyURI string `spanner:"BodyURI"`
}
type Build struct {
ID string `spanner:"ID"`
TreeName string `spanner:"TreeName"`
TreeURL string `spanner:"TreeURL"`
CommitHash string `spanner:"CommitHash"`
CommitDate time.Time `spanner:"CommitDate"`
SeriesID spanner.NullString `spanner:"SeriesID"`
Arch string `spanner:"Arch"`
ConfigName string `spanner:"ConfigName"`
ConfigURI string `spanner:"ConfigURI"`
LogURI string `spanner:"LogURI"`
Status string `spanner:"Status"`
Compiler string `spanner:"Compiler"`
}
func (b *Build) SetSeriesID(val string) {
b.SeriesID = spanner.NullString{StringVal: val, Valid: true}
}
const (
BuildFailed string = "build_failed"
// BuiltNotTested string = "built"
// BuildTestFailed string = "tests_failed"
BuildSuccess string = "success"
)
type Session struct {
ID string `spanner:"ID"`
SeriesID string `spanner:"SeriesID"`
CreatedAt time.Time `spanner:"CreatedAt"`
StartedAt spanner.NullTime `spanner:"StartedAt"`
FinishedAt spanner.NullTime `spanner:"FinishedAt"`
SkipReason spanner.NullString `spanner:"SkipReason"`
LogURI string `spanner:"LogURI"`
TriageLogURI string `spanner:"TriageLogURI"`
Tags []string `spanner:"Tags"`
// TODO: to accept more specific fuzzing assignment,
// add Triager, BaseRepo, BaseCommit, Config fields.
}
type SessionStatus string
const (
SessionStatusWaiting SessionStatus = "waiting"
SessionStatusInProgress SessionStatus = "in progress"
SessionStatusFinished SessionStatus = "finished"
SessionStatusSkipped SessionStatus = "skipped"
// To be used in filters.
SessionStatusAny SessionStatus = ""
)
// It could have been a calculated field in Spanner, but the Go library for Spanner currently
// does not support read-only fields.
func (s *Session) Status() SessionStatus {
if s.StartedAt.IsNull() {
return SessionStatusWaiting
} else if s.FinishedAt.IsNull() {
return SessionStatusInProgress
} else if !s.SkipReason.IsNull() {
return SessionStatusSkipped
}
return SessionStatusFinished
}
func (s *Session) Duration() time.Duration {
if s.FinishedAt.IsNull() {
return 0
}
return s.FinishedAt.Time.Sub(s.StartedAt.Time).Truncate(time.Minute)
}
func (s *Session) SetStartedAt(t time.Time) {
s.StartedAt = spanner.NullTime{Time: t, Valid: true}
}
func (s *Session) SetFinishedAt(t time.Time) {
s.FinishedAt = spanner.NullTime{Time: t, Valid: true}
}
func (s *Session) SetSkipReason(reason string) {
s.SkipReason = spanner.NullString{StringVal: reason, Valid: true}
}
type SessionTest struct {
SessionID string `spanner:"SessionID"`
BaseBuildID spanner.NullString `spanner:"BaseBuildID"`
PatchedBuildID spanner.NullString `spanner:"PatchedBuildID"`
UpdatedAt time.Time `spanner:"UpdatedAt"`
TestName string `spanner:"TestName"`
Result string `spanner:"Result"`
LogURI string `spanner:"LogURI"`
ArtifactsArchiveURI string `spanner:"ArtifactsArchiveURI"`
}
type Finding struct {
ID string `spanner:"ID"`
SessionID string `spanner:"SessionID"`
TestName string `spanner:"TestName"`
Title string `spanner:"Title"`
ReportURI string `spanner:"ReportURI"`
LogURI string `spanner:"LogURI"`
SyzReproURI string `spanner:"SyzReproURI"`
SyzReproOptsURI string `spanner:"SyzReproOptsURI"`
CReproURI string `spanner:"CReproURI"`
InvalidatedAt spanner.NullTime `spanner:"InvalidatedAt"`
}
func (f *Finding) SetInvalidatedAt(t time.Time) {
f.InvalidatedAt = spanner.NullTime{Time: t, Valid: true}
}
type SessionReport struct {
ID string `spanner:"ID"`
SessionID string `spanner:"SessionID"`
ReportedAt spanner.NullTime `spanner:"ReportedAt"`
Moderation bool `spanner:"Moderation"`
Reporter string `spanner:"Reporter"`
}
func (s *SessionReport) SetReportedAt(t time.Time) {
s.ReportedAt = spanner.NullTime{Time: t, Valid: true}
}
type ReportReply struct {
MessageID string `spanner:"MessageID"`
ReportID string `spanner:"ReportID"`
Time time.Time `spanner:"Time"`
}
// BaseFinding collects all crashes observed on the base kernel tree.
// It will be used to avoid unnecessary bug reproduction attempts.
type BaseFinding struct {
CommitHash string `spanner:"CommitHash"`
Config string `spanner:"Config"`
Arch string `spanner:"Arch"`
Title string `spanner:"Title"`
}
|