aboutsummaryrefslogtreecommitdiffstats
path: root/syz-cluster/pkg/db/entities.go
blob: 563d7e4ecbb18c0d387d645f4a35dd0007401d4b (plain)
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"`
}