blob: 9775eae702df377e882d7de7f4374078d10be0e0 [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) {
127 db := MockDatabase{
128 matches: []db.Match{
129 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700130 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800131 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
132 },
133 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700134 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800135 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
136 },
137 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700138 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800139 R1: 7, R2: 44, R3: 602, B1: 973, B2: 402, B3: 202,
140 },
141 },
142 }
143 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800144 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800145 scoutingServer.Start(8080)
146 defer scoutingServer.Stop()
147
148 builder := flatbuffers.NewBuilder(1024)
149 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
150
151 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
152 if err != nil {
153 t.Fatal("Failed to request all matches: ", err)
154 }
155
156 expected := request_all_matches_response.RequestAllMatchesResponseT{
157 MatchList: []*request_all_matches_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700158 // MatchNumber, SetNumber, CompLevel
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800159 // R1, R2, R3, B1, B2, B3
160 {
161 1, 1, "qual",
162 5, 42, 600, 971, 400, 200,
163 },
164 {
165 2, 1, "qual",
166 6, 43, 601, 972, 401, 201,
167 },
168 {
169 3, 1, "qual",
170 7, 44, 602, 973, 402, 202,
171 },
172 },
173 }
174 if len(expected.MatchList) != len(response.MatchList) {
175 t.Fatal("Expected ", expected, ", but got ", *response)
176 }
177 for i, match := range expected.MatchList {
178 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
179 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
180 }
181 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800182
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800183}
184
Philipp Schraderacf96232022-03-01 22:03:30 -0800185// Validates that we can request the stats.
186func TestRequestDataScouting(t *testing.T) {
187 db := MockDatabase{
188 stats: []db.Stats{
189 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700190 TeamNumber: 971, MatchNumber: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700191 StartingQuadrant: 1,
192 AutoBallPickedUp: [5]bool{true, false, false, false, true},
193 ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
Philipp Schraderacf96232022-03-01 22:03:30 -0800194 ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700195 PlayedDefense: 7, DefenseReceivedScore: 3, Climbing: 2,
196 Comment: "a lovely comment", CollectedBy: "john",
Philipp Schraderacf96232022-03-01 22:03:30 -0800197 },
198 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700199 TeamNumber: 972, MatchNumber: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700200 StartingQuadrant: 2,
201 AutoBallPickedUp: [5]bool{false, false, true, false, false},
202 ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
Philipp Schraderacf96232022-03-01 22:03:30 -0800203 ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700204 PlayedDefense: 8, DefenseReceivedScore: 1, Climbing: 4,
205 Comment: "another lovely comment", CollectedBy: "andrea",
Philipp Schraderacf96232022-03-01 22:03:30 -0800206 },
207 },
208 }
209 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800210 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderacf96232022-03-01 22:03:30 -0800211 scoutingServer.Start(8080)
212 defer scoutingServer.Stop()
213
214 builder := flatbuffers.NewBuilder(1024)
215 builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
216
217 response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
218 if err != nil {
219 t.Fatal("Failed to request all matches: ", err)
220 }
221
222 expected := request_data_scouting_response.RequestDataScoutingResponseT{
223 StatsList: []*request_data_scouting_response.StatsT{
Philipp Schraderacf96232022-03-01 22:03:30 -0800224 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700225 Team: 971, Match: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700226 MissedShotsAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
227 MissedShotsTele: 1, UpperGoalTele: 2, LowerGoalTele: 3,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700228 DefenseRating: 7,
229 DefenseReceivedRating: 3,
230 CollectedBy: "john",
231 AutoBall1: true, AutoBall2: false, AutoBall3: false,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700232 AutoBall4: false, AutoBall5: true,
233 StartingQuadrant: 1,
234 ClimbLevel: request_data_scouting_response.ClimbLevelFailedWithPlentyOfTime,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700235 Comment: "a lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800236 },
237 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700238 Team: 972, Match: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700239 MissedShotsAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
240 MissedShotsTele: 2, UpperGoalTele: 3, LowerGoalTele: 4,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700241 DefenseRating: 8,
242 DefenseReceivedRating: 1,
243 CollectedBy: "andrea",
244 AutoBall1: false, AutoBall2: false, AutoBall3: true,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700245 AutoBall4: false, AutoBall5: false,
246 StartingQuadrant: 2,
247 ClimbLevel: request_data_scouting_response.ClimbLevelMedium,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700248 Comment: "another lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800249 },
250 },
251 }
252 if len(expected.StatsList) != len(response.StatsList) {
253 t.Fatal("Expected ", expected, ", but got ", *response)
254 }
255 for i, match := range expected.StatsList {
256 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
257 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
258 }
259 }
260}
261
Alex Perry81f96ba2022-03-13 18:26:19 -0700262func TestSubmitNotes(t *testing.T) {
263 database := MockDatabase{}
264 scoutingServer := server.NewScoutingServer()
265 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
266 scoutingServer.Start(8080)
267 defer scoutingServer.Stop()
268
269 builder := flatbuffers.NewBuilder(1024)
270 builder.Finish((&submit_notes.SubmitNotesT{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800271 Team: 971,
272 Notes: "Notes",
273 GoodDriving: true,
274 BadDriving: false,
275 SketchyClimb: true,
276 SolidClimb: false,
277 GoodDefense: true,
278 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700279 }).Pack(builder))
280
281 _, err := debug.SubmitNotes("http://localhost:8080", builder.FinishedBytes())
282 if err != nil {
283 t.Fatal("Failed to submit notes: ", err)
284 }
285
286 expected := []db.NotesData{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800287 {
288 TeamNumber: 971,
289 Notes: "Notes",
290 GoodDriving: true,
291 BadDriving: false,
292 SketchyClimb: true,
293 SolidClimb: false,
294 GoodDefense: true,
295 BadDefense: false,
296 },
Alex Perry81f96ba2022-03-13 18:26:19 -0700297 }
298
299 if !reflect.DeepEqual(database.notes, expected) {
300 t.Fatal("Submitted notes did not match", expected, database.notes)
301 }
302}
303
304func TestRequestNotes(t *testing.T) {
305 database := MockDatabase{
306 notes: []db.NotesData{{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800307 TeamNumber: 971,
308 Notes: "Notes",
309 GoodDriving: true,
310 BadDriving: false,
311 SketchyClimb: true,
312 SolidClimb: false,
313 GoodDefense: true,
314 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700315 }},
316 }
317 scoutingServer := server.NewScoutingServer()
318 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
319 scoutingServer.Start(8080)
320 defer scoutingServer.Stop()
321
322 builder := flatbuffers.NewBuilder(1024)
323 builder.Finish((&request_notes_for_team.RequestNotesForTeamT{
324 Team: 971,
325 }).Pack(builder))
326 response, err := debug.RequestNotes("http://localhost:8080", builder.FinishedBytes())
327 if err != nil {
328 t.Fatal("Failed to submit notes: ", err)
329 }
330
331 if response.Notes[0].Data != "Notes" {
332 t.Fatal("requested notes did not match", response)
333 }
334}
335
Milo Lin1d59f0c2022-06-22 20:30:58 -0700336func TestRequestShiftSchedule(t *testing.T) {
337 db := MockDatabase{
338 shiftSchedule: []db.Shift{
339 {
340 MatchNumber: 1,
341 R1scouter: "Bob",
342 R2scouter: "James",
343 R3scouter: "Robert",
344 B1scouter: "Alice",
345 B2scouter: "Mary",
346 B3scouter: "Patricia",
347 },
348 {
349 MatchNumber: 2,
350 R1scouter: "Liam",
351 R2scouter: "Noah",
352 R3scouter: "Oliver",
353 B1scouter: "Emma",
354 B2scouter: "Charlotte",
355 B3scouter: "Amelia",
356 },
357 },
358 }
359 scoutingServer := server.NewScoutingServer()
360 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
361 scoutingServer.Start(8080)
362 defer scoutingServer.Stop()
363
364 builder := flatbuffers.NewBuilder(1024)
365 builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
366
367 response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
368 if err != nil {
369 t.Fatal("Failed to request shift schedule: ", err)
370 }
371
372 expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
373 ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
374 {
375 MatchNumber: 1,
376 R1scouter: "Bob",
377 R2scouter: "James",
378 R3scouter: "Robert",
379 B1scouter: "Alice",
380 B2scouter: "Mary",
381 B3scouter: "Patricia",
382 },
383 {
384 MatchNumber: 2,
385 R1scouter: "Liam",
386 R2scouter: "Noah",
387 R3scouter: "Oliver",
388 B1scouter: "Emma",
389 B2scouter: "Charlotte",
390 B3scouter: "Amelia",
391 },
392 },
393 }
394 if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
395 t.Fatal("Expected ", expected, ", but got ", *response)
396 }
397 for i, match := range expected.ShiftSchedule {
398 if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
399 t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
400 }
401 }
402}
403
404func TestSubmitShiftSchedule(t *testing.T) {
405 database := MockDatabase{}
406 scoutingServer := server.NewScoutingServer()
407 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
408 scoutingServer.Start(8080)
409 defer scoutingServer.Stop()
410
411 builder := flatbuffers.NewBuilder(1024)
412 builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
413 ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
414 {MatchNumber: 1,
415 R1scouter: "Bob",
416 R2scouter: "James",
417 R3scouter: "Robert",
418 B1scouter: "Alice",
419 B2scouter: "Mary",
420 B3scouter: "Patricia"},
421 },
422 }).Pack(builder))
423
424 _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
425 if err != nil {
426 t.Fatal("Failed to submit shift schedule: ", err)
427 }
428
429 expected := []db.Shift{
430 {MatchNumber: 1,
431 R1scouter: "Bob",
432 R2scouter: "James",
433 R3scouter: "Robert",
434 B1scouter: "Alice",
435 B2scouter: "Mary",
436 B3scouter: "Patricia"},
437 }
438 if !reflect.DeepEqual(expected, database.shiftSchedule) {
439 t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
440 }
441}
442
Philipp Schraderd3fac192022-03-02 20:35:46 -0800443// Validates that we can download the schedule from The Blue Alliance.
444func TestRefreshMatchList(t *testing.T) {
445 scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
446 return []scraping.Match{
447 {
448 CompLevel: "qual",
449 MatchNumber: 1,
Philipp Schrader45befdd2022-04-08 19:12:44 -0700450 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800451 Alliances: scraping.Alliances{
452 Red: scraping.Alliance{
453 TeamKeys: []string{
454 "100",
455 "200",
456 "300",
457 },
458 },
459 Blue: scraping.Alliance{
460 TeamKeys: []string{
461 "101",
462 "201",
463 "301",
464 },
465 },
466 },
467 WinningAlliance: "",
468 EventKey: "",
469 Time: 0,
470 PredictedTime: 0,
471 ActualTime: 0,
472 PostResultTime: 0,
473 ScoreBreakdowns: scraping.ScoreBreakdowns{},
474 },
475 }, nil
476 }
477
478 database := MockDatabase{}
479 scoutingServer := server.NewScoutingServer()
480 HandleRequests(&database, scrapeMockSchedule, scoutingServer)
481 scoutingServer.Start(8080)
482 defer scoutingServer.Stop()
483
484 builder := flatbuffers.NewBuilder(1024)
485 builder.Finish((&refresh_match_list.RefreshMatchListT{}).Pack(builder))
486
487 response, err := debug.RefreshMatchList("http://localhost:8080", builder.FinishedBytes())
488 if err != nil {
489 t.Fatal("Failed to request all matches: ", err)
490 }
491
492 // Validate the response.
493 expected := refresh_match_list_response.RefreshMatchListResponseT{}
494 if !reflect.DeepEqual(expected, *response) {
495 t.Fatal("Expected ", expected, ", but got ", *response)
496 }
497
498 // Make sure that the data made it into the database.
499 expectedMatches := []db.Match{
500 {
501 MatchNumber: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -0700502 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800503 CompLevel: "qual",
504 R1: 100,
505 R2: 200,
506 R3: 300,
507 B1: 101,
508 B2: 201,
509 B3: 301,
510 },
511 }
512 if !reflect.DeepEqual(expectedMatches, database.matches) {
513 t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
514 }
515}
516
Filip Kujawa210a03b2022-11-24 14:41:11 -0800517func TestSubmitDriverRanking(t *testing.T) {
518 database := MockDatabase{}
519 scoutingServer := server.NewScoutingServer()
520 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
521 scoutingServer.Start(8080)
522 defer scoutingServer.Stop()
523
524 builder := flatbuffers.NewBuilder(1024)
525 builder.Finish((&submit_driver_ranking.SubmitDriverRankingT{
526 MatchNumber: 36,
527 Rank1: 1234,
528 Rank2: 1235,
529 Rank3: 1236,
530 }).Pack(builder))
531
532 _, err := debug.SubmitDriverRanking("http://localhost:8080", builder.FinishedBytes())
533 if err != nil {
534 t.Fatal("Failed to submit driver ranking: ", err)
535 }
536
537 expected := []db.DriverRankingData{
538 {MatchNumber: 36, Rank1: 1234, Rank2: 1235, Rank3: 1236},
539 }
540
541 if !reflect.DeepEqual(database.driver_ranking, expected) {
542 t.Fatal("Submitted notes did not match", expected, database.notes)
543 }
544}
545
Filip Kujawaf882e022022-12-14 13:14:08 -0800546// Validates that we can request the driver rankings.
547func TestRequestDriverRankings(t *testing.T) {
548 db := MockDatabase{
549 driver_ranking: []db.DriverRankingData{
550 {
551 MatchNumber: 36,
552 Rank1: 1234,
553 Rank2: 1235,
554 Rank3: 1236,
555 },
556 {
557 MatchNumber: 36,
558 Rank1: 101,
559 Rank2: 202,
560 Rank3: 303,
561 },
562 },
563 }
564 scoutingServer := server.NewScoutingServer()
565 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
566 scoutingServer.Start(8080)
567 defer scoutingServer.Stop()
568
569 builder := flatbuffers.NewBuilder(1024)
570 builder.Finish((&request_all_driver_rankings.RequestAllDriverRankingsT{}).Pack(builder))
571
572 response, err := debug.RequestAllDriverRankings("http://localhost:8080", builder.FinishedBytes())
573 if err != nil {
574 t.Fatal("Failed to request all driver rankings: ", err)
575 }
576
577 expected := request_all_driver_rankings_response.RequestAllDriverRankingsResponseT{
578 DriverRankingList: []*request_all_driver_rankings_response.RankingT{
579 {
580 MatchNumber: 36,
581 Rank1: 1234,
582 Rank2: 1235,
583 Rank3: 1236,
584 },
585 {
586 MatchNumber: 36,
587 Rank1: 101,
588 Rank2: 202,
589 Rank3: 303,
590 },
591 },
592 }
593 if len(expected.DriverRankingList) != len(response.DriverRankingList) {
594 t.Fatal("Expected ", expected, ", but got ", *response)
595 }
596 for i, match := range expected.DriverRankingList {
597 if !reflect.DeepEqual(*match, *response.DriverRankingList[i]) {
598 t.Fatal("Expected for driver ranking", i, ":", *match, ", but got:", *response.DriverRankingList[i])
599 }
600 }
601}
602
603// Validates that we can request all notes.
604func TestRequestAllNotes(t *testing.T) {
605 db := MockDatabase{
606 notes: []db.NotesData{
607 {
608 TeamNumber: 971,
609 Notes: "Notes",
610 GoodDriving: true,
611 BadDriving: false,
612 SketchyClimb: true,
613 SolidClimb: false,
614 GoodDefense: true,
615 BadDefense: false,
616 },
617 {
618 TeamNumber: 972,
619 Notes: "More Notes",
620 GoodDriving: false,
621 BadDriving: false,
622 SketchyClimb: false,
623 SolidClimb: true,
624 GoodDefense: false,
625 BadDefense: true,
626 },
627 },
628 }
629 scoutingServer := server.NewScoutingServer()
630 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
631 scoutingServer.Start(8080)
632 defer scoutingServer.Stop()
633
634 builder := flatbuffers.NewBuilder(1024)
635 builder.Finish((&request_all_notes.RequestAllNotesT{}).Pack(builder))
636
637 response, err := debug.RequestAllNotes("http://localhost:8080", builder.FinishedBytes())
638 if err != nil {
639 t.Fatal("Failed to request all notes: ", err)
640 }
641
642 expected := request_all_notes_response.RequestAllNotesResponseT{
643 NoteList: []*request_all_notes_response.NoteT{
644 {
645 Team: 971,
646 Notes: "Notes",
647 GoodDriving: true,
648 BadDriving: false,
649 SketchyClimb: true,
650 SolidClimb: false,
651 GoodDefense: true,
652 BadDefense: false,
653 },
654 {
655 Team: 972,
656 Notes: "More Notes",
657 GoodDriving: false,
658 BadDriving: false,
659 SketchyClimb: false,
660 SolidClimb: true,
661 GoodDefense: false,
662 BadDefense: true,
663 },
664 },
665 }
666 if len(expected.NoteList) != len(response.NoteList) {
667 t.Fatal("Expected ", expected, ", but got ", *response)
668 }
669 for i, note := range expected.NoteList {
670 if !reflect.DeepEqual(*note, *response.NoteList[i]) {
671 t.Fatal("Expected for note", i, ":", *note, ", but got:", *response.NoteList[i])
672 }
673 }
674}
675
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800676// A mocked database we can use for testing. Add functionality to this as
677// needed for your tests.
678
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800679type MockDatabase struct {
Filip Kujawa210a03b2022-11-24 14:41:11 -0800680 matches []db.Match
681 stats []db.Stats
682 notes []db.NotesData
683 shiftSchedule []db.Shift
684 driver_ranking []db.DriverRankingData
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800685}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800686
Philipp Schraderd3fac192022-03-02 20:35:46 -0800687func (database *MockDatabase) AddToMatch(match db.Match) error {
688 database.matches = append(database.matches, match)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800689 return nil
690}
691
Philipp Schrader30005e42022-03-06 13:53:58 -0800692func (database *MockDatabase) AddToStats(stats db.Stats) error {
693 database.stats = append(database.stats, stats)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800694 return nil
695}
696
697func (database *MockDatabase) ReturnMatches() ([]db.Match, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800698 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800699}
700
701func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
Philipp Schraderacf96232022-03-01 22:03:30 -0800702 return database.stats, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800703}
704
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800705func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
706 return []db.Stats{}, nil
707}
Philipp Schraderd3fac192022-03-02 20:35:46 -0800708
Philipp Schradereecb8962022-06-01 21:02:42 -0700709func (database *MockDatabase) QueryNotes(requestedTeam int32) ([]string, error) {
Alex Perry81f96ba2022-03-13 18:26:19 -0700710 var results []string
711 for _, data := range database.notes {
712 if data.TeamNumber == requestedTeam {
Philipp Schradereecb8962022-06-01 21:02:42 -0700713 results = append(results, data.Notes)
Alex Perry81f96ba2022-03-13 18:26:19 -0700714 }
715 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700716 return results, nil
Alex Perry81f96ba2022-03-13 18:26:19 -0700717}
718
Filip Kujawaf947cb42022-11-21 10:00:30 -0800719func (database *MockDatabase) AddNotes(data db.NotesData) error {
720 database.notes = append(database.notes, data)
Alex Perry81f96ba2022-03-13 18:26:19 -0700721 return nil
722}
723
Filip Kujawaf882e022022-12-14 13:14:08 -0800724func (database *MockDatabase) ReturnAllNotes() ([]db.NotesData, error) {
725 return database.notes, nil
726}
727
Milo Lin1d59f0c2022-06-22 20:30:58 -0700728func (database *MockDatabase) AddToShift(data db.Shift) error {
729 database.shiftSchedule = append(database.shiftSchedule, data)
730 return nil
731}
732
733func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
734 return database.shiftSchedule, nil
735}
736
737func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
738 return []db.Shift{}, nil
739}
740
Filip Kujawa210a03b2022-11-24 14:41:11 -0800741func (database *MockDatabase) AddDriverRanking(data db.DriverRankingData) error {
742 database.driver_ranking = append(database.driver_ranking, data)
743 return nil
744}
745
Filip Kujawaf882e022022-12-14 13:14:08 -0800746func (database *MockDatabase) ReturnAllDriverRankings() ([]db.DriverRankingData, error) {
747 return database.driver_ranking, nil
748}
749
Philipp Schraderd3fac192022-03-02 20:35:46 -0800750// Returns an empty match list from the fake The Blue Alliance scraping.
751func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
752 return nil, nil
753}