blob: 55b789b393b12f75b7ea5b7665c7d4253d73a8f6 [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"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080016 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
17 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
Philipp Schraderacf96232022-03-01 22:03:30 -080018 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting"
19 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
Philipp Schraderd1c4bef2022-02-28 22:51:30 -080020 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team"
21 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070022 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
Milo Lin1d59f0c2022-06-22 20:30:58 -070023 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule"
24 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080025 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
Philipp Schrader30005e42022-03-06 13:53:58 -080026 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
Filip Kujawa210a03b2022-11-24 14:41:11 -080027 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking"
Alex Perry81f96ba2022-03-13 18:26:19 -070028 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes"
Milo Lin1d59f0c2022-06-22 20:30:58 -070029 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080030 "github.com/frc971/971-Robot-Code/scouting/webserver/server"
31 flatbuffers "github.com/google/flatbuffers/go"
32)
33
34// Validates that an unhandled address results in a 404.
35func Test404(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080036 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080037 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080038 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080039 scoutingServer.Start(8080)
40 defer scoutingServer.Stop()
41
42 resp, err := http.Get("http://localhost:8080/requests/foo")
43 if err != nil {
44 t.Fatalf("Failed to get data: %v", err)
45 }
46 if resp.StatusCode != http.StatusNotFound {
47 t.Fatalf("Expected error code 404, but got %d instead", resp.Status)
48 }
49}
50
51// Validates that we can submit new data scouting data.
52func TestSubmitDataScoutingError(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080053 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080054 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080055 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080056 scoutingServer.Start(8080)
57 defer scoutingServer.Stop()
58
59 resp, err := http.Post("http://localhost:8080/requests/submit/data_scouting", "application/octet-stream", bytes.NewReader([]byte("")))
60 if err != nil {
61 t.Fatalf("Failed to send request: %v", err)
62 }
63 if resp.StatusCode != http.StatusBadRequest {
64 t.Fatal("Unexpected status code. Got", resp.Status)
65 }
66
67 responseBytes, err := io.ReadAll(resp.Body)
68 if err != nil {
69 t.Fatal("Failed to read response bytes:", err)
70 }
71 errorResponse := error_response.GetRootAsErrorResponse(responseBytes, 0)
72
73 errorMessage := string(errorResponse.ErrorMessage())
74 if errorMessage != "Failed to parse SubmitDataScouting: runtime error: index out of range [3] with length 0" {
75 t.Fatal("Got mismatched error message:", errorMessage)
76 }
77}
78
79// Validates that we can submit new data scouting data.
80func TestSubmitDataScouting(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080081 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080082 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080083 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080084 scoutingServer.Start(8080)
85 defer scoutingServer.Stop()
86
87 builder := flatbuffers.NewBuilder(1024)
88 builder.Finish((&submit_data_scouting.SubmitDataScoutingT{
Philipp Schraderfa45d742022-03-18 19:29:05 -070089 Team: 971,
90 Match: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -070091 SetNumber: 8,
Philipp Schrader4535b7e2022-04-08 20:27:00 -070092 CompLevel: "quals",
Philipp Schraderfa45d742022-03-18 19:29:05 -070093 StartingQuadrant: 2,
94 AutoBall1: true,
95 AutoBall2: false,
96 AutoBall3: false,
97 AutoBall4: false,
98 AutoBall5: false,
99 MissedShotsAuto: 9971,
100 UpperGoalAuto: 9971,
101 LowerGoalAuto: 9971,
102 MissedShotsTele: 9971,
103 UpperGoalTele: 9971,
104 LowerGoalTele: 9971,
105 DefenseRating: 9971,
106 DefenseReceivedRating: 4,
107 ClimbLevel: submit_data_scouting.ClimbLevelLow,
108 Comment: "this is a comment",
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800109 }).Pack(builder))
110
Philipp Schrader30005e42022-03-06 13:53:58 -0800111 response, err := debug.SubmitDataScouting("http://localhost:8080", builder.FinishedBytes())
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800112 if err != nil {
Philipp Schrader30005e42022-03-06 13:53:58 -0800113 t.Fatal("Failed to submit data scouting: ", err)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800114 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800115
116 // We get an empty response back. Validate that.
117 expected := submit_data_scouting_response.SubmitDataScoutingResponseT{}
118 if !reflect.DeepEqual(expected, *response) {
119 t.Fatal("Expected ", expected, ", but got:", *response)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800120 }
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800121}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800122
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800123// Validates that we can request the full match list.
124func TestRequestAllMatches(t *testing.T) {
125 db := MockDatabase{
126 matches: []db.Match{
127 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700128 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800129 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
130 },
131 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700132 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800133 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
134 },
135 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700136 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800137 R1: 7, R2: 44, R3: 602, B1: 973, B2: 402, B3: 202,
138 },
139 },
140 }
141 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800142 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800143 scoutingServer.Start(8080)
144 defer scoutingServer.Stop()
145
146 builder := flatbuffers.NewBuilder(1024)
147 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
148
149 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
150 if err != nil {
151 t.Fatal("Failed to request all matches: ", err)
152 }
153
154 expected := request_all_matches_response.RequestAllMatchesResponseT{
155 MatchList: []*request_all_matches_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700156 // MatchNumber, SetNumber, CompLevel
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800157 // R1, R2, R3, B1, B2, B3
158 {
159 1, 1, "qual",
160 5, 42, 600, 971, 400, 200,
161 },
162 {
163 2, 1, "qual",
164 6, 43, 601, 972, 401, 201,
165 },
166 {
167 3, 1, "qual",
168 7, 44, 602, 973, 402, 202,
169 },
170 },
171 }
172 if len(expected.MatchList) != len(response.MatchList) {
173 t.Fatal("Expected ", expected, ", but got ", *response)
174 }
175 for i, match := range expected.MatchList {
176 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
177 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
178 }
179 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800180
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800181}
182
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800183// Validates that we can request the full match list.
184func TestRequestMatchesForTeam(t *testing.T) {
185 db := MockDatabase{
186 matches: []db.Match{
187 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700188 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800189 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
190 },
191 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700192 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800193 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
194 },
195 },
196 }
197 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800198 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800199 scoutingServer.Start(8080)
200 defer scoutingServer.Stop()
201
202 builder := flatbuffers.NewBuilder(1024)
203 builder.Finish((&request_matches_for_team.RequestMatchesForTeamT{
204 Team: 971,
205 }).Pack(builder))
206
207 response, err := debug.RequestMatchesForTeam("http://localhost:8080", builder.FinishedBytes())
208 if err != nil {
209 t.Fatal("Failed to request all matches: ", err)
210 }
211
212 expected := request_matches_for_team_response.RequestMatchesForTeamResponseT{
213 MatchList: []*request_matches_for_team_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700214 // MatchNumber, SetNumber, CompLevel
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800215 // R1, R2, R3, B1, B2, B3
216 {
217 1, 1, "qual",
218 5, 42, 600, 971, 400, 200,
219 },
220 },
221 }
222 if len(expected.MatchList) != len(response.MatchList) {
223 t.Fatal("Expected ", expected, ", but got ", *response)
224 }
225 for i, match := range expected.MatchList {
226 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
227 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
228 }
229 }
230}
231
Philipp Schraderacf96232022-03-01 22:03:30 -0800232// Validates that we can request the stats.
233func TestRequestDataScouting(t *testing.T) {
234 db := MockDatabase{
235 stats: []db.Stats{
236 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700237 TeamNumber: 971, MatchNumber: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700238 StartingQuadrant: 1,
239 AutoBallPickedUp: [5]bool{true, false, false, false, true},
240 ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
Philipp Schraderacf96232022-03-01 22:03:30 -0800241 ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700242 PlayedDefense: 7, DefenseReceivedScore: 3, Climbing: 2,
243 Comment: "a lovely comment", CollectedBy: "john",
Philipp Schraderacf96232022-03-01 22:03:30 -0800244 },
245 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700246 TeamNumber: 972, MatchNumber: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700247 StartingQuadrant: 2,
248 AutoBallPickedUp: [5]bool{false, false, true, false, false},
249 ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
Philipp Schraderacf96232022-03-01 22:03:30 -0800250 ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700251 PlayedDefense: 8, DefenseReceivedScore: 1, Climbing: 4,
252 Comment: "another lovely comment", CollectedBy: "andrea",
Philipp Schraderacf96232022-03-01 22:03:30 -0800253 },
254 },
255 }
256 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800257 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderacf96232022-03-01 22:03:30 -0800258 scoutingServer.Start(8080)
259 defer scoutingServer.Stop()
260
261 builder := flatbuffers.NewBuilder(1024)
262 builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
263
264 response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
265 if err != nil {
266 t.Fatal("Failed to request all matches: ", err)
267 }
268
269 expected := request_data_scouting_response.RequestDataScoutingResponseT{
270 StatsList: []*request_data_scouting_response.StatsT{
Philipp Schraderacf96232022-03-01 22:03:30 -0800271 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700272 Team: 971, Match: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700273 MissedShotsAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
274 MissedShotsTele: 1, UpperGoalTele: 2, LowerGoalTele: 3,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700275 DefenseRating: 7,
276 DefenseReceivedRating: 3,
277 CollectedBy: "john",
278 AutoBall1: true, AutoBall2: false, AutoBall3: false,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700279 AutoBall4: false, AutoBall5: true,
280 StartingQuadrant: 1,
281 ClimbLevel: request_data_scouting_response.ClimbLevelFailedWithPlentyOfTime,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700282 Comment: "a lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800283 },
284 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700285 Team: 972, Match: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700286 MissedShotsAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
287 MissedShotsTele: 2, UpperGoalTele: 3, LowerGoalTele: 4,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700288 DefenseRating: 8,
289 DefenseReceivedRating: 1,
290 CollectedBy: "andrea",
291 AutoBall1: false, AutoBall2: false, AutoBall3: true,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700292 AutoBall4: false, AutoBall5: false,
293 StartingQuadrant: 2,
294 ClimbLevel: request_data_scouting_response.ClimbLevelMedium,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700295 Comment: "another lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800296 },
297 },
298 }
299 if len(expected.StatsList) != len(response.StatsList) {
300 t.Fatal("Expected ", expected, ", but got ", *response)
301 }
302 for i, match := range expected.StatsList {
303 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
304 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
305 }
306 }
307}
308
Alex Perry81f96ba2022-03-13 18:26:19 -0700309func TestSubmitNotes(t *testing.T) {
310 database := MockDatabase{}
311 scoutingServer := server.NewScoutingServer()
312 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
313 scoutingServer.Start(8080)
314 defer scoutingServer.Stop()
315
316 builder := flatbuffers.NewBuilder(1024)
317 builder.Finish((&submit_notes.SubmitNotesT{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800318 Team: 971,
319 Notes: "Notes",
320 GoodDriving: true,
321 BadDriving: false,
322 SketchyClimb: true,
323 SolidClimb: false,
324 GoodDefense: true,
325 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700326 }).Pack(builder))
327
328 _, err := debug.SubmitNotes("http://localhost:8080", builder.FinishedBytes())
329 if err != nil {
330 t.Fatal("Failed to submit notes: ", err)
331 }
332
333 expected := []db.NotesData{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800334 {
335 TeamNumber: 971,
336 Notes: "Notes",
337 GoodDriving: true,
338 BadDriving: false,
339 SketchyClimb: true,
340 SolidClimb: false,
341 GoodDefense: true,
342 BadDefense: false,
343 },
Alex Perry81f96ba2022-03-13 18:26:19 -0700344 }
345
346 if !reflect.DeepEqual(database.notes, expected) {
347 t.Fatal("Submitted notes did not match", expected, database.notes)
348 }
349}
350
351func TestRequestNotes(t *testing.T) {
352 database := MockDatabase{
353 notes: []db.NotesData{{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800354 TeamNumber: 971,
355 Notes: "Notes",
356 GoodDriving: true,
357 BadDriving: false,
358 SketchyClimb: true,
359 SolidClimb: false,
360 GoodDefense: true,
361 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700362 }},
363 }
364 scoutingServer := server.NewScoutingServer()
365 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
366 scoutingServer.Start(8080)
367 defer scoutingServer.Stop()
368
369 builder := flatbuffers.NewBuilder(1024)
370 builder.Finish((&request_notes_for_team.RequestNotesForTeamT{
371 Team: 971,
372 }).Pack(builder))
373 response, err := debug.RequestNotes("http://localhost:8080", builder.FinishedBytes())
374 if err != nil {
375 t.Fatal("Failed to submit notes: ", err)
376 }
377
378 if response.Notes[0].Data != "Notes" {
379 t.Fatal("requested notes did not match", response)
380 }
381}
382
Milo Lin1d59f0c2022-06-22 20:30:58 -0700383func TestRequestShiftSchedule(t *testing.T) {
384 db := MockDatabase{
385 shiftSchedule: []db.Shift{
386 {
387 MatchNumber: 1,
388 R1scouter: "Bob",
389 R2scouter: "James",
390 R3scouter: "Robert",
391 B1scouter: "Alice",
392 B2scouter: "Mary",
393 B3scouter: "Patricia",
394 },
395 {
396 MatchNumber: 2,
397 R1scouter: "Liam",
398 R2scouter: "Noah",
399 R3scouter: "Oliver",
400 B1scouter: "Emma",
401 B2scouter: "Charlotte",
402 B3scouter: "Amelia",
403 },
404 },
405 }
406 scoutingServer := server.NewScoutingServer()
407 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
408 scoutingServer.Start(8080)
409 defer scoutingServer.Stop()
410
411 builder := flatbuffers.NewBuilder(1024)
412 builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
413
414 response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
415 if err != nil {
416 t.Fatal("Failed to request shift schedule: ", err)
417 }
418
419 expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
420 ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
421 {
422 MatchNumber: 1,
423 R1scouter: "Bob",
424 R2scouter: "James",
425 R3scouter: "Robert",
426 B1scouter: "Alice",
427 B2scouter: "Mary",
428 B3scouter: "Patricia",
429 },
430 {
431 MatchNumber: 2,
432 R1scouter: "Liam",
433 R2scouter: "Noah",
434 R3scouter: "Oliver",
435 B1scouter: "Emma",
436 B2scouter: "Charlotte",
437 B3scouter: "Amelia",
438 },
439 },
440 }
441 if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
442 t.Fatal("Expected ", expected, ", but got ", *response)
443 }
444 for i, match := range expected.ShiftSchedule {
445 if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
446 t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
447 }
448 }
449}
450
451func TestSubmitShiftSchedule(t *testing.T) {
452 database := MockDatabase{}
453 scoutingServer := server.NewScoutingServer()
454 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
455 scoutingServer.Start(8080)
456 defer scoutingServer.Stop()
457
458 builder := flatbuffers.NewBuilder(1024)
459 builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
460 ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
461 {MatchNumber: 1,
462 R1scouter: "Bob",
463 R2scouter: "James",
464 R3scouter: "Robert",
465 B1scouter: "Alice",
466 B2scouter: "Mary",
467 B3scouter: "Patricia"},
468 },
469 }).Pack(builder))
470
471 _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
472 if err != nil {
473 t.Fatal("Failed to submit shift schedule: ", err)
474 }
475
476 expected := []db.Shift{
477 {MatchNumber: 1,
478 R1scouter: "Bob",
479 R2scouter: "James",
480 R3scouter: "Robert",
481 B1scouter: "Alice",
482 B2scouter: "Mary",
483 B3scouter: "Patricia"},
484 }
485 if !reflect.DeepEqual(expected, database.shiftSchedule) {
486 t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
487 }
488}
489
Philipp Schraderd3fac192022-03-02 20:35:46 -0800490// Validates that we can download the schedule from The Blue Alliance.
491func TestRefreshMatchList(t *testing.T) {
492 scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
493 return []scraping.Match{
494 {
495 CompLevel: "qual",
496 MatchNumber: 1,
Philipp Schrader45befdd2022-04-08 19:12:44 -0700497 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800498 Alliances: scraping.Alliances{
499 Red: scraping.Alliance{
500 TeamKeys: []string{
501 "100",
502 "200",
503 "300",
504 },
505 },
506 Blue: scraping.Alliance{
507 TeamKeys: []string{
508 "101",
509 "201",
510 "301",
511 },
512 },
513 },
514 WinningAlliance: "",
515 EventKey: "",
516 Time: 0,
517 PredictedTime: 0,
518 ActualTime: 0,
519 PostResultTime: 0,
520 ScoreBreakdowns: scraping.ScoreBreakdowns{},
521 },
522 }, nil
523 }
524
525 database := MockDatabase{}
526 scoutingServer := server.NewScoutingServer()
527 HandleRequests(&database, scrapeMockSchedule, scoutingServer)
528 scoutingServer.Start(8080)
529 defer scoutingServer.Stop()
530
531 builder := flatbuffers.NewBuilder(1024)
532 builder.Finish((&refresh_match_list.RefreshMatchListT{}).Pack(builder))
533
534 response, err := debug.RefreshMatchList("http://localhost:8080", builder.FinishedBytes())
535 if err != nil {
536 t.Fatal("Failed to request all matches: ", err)
537 }
538
539 // Validate the response.
540 expected := refresh_match_list_response.RefreshMatchListResponseT{}
541 if !reflect.DeepEqual(expected, *response) {
542 t.Fatal("Expected ", expected, ", but got ", *response)
543 }
544
545 // Make sure that the data made it into the database.
546 expectedMatches := []db.Match{
547 {
548 MatchNumber: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -0700549 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800550 CompLevel: "qual",
551 R1: 100,
552 R2: 200,
553 R3: 300,
554 B1: 101,
555 B2: 201,
556 B3: 301,
557 },
558 }
559 if !reflect.DeepEqual(expectedMatches, database.matches) {
560 t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
561 }
562}
563
Filip Kujawa210a03b2022-11-24 14:41:11 -0800564func TestSubmitDriverRanking(t *testing.T) {
565 database := MockDatabase{}
566 scoutingServer := server.NewScoutingServer()
567 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
568 scoutingServer.Start(8080)
569 defer scoutingServer.Stop()
570
571 builder := flatbuffers.NewBuilder(1024)
572 builder.Finish((&submit_driver_ranking.SubmitDriverRankingT{
573 MatchNumber: 36,
574 Rank1: 1234,
575 Rank2: 1235,
576 Rank3: 1236,
577 }).Pack(builder))
578
579 _, err := debug.SubmitDriverRanking("http://localhost:8080", builder.FinishedBytes())
580 if err != nil {
581 t.Fatal("Failed to submit driver ranking: ", err)
582 }
583
584 expected := []db.DriverRankingData{
585 {MatchNumber: 36, Rank1: 1234, Rank2: 1235, Rank3: 1236},
586 }
587
588 if !reflect.DeepEqual(database.driver_ranking, expected) {
589 t.Fatal("Submitted notes did not match", expected, database.notes)
590 }
591}
592
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800593// A mocked database we can use for testing. Add functionality to this as
594// needed for your tests.
595
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800596type MockDatabase struct {
Filip Kujawa210a03b2022-11-24 14:41:11 -0800597 matches []db.Match
598 stats []db.Stats
599 notes []db.NotesData
600 shiftSchedule []db.Shift
601 driver_ranking []db.DriverRankingData
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800602}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800603
Philipp Schraderd3fac192022-03-02 20:35:46 -0800604func (database *MockDatabase) AddToMatch(match db.Match) error {
605 database.matches = append(database.matches, match)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800606 return nil
607}
608
Philipp Schrader30005e42022-03-06 13:53:58 -0800609func (database *MockDatabase) AddToStats(stats db.Stats) error {
610 database.stats = append(database.stats, stats)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800611 return nil
612}
613
614func (database *MockDatabase) ReturnMatches() ([]db.Match, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800615 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800616}
617
618func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
Philipp Schraderacf96232022-03-01 22:03:30 -0800619 return database.stats, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800620}
621
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800622func (database *MockDatabase) QueryMatches(requestedTeam int32) ([]db.Match, error) {
623 var matches []db.Match
624 for _, match := range database.matches {
625 for _, team := range []int32{match.R1, match.R2, match.R3, match.B1, match.B2, match.B3} {
626 if team == requestedTeam {
627 matches = append(matches, match)
628 break
629 }
630 }
631 }
632 return matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800633}
634
635func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
636 return []db.Stats{}, nil
637}
Philipp Schraderd3fac192022-03-02 20:35:46 -0800638
Philipp Schradereecb8962022-06-01 21:02:42 -0700639func (database *MockDatabase) QueryNotes(requestedTeam int32) ([]string, error) {
Alex Perry81f96ba2022-03-13 18:26:19 -0700640 var results []string
641 for _, data := range database.notes {
642 if data.TeamNumber == requestedTeam {
Philipp Schradereecb8962022-06-01 21:02:42 -0700643 results = append(results, data.Notes)
Alex Perry81f96ba2022-03-13 18:26:19 -0700644 }
645 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700646 return results, nil
Alex Perry81f96ba2022-03-13 18:26:19 -0700647}
648
Filip Kujawaf947cb42022-11-21 10:00:30 -0800649func (database *MockDatabase) AddNotes(data db.NotesData) error {
650 database.notes = append(database.notes, data)
Alex Perry81f96ba2022-03-13 18:26:19 -0700651 return nil
652}
653
Milo Lin1d59f0c2022-06-22 20:30:58 -0700654func (database *MockDatabase) AddToShift(data db.Shift) error {
655 database.shiftSchedule = append(database.shiftSchedule, data)
656 return nil
657}
658
659func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
660 return database.shiftSchedule, nil
661}
662
663func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
664 return []db.Shift{}, nil
665}
666
Filip Kujawa210a03b2022-11-24 14:41:11 -0800667func (database *MockDatabase) AddDriverRanking(data db.DriverRankingData) error {
668 database.driver_ranking = append(database.driver_ranking, data)
669 return nil
670}
671
Philipp Schraderd3fac192022-03-02 20:35:46 -0800672// Returns an empty match list from the fake The Blue Alliance scraping.
673func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
674 return nil, nil
675}