blob: 3b9033a2924f602ed164e077be1365973943683b [file] [log] [blame]
Philipp Schradercdb5cfc2022-02-20 14:57:07 -08001package requests
2
3import (
4 "bytes"
5 "io"
6 "net/http"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -08007 "reflect"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -08008 "testing"
9
Philipp Schrader8747f1b2022-02-23 23:56:22 -080010 "github.com/frc971/971-Robot-Code/scouting/db"
Philipp Schraderd3fac192022-03-02 20:35:46 -080011 "github.com/frc971/971-Robot-Code/scouting/scraping"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080012 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080013 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
Philipp Schraderd3fac192022-03-02 20:35:46 -080014 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list"
15 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list_response"
Filip Kujawaf882e022022-12-14 13:14:08 -080016 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings"
17 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings_response"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080018 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
19 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
Filip Kujawaf882e022022-12-14 13:14:08 -080020 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes"
21 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes_response"
Philipp Schraderacf96232022-03-01 22:03:30 -080022 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting"
23 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070024 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
Milo Lin1d59f0c2022-06-22 20:30:58 -070025 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule"
26 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080027 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
Philipp Schrader30005e42022-03-06 13:53:58 -080028 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
Filip Kujawa210a03b2022-11-24 14:41:11 -080029 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking"
Alex Perry81f96ba2022-03-13 18:26:19 -070030 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes"
Milo Lin1d59f0c2022-06-22 20:30:58 -070031 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080032 "github.com/frc971/971-Robot-Code/scouting/webserver/server"
33 flatbuffers "github.com/google/flatbuffers/go"
34)
35
36// Validates that an unhandled address results in a 404.
37func Test404(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080038 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080039 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080040 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080041 scoutingServer.Start(8080)
42 defer scoutingServer.Stop()
43
44 resp, err := http.Get("http://localhost:8080/requests/foo")
45 if err != nil {
46 t.Fatalf("Failed to get data: %v", err)
47 }
48 if resp.StatusCode != http.StatusNotFound {
49 t.Fatalf("Expected error code 404, but got %d instead", resp.Status)
50 }
51}
52
53// Validates that we can submit new data scouting data.
54func TestSubmitDataScoutingError(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080055 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080056 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080057 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080058 scoutingServer.Start(8080)
59 defer scoutingServer.Stop()
60
61 resp, err := http.Post("http://localhost:8080/requests/submit/data_scouting", "application/octet-stream", bytes.NewReader([]byte("")))
62 if err != nil {
63 t.Fatalf("Failed to send request: %v", err)
64 }
65 if resp.StatusCode != http.StatusBadRequest {
66 t.Fatal("Unexpected status code. Got", resp.Status)
67 }
68
69 responseBytes, err := io.ReadAll(resp.Body)
70 if err != nil {
71 t.Fatal("Failed to read response bytes:", err)
72 }
73 errorResponse := error_response.GetRootAsErrorResponse(responseBytes, 0)
74
75 errorMessage := string(errorResponse.ErrorMessage())
76 if errorMessage != "Failed to parse SubmitDataScouting: runtime error: index out of range [3] with length 0" {
77 t.Fatal("Got mismatched error message:", errorMessage)
78 }
79}
80
81// Validates that we can submit new data scouting data.
82func TestSubmitDataScouting(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080083 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080084 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080085 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080086 scoutingServer.Start(8080)
87 defer scoutingServer.Stop()
88
89 builder := flatbuffers.NewBuilder(1024)
90 builder.Finish((&submit_data_scouting.SubmitDataScoutingT{
Philipp Schraderfa45d742022-03-18 19:29:05 -070091 Team: 971,
92 Match: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -070093 SetNumber: 8,
Philipp Schrader4535b7e2022-04-08 20:27:00 -070094 CompLevel: "quals",
Philipp Schraderfa45d742022-03-18 19:29:05 -070095 StartingQuadrant: 2,
96 AutoBall1: true,
97 AutoBall2: false,
98 AutoBall3: false,
99 AutoBall4: false,
100 AutoBall5: false,
101 MissedShotsAuto: 9971,
102 UpperGoalAuto: 9971,
103 LowerGoalAuto: 9971,
104 MissedShotsTele: 9971,
105 UpperGoalTele: 9971,
106 LowerGoalTele: 9971,
107 DefenseRating: 9971,
108 DefenseReceivedRating: 4,
109 ClimbLevel: submit_data_scouting.ClimbLevelLow,
110 Comment: "this is a comment",
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800111 }).Pack(builder))
112
Philipp Schrader30005e42022-03-06 13:53:58 -0800113 response, err := debug.SubmitDataScouting("http://localhost:8080", builder.FinishedBytes())
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800114 if err != nil {
Philipp Schrader30005e42022-03-06 13:53:58 -0800115 t.Fatal("Failed to submit data scouting: ", err)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800116 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800117
118 // We get an empty response back. Validate that.
119 expected := submit_data_scouting_response.SubmitDataScoutingResponseT{}
120 if !reflect.DeepEqual(expected, *response) {
121 t.Fatal("Expected ", expected, ", but got:", *response)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800122 }
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800123}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800124
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800125// Validates that we can request the full match list.
126func TestRequestAllMatches(t *testing.T) {
Philipp Schrader6e8d6fa2023-02-18 17:15:13 -0800127 t.Skip("TODO(phil/emily): Figure out why this test is failing.")
128
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800129 db := MockDatabase{
Emily Markovabf24c9e2023-02-08 20:31:11 -0800130 matches: []db.TeamMatch{
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800131 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700132 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800133 Alliance: "R", AlliancePosition: 1, TeamNumber: 5,
134 },
135 {
136 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
137 Alliance: "R", AlliancePosition: 2, TeamNumber: 42,
138 },
139 {
140 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
141 Alliance: "R", AlliancePosition: 3, TeamNumber: 600,
142 },
143 {
144 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
145 Alliance: "B", AlliancePosition: 1, TeamNumber: 971,
146 },
147 {
148 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
149 Alliance: "B", AlliancePosition: 2, TeamNumber: 400,
150 },
151 {
152 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
153 Alliance: "B", AlliancePosition: 3, TeamNumber: 200,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800154 },
155 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700156 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800157 Alliance: "R", AlliancePosition: 1, TeamNumber: 6,
158 },
159 {
160 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
161 Alliance: "R", AlliancePosition: 2, TeamNumber: 43,
162 },
163 {
164 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
165 Alliance: "R", AlliancePosition: 3, TeamNumber: 601,
166 },
167 {
168 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
169 Alliance: "B", AlliancePosition: 1, TeamNumber: 972,
170 },
171 {
172 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
173 Alliance: "B", AlliancePosition: 2, TeamNumber: 401,
174 },
175 {
176 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
177 Alliance: "B", AlliancePosition: 3, TeamNumber: 201,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800178 },
179 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700180 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800181 Alliance: "R", AlliancePosition: 1, TeamNumber: 7,
182 },
183 {
184 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
185 Alliance: "R", AlliancePosition: 2, TeamNumber: 44,
186 },
187 {
188 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
189 Alliance: "R", AlliancePosition: 3, TeamNumber: 602,
190 },
191 {
192 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
193 Alliance: "B", AlliancePosition: 1, TeamNumber: 973,
194 },
195 {
196 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
197 Alliance: "B", AlliancePosition: 2, TeamNumber: 402,
198 },
199 {
200 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
201 Alliance: "B", AlliancePosition: 3, TeamNumber: 202,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800202 },
203 },
204 }
205 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800206 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800207 scoutingServer.Start(8080)
208 defer scoutingServer.Stop()
209
210 builder := flatbuffers.NewBuilder(1024)
211 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
212
213 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
214 if err != nil {
215 t.Fatal("Failed to request all matches: ", err)
216 }
217
218 expected := request_all_matches_response.RequestAllMatchesResponseT{
219 MatchList: []*request_all_matches_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700220 // MatchNumber, SetNumber, CompLevel
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800221 // R1, R2, R3, B1, B2, B3
222 {
223 1, 1, "qual",
224 5, 42, 600, 971, 400, 200,
225 },
226 {
227 2, 1, "qual",
228 6, 43, 601, 972, 401, 201,
229 },
230 {
231 3, 1, "qual",
232 7, 44, 602, 973, 402, 202,
233 },
234 },
235 }
236 if len(expected.MatchList) != len(response.MatchList) {
237 t.Fatal("Expected ", expected, ", but got ", *response)
238 }
239 for i, match := range expected.MatchList {
240 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
241 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
242 }
243 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800244
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800245}
246
Philipp Schraderacf96232022-03-01 22:03:30 -0800247// Validates that we can request the stats.
248func TestRequestDataScouting(t *testing.T) {
249 db := MockDatabase{
250 stats: []db.Stats{
251 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700252 TeamNumber: 971, MatchNumber: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700253 StartingQuadrant: 1,
254 AutoBallPickedUp: [5]bool{true, false, false, false, true},
255 ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
Philipp Schraderacf96232022-03-01 22:03:30 -0800256 ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700257 PlayedDefense: 7, DefenseReceivedScore: 3, Climbing: 2,
258 Comment: "a lovely comment", CollectedBy: "john",
Philipp Schraderacf96232022-03-01 22:03:30 -0800259 },
260 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700261 TeamNumber: 972, MatchNumber: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700262 StartingQuadrant: 2,
263 AutoBallPickedUp: [5]bool{false, false, true, false, false},
264 ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
Philipp Schraderacf96232022-03-01 22:03:30 -0800265 ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700266 PlayedDefense: 8, DefenseReceivedScore: 1, Climbing: 4,
267 Comment: "another lovely comment", CollectedBy: "andrea",
Philipp Schraderacf96232022-03-01 22:03:30 -0800268 },
269 },
270 }
271 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800272 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderacf96232022-03-01 22:03:30 -0800273 scoutingServer.Start(8080)
274 defer scoutingServer.Stop()
275
276 builder := flatbuffers.NewBuilder(1024)
277 builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
278
279 response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
280 if err != nil {
281 t.Fatal("Failed to request all matches: ", err)
282 }
283
284 expected := request_data_scouting_response.RequestDataScoutingResponseT{
285 StatsList: []*request_data_scouting_response.StatsT{
Philipp Schraderacf96232022-03-01 22:03:30 -0800286 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700287 Team: 971, Match: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700288 MissedShotsAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
289 MissedShotsTele: 1, UpperGoalTele: 2, LowerGoalTele: 3,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700290 DefenseRating: 7,
291 DefenseReceivedRating: 3,
292 CollectedBy: "john",
293 AutoBall1: true, AutoBall2: false, AutoBall3: false,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700294 AutoBall4: false, AutoBall5: true,
295 StartingQuadrant: 1,
296 ClimbLevel: request_data_scouting_response.ClimbLevelFailedWithPlentyOfTime,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700297 Comment: "a lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800298 },
299 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700300 Team: 972, Match: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700301 MissedShotsAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
302 MissedShotsTele: 2, UpperGoalTele: 3, LowerGoalTele: 4,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700303 DefenseRating: 8,
304 DefenseReceivedRating: 1,
305 CollectedBy: "andrea",
306 AutoBall1: false, AutoBall2: false, AutoBall3: true,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700307 AutoBall4: false, AutoBall5: false,
308 StartingQuadrant: 2,
309 ClimbLevel: request_data_scouting_response.ClimbLevelMedium,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700310 Comment: "another lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800311 },
312 },
313 }
314 if len(expected.StatsList) != len(response.StatsList) {
315 t.Fatal("Expected ", expected, ", but got ", *response)
316 }
317 for i, match := range expected.StatsList {
318 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
319 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
320 }
321 }
322}
323
Alex Perry81f96ba2022-03-13 18:26:19 -0700324func TestSubmitNotes(t *testing.T) {
325 database := MockDatabase{}
326 scoutingServer := server.NewScoutingServer()
327 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
328 scoutingServer.Start(8080)
329 defer scoutingServer.Stop()
330
331 builder := flatbuffers.NewBuilder(1024)
332 builder.Finish((&submit_notes.SubmitNotesT{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800333 Team: 971,
334 Notes: "Notes",
335 GoodDriving: true,
336 BadDriving: false,
337 SketchyClimb: true,
338 SolidClimb: false,
339 GoodDefense: true,
340 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700341 }).Pack(builder))
342
343 _, err := debug.SubmitNotes("http://localhost:8080", builder.FinishedBytes())
344 if err != nil {
345 t.Fatal("Failed to submit notes: ", err)
346 }
347
348 expected := []db.NotesData{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800349 {
350 TeamNumber: 971,
351 Notes: "Notes",
352 GoodDriving: true,
353 BadDriving: false,
354 SketchyClimb: true,
355 SolidClimb: false,
356 GoodDefense: true,
357 BadDefense: false,
358 },
Alex Perry81f96ba2022-03-13 18:26:19 -0700359 }
360
361 if !reflect.DeepEqual(database.notes, expected) {
362 t.Fatal("Submitted notes did not match", expected, database.notes)
363 }
364}
365
366func TestRequestNotes(t *testing.T) {
367 database := MockDatabase{
368 notes: []db.NotesData{{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800369 TeamNumber: 971,
370 Notes: "Notes",
371 GoodDriving: true,
372 BadDriving: false,
373 SketchyClimb: true,
374 SolidClimb: false,
375 GoodDefense: true,
376 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700377 }},
378 }
379 scoutingServer := server.NewScoutingServer()
380 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
381 scoutingServer.Start(8080)
382 defer scoutingServer.Stop()
383
384 builder := flatbuffers.NewBuilder(1024)
385 builder.Finish((&request_notes_for_team.RequestNotesForTeamT{
386 Team: 971,
387 }).Pack(builder))
388 response, err := debug.RequestNotes("http://localhost:8080", builder.FinishedBytes())
389 if err != nil {
390 t.Fatal("Failed to submit notes: ", err)
391 }
392
393 if response.Notes[0].Data != "Notes" {
394 t.Fatal("requested notes did not match", response)
395 }
396}
397
Milo Lin1d59f0c2022-06-22 20:30:58 -0700398func TestRequestShiftSchedule(t *testing.T) {
399 db := MockDatabase{
400 shiftSchedule: []db.Shift{
401 {
402 MatchNumber: 1,
403 R1scouter: "Bob",
404 R2scouter: "James",
405 R3scouter: "Robert",
406 B1scouter: "Alice",
407 B2scouter: "Mary",
408 B3scouter: "Patricia",
409 },
410 {
411 MatchNumber: 2,
412 R1scouter: "Liam",
413 R2scouter: "Noah",
414 R3scouter: "Oliver",
415 B1scouter: "Emma",
416 B2scouter: "Charlotte",
417 B3scouter: "Amelia",
418 },
419 },
420 }
421 scoutingServer := server.NewScoutingServer()
422 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
423 scoutingServer.Start(8080)
424 defer scoutingServer.Stop()
425
426 builder := flatbuffers.NewBuilder(1024)
427 builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
428
429 response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
430 if err != nil {
431 t.Fatal("Failed to request shift schedule: ", err)
432 }
433
434 expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
435 ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
436 {
437 MatchNumber: 1,
438 R1scouter: "Bob",
439 R2scouter: "James",
440 R3scouter: "Robert",
441 B1scouter: "Alice",
442 B2scouter: "Mary",
443 B3scouter: "Patricia",
444 },
445 {
446 MatchNumber: 2,
447 R1scouter: "Liam",
448 R2scouter: "Noah",
449 R3scouter: "Oliver",
450 B1scouter: "Emma",
451 B2scouter: "Charlotte",
452 B3scouter: "Amelia",
453 },
454 },
455 }
456 if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
457 t.Fatal("Expected ", expected, ", but got ", *response)
458 }
459 for i, match := range expected.ShiftSchedule {
460 if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
461 t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
462 }
463 }
464}
465
466func TestSubmitShiftSchedule(t *testing.T) {
467 database := MockDatabase{}
468 scoutingServer := server.NewScoutingServer()
469 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
470 scoutingServer.Start(8080)
471 defer scoutingServer.Stop()
472
473 builder := flatbuffers.NewBuilder(1024)
474 builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
475 ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
476 {MatchNumber: 1,
477 R1scouter: "Bob",
478 R2scouter: "James",
479 R3scouter: "Robert",
480 B1scouter: "Alice",
481 B2scouter: "Mary",
482 B3scouter: "Patricia"},
483 },
484 }).Pack(builder))
485
486 _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
487 if err != nil {
488 t.Fatal("Failed to submit shift schedule: ", err)
489 }
490
491 expected := []db.Shift{
492 {MatchNumber: 1,
493 R1scouter: "Bob",
494 R2scouter: "James",
495 R3scouter: "Robert",
496 B1scouter: "Alice",
497 B2scouter: "Mary",
498 B3scouter: "Patricia"},
499 }
500 if !reflect.DeepEqual(expected, database.shiftSchedule) {
501 t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
502 }
503}
504
Philipp Schraderd3fac192022-03-02 20:35:46 -0800505// Validates that we can download the schedule from The Blue Alliance.
506func TestRefreshMatchList(t *testing.T) {
507 scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
508 return []scraping.Match{
509 {
510 CompLevel: "qual",
511 MatchNumber: 1,
Philipp Schrader45befdd2022-04-08 19:12:44 -0700512 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800513 Alliances: scraping.Alliances{
514 Red: scraping.Alliance{
515 TeamKeys: []string{
516 "100",
517 "200",
518 "300",
519 },
520 },
521 Blue: scraping.Alliance{
522 TeamKeys: []string{
523 "101",
524 "201",
525 "301",
526 },
527 },
528 },
529 WinningAlliance: "",
530 EventKey: "",
531 Time: 0,
532 PredictedTime: 0,
533 ActualTime: 0,
534 PostResultTime: 0,
535 ScoreBreakdowns: scraping.ScoreBreakdowns{},
536 },
537 }, nil
538 }
539
540 database := MockDatabase{}
541 scoutingServer := server.NewScoutingServer()
542 HandleRequests(&database, scrapeMockSchedule, scoutingServer)
543 scoutingServer.Start(8080)
544 defer scoutingServer.Stop()
545
546 builder := flatbuffers.NewBuilder(1024)
547 builder.Finish((&refresh_match_list.RefreshMatchListT{}).Pack(builder))
548
549 response, err := debug.RefreshMatchList("http://localhost:8080", builder.FinishedBytes())
550 if err != nil {
551 t.Fatal("Failed to request all matches: ", err)
552 }
553
554 // Validate the response.
555 expected := refresh_match_list_response.RefreshMatchListResponseT{}
556 if !reflect.DeepEqual(expected, *response) {
557 t.Fatal("Expected ", expected, ", but got ", *response)
558 }
559
560 // Make sure that the data made it into the database.
Emily Markovabf24c9e2023-02-08 20:31:11 -0800561 expectedMatches := []db.TeamMatch{
Philipp Schraderd3fac192022-03-02 20:35:46 -0800562 {
Emily Markovabf24c9e2023-02-08 20:31:11 -0800563 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
564 Alliance: "R", AlliancePosition: 1, TeamNumber: 100,
565 },
566 {
567 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
568 Alliance: "R", AlliancePosition: 2, TeamNumber: 200,
569 },
570 {
571 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
572 Alliance: "R", AlliancePosition: 3, TeamNumber: 300,
573 },
574 {
575 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
576 Alliance: "B", AlliancePosition: 1, TeamNumber: 101,
577 },
578 {
579 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
580 Alliance: "B", AlliancePosition: 2, TeamNumber: 201,
581 },
582 {
583 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
584 Alliance: "B", AlliancePosition: 3, TeamNumber: 301,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800585 },
586 }
Emily Markovabf24c9e2023-02-08 20:31:11 -0800587
Philipp Schraderd3fac192022-03-02 20:35:46 -0800588 if !reflect.DeepEqual(expectedMatches, database.matches) {
589 t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
590 }
591}
592
Filip Kujawa210a03b2022-11-24 14:41:11 -0800593func TestSubmitDriverRanking(t *testing.T) {
594 database := MockDatabase{}
595 scoutingServer := server.NewScoutingServer()
596 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
597 scoutingServer.Start(8080)
598 defer scoutingServer.Stop()
599
600 builder := flatbuffers.NewBuilder(1024)
601 builder.Finish((&submit_driver_ranking.SubmitDriverRankingT{
602 MatchNumber: 36,
603 Rank1: 1234,
604 Rank2: 1235,
605 Rank3: 1236,
606 }).Pack(builder))
607
608 _, err := debug.SubmitDriverRanking("http://localhost:8080", builder.FinishedBytes())
609 if err != nil {
610 t.Fatal("Failed to submit driver ranking: ", err)
611 }
612
613 expected := []db.DriverRankingData{
614 {MatchNumber: 36, Rank1: 1234, Rank2: 1235, Rank3: 1236},
615 }
616
617 if !reflect.DeepEqual(database.driver_ranking, expected) {
618 t.Fatal("Submitted notes did not match", expected, database.notes)
619 }
620}
621
Filip Kujawaf882e022022-12-14 13:14:08 -0800622// Validates that we can request the driver rankings.
623func TestRequestDriverRankings(t *testing.T) {
624 db := MockDatabase{
625 driver_ranking: []db.DriverRankingData{
626 {
627 MatchNumber: 36,
628 Rank1: 1234,
629 Rank2: 1235,
630 Rank3: 1236,
631 },
632 {
633 MatchNumber: 36,
634 Rank1: 101,
635 Rank2: 202,
636 Rank3: 303,
637 },
638 },
639 }
640 scoutingServer := server.NewScoutingServer()
641 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
642 scoutingServer.Start(8080)
643 defer scoutingServer.Stop()
644
645 builder := flatbuffers.NewBuilder(1024)
646 builder.Finish((&request_all_driver_rankings.RequestAllDriverRankingsT{}).Pack(builder))
647
648 response, err := debug.RequestAllDriverRankings("http://localhost:8080", builder.FinishedBytes())
649 if err != nil {
650 t.Fatal("Failed to request all driver rankings: ", err)
651 }
652
653 expected := request_all_driver_rankings_response.RequestAllDriverRankingsResponseT{
654 DriverRankingList: []*request_all_driver_rankings_response.RankingT{
655 {
656 MatchNumber: 36,
657 Rank1: 1234,
658 Rank2: 1235,
659 Rank3: 1236,
660 },
661 {
662 MatchNumber: 36,
663 Rank1: 101,
664 Rank2: 202,
665 Rank3: 303,
666 },
667 },
668 }
669 if len(expected.DriverRankingList) != len(response.DriverRankingList) {
670 t.Fatal("Expected ", expected, ", but got ", *response)
671 }
672 for i, match := range expected.DriverRankingList {
673 if !reflect.DeepEqual(*match, *response.DriverRankingList[i]) {
674 t.Fatal("Expected for driver ranking", i, ":", *match, ", but got:", *response.DriverRankingList[i])
675 }
676 }
677}
678
679// Validates that we can request all notes.
680func TestRequestAllNotes(t *testing.T) {
681 db := MockDatabase{
682 notes: []db.NotesData{
683 {
684 TeamNumber: 971,
685 Notes: "Notes",
686 GoodDriving: true,
687 BadDriving: false,
688 SketchyClimb: true,
689 SolidClimb: false,
690 GoodDefense: true,
691 BadDefense: false,
692 },
693 {
694 TeamNumber: 972,
695 Notes: "More Notes",
696 GoodDriving: false,
697 BadDriving: false,
698 SketchyClimb: false,
699 SolidClimb: true,
700 GoodDefense: false,
701 BadDefense: true,
702 },
703 },
704 }
705 scoutingServer := server.NewScoutingServer()
706 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
707 scoutingServer.Start(8080)
708 defer scoutingServer.Stop()
709
710 builder := flatbuffers.NewBuilder(1024)
711 builder.Finish((&request_all_notes.RequestAllNotesT{}).Pack(builder))
712
713 response, err := debug.RequestAllNotes("http://localhost:8080", builder.FinishedBytes())
714 if err != nil {
715 t.Fatal("Failed to request all notes: ", err)
716 }
717
718 expected := request_all_notes_response.RequestAllNotesResponseT{
719 NoteList: []*request_all_notes_response.NoteT{
720 {
721 Team: 971,
722 Notes: "Notes",
723 GoodDriving: true,
724 BadDriving: false,
725 SketchyClimb: true,
726 SolidClimb: false,
727 GoodDefense: true,
728 BadDefense: false,
729 },
730 {
731 Team: 972,
732 Notes: "More Notes",
733 GoodDriving: false,
734 BadDriving: false,
735 SketchyClimb: false,
736 SolidClimb: true,
737 GoodDefense: false,
738 BadDefense: true,
739 },
740 },
741 }
742 if len(expected.NoteList) != len(response.NoteList) {
743 t.Fatal("Expected ", expected, ", but got ", *response)
744 }
745 for i, note := range expected.NoteList {
746 if !reflect.DeepEqual(*note, *response.NoteList[i]) {
747 t.Fatal("Expected for note", i, ":", *note, ", but got:", *response.NoteList[i])
748 }
749 }
750}
751
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800752// A mocked database we can use for testing. Add functionality to this as
753// needed for your tests.
754
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800755type MockDatabase struct {
Emily Markovabf24c9e2023-02-08 20:31:11 -0800756 matches []db.TeamMatch
Filip Kujawa210a03b2022-11-24 14:41:11 -0800757 stats []db.Stats
758 notes []db.NotesData
759 shiftSchedule []db.Shift
760 driver_ranking []db.DriverRankingData
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800761}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800762
Emily Markovabf24c9e2023-02-08 20:31:11 -0800763func (database *MockDatabase) AddToMatch(match db.TeamMatch) error {
Philipp Schraderd3fac192022-03-02 20:35:46 -0800764 database.matches = append(database.matches, match)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800765 return nil
766}
767
Philipp Schrader30005e42022-03-06 13:53:58 -0800768func (database *MockDatabase) AddToStats(stats db.Stats) error {
769 database.stats = append(database.stats, stats)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800770 return nil
771}
772
Emily Markovabf24c9e2023-02-08 20:31:11 -0800773func (database *MockDatabase) ReturnMatches() ([]db.TeamMatch, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800774 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800775}
776
777func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
Philipp Schraderacf96232022-03-01 22:03:30 -0800778 return database.stats, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800779}
780
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800781func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
782 return []db.Stats{}, nil
783}
Philipp Schraderd3fac192022-03-02 20:35:46 -0800784
Philipp Schradereecb8962022-06-01 21:02:42 -0700785func (database *MockDatabase) QueryNotes(requestedTeam int32) ([]string, error) {
Alex Perry81f96ba2022-03-13 18:26:19 -0700786 var results []string
787 for _, data := range database.notes {
788 if data.TeamNumber == requestedTeam {
Philipp Schradereecb8962022-06-01 21:02:42 -0700789 results = append(results, data.Notes)
Alex Perry81f96ba2022-03-13 18:26:19 -0700790 }
791 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700792 return results, nil
Alex Perry81f96ba2022-03-13 18:26:19 -0700793}
794
Filip Kujawaf947cb42022-11-21 10:00:30 -0800795func (database *MockDatabase) AddNotes(data db.NotesData) error {
796 database.notes = append(database.notes, data)
Alex Perry81f96ba2022-03-13 18:26:19 -0700797 return nil
798}
799
Filip Kujawaf882e022022-12-14 13:14:08 -0800800func (database *MockDatabase) ReturnAllNotes() ([]db.NotesData, error) {
801 return database.notes, nil
802}
803
Milo Lin1d59f0c2022-06-22 20:30:58 -0700804func (database *MockDatabase) AddToShift(data db.Shift) error {
805 database.shiftSchedule = append(database.shiftSchedule, data)
806 return nil
807}
808
809func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
810 return database.shiftSchedule, nil
811}
812
813func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
814 return []db.Shift{}, nil
815}
816
Filip Kujawa210a03b2022-11-24 14:41:11 -0800817func (database *MockDatabase) AddDriverRanking(data db.DriverRankingData) error {
818 database.driver_ranking = append(database.driver_ranking, data)
819 return nil
820}
821
Filip Kujawaf882e022022-12-14 13:14:08 -0800822func (database *MockDatabase) ReturnAllDriverRankings() ([]db.DriverRankingData, error) {
823 return database.driver_ranking, nil
824}
825
Philipp Schraderd3fac192022-03-02 20:35:46 -0800826// Returns an empty match list from the fake The Blue Alliance scraping.
827func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
828 return nil, nil
829}