blob: 44fd5dbb395652a7b459cc5b2c38529389987ac8 [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"
Alex Perry81f96ba2022-03-13 18:26:19 -070027 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes"
Milo Lin1d59f0c2022-06-22 20:30:58 -070028 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080029 "github.com/frc971/971-Robot-Code/scouting/webserver/server"
30 flatbuffers "github.com/google/flatbuffers/go"
31)
32
33// Validates that an unhandled address results in a 404.
34func Test404(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080035 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080036 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080037 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080038 scoutingServer.Start(8080)
39 defer scoutingServer.Stop()
40
41 resp, err := http.Get("http://localhost:8080/requests/foo")
42 if err != nil {
43 t.Fatalf("Failed to get data: %v", err)
44 }
45 if resp.StatusCode != http.StatusNotFound {
46 t.Fatalf("Expected error code 404, but got %d instead", resp.Status)
47 }
48}
49
50// Validates that we can submit new data scouting data.
51func TestSubmitDataScoutingError(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080052 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080053 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080054 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080055 scoutingServer.Start(8080)
56 defer scoutingServer.Stop()
57
58 resp, err := http.Post("http://localhost:8080/requests/submit/data_scouting", "application/octet-stream", bytes.NewReader([]byte("")))
59 if err != nil {
60 t.Fatalf("Failed to send request: %v", err)
61 }
62 if resp.StatusCode != http.StatusBadRequest {
63 t.Fatal("Unexpected status code. Got", resp.Status)
64 }
65
66 responseBytes, err := io.ReadAll(resp.Body)
67 if err != nil {
68 t.Fatal("Failed to read response bytes:", err)
69 }
70 errorResponse := error_response.GetRootAsErrorResponse(responseBytes, 0)
71
72 errorMessage := string(errorResponse.ErrorMessage())
73 if errorMessage != "Failed to parse SubmitDataScouting: runtime error: index out of range [3] with length 0" {
74 t.Fatal("Got mismatched error message:", errorMessage)
75 }
76}
77
78// Validates that we can submit new data scouting data.
79func TestSubmitDataScouting(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080080 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080081 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080082 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080083 scoutingServer.Start(8080)
84 defer scoutingServer.Stop()
85
86 builder := flatbuffers.NewBuilder(1024)
87 builder.Finish((&submit_data_scouting.SubmitDataScoutingT{
Philipp Schraderfa45d742022-03-18 19:29:05 -070088 Team: 971,
89 Match: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -070090 SetNumber: 8,
Philipp Schrader4535b7e2022-04-08 20:27:00 -070091 CompLevel: "quals",
Philipp Schraderfa45d742022-03-18 19:29:05 -070092 StartingQuadrant: 2,
93 AutoBall1: true,
94 AutoBall2: false,
95 AutoBall3: false,
96 AutoBall4: false,
97 AutoBall5: false,
98 MissedShotsAuto: 9971,
99 UpperGoalAuto: 9971,
100 LowerGoalAuto: 9971,
101 MissedShotsTele: 9971,
102 UpperGoalTele: 9971,
103 LowerGoalTele: 9971,
104 DefenseRating: 9971,
105 DefenseReceivedRating: 4,
106 ClimbLevel: submit_data_scouting.ClimbLevelLow,
107 Comment: "this is a comment",
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800108 }).Pack(builder))
109
Philipp Schrader30005e42022-03-06 13:53:58 -0800110 response, err := debug.SubmitDataScouting("http://localhost:8080", builder.FinishedBytes())
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800111 if err != nil {
Philipp Schrader30005e42022-03-06 13:53:58 -0800112 t.Fatal("Failed to submit data scouting: ", err)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800113 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800114
115 // We get an empty response back. Validate that.
116 expected := submit_data_scouting_response.SubmitDataScoutingResponseT{}
117 if !reflect.DeepEqual(expected, *response) {
118 t.Fatal("Expected ", expected, ", but got:", *response)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800119 }
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800120}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800121
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800122// Validates that we can request the full match list.
123func TestRequestAllMatches(t *testing.T) {
124 db := MockDatabase{
125 matches: []db.Match{
126 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700127 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800128 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
129 },
130 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700131 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800132 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
133 },
134 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700135 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800136 R1: 7, R2: 44, R3: 602, B1: 973, B2: 402, B3: 202,
137 },
138 },
139 }
140 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800141 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800142 scoutingServer.Start(8080)
143 defer scoutingServer.Stop()
144
145 builder := flatbuffers.NewBuilder(1024)
146 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
147
148 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
149 if err != nil {
150 t.Fatal("Failed to request all matches: ", err)
151 }
152
153 expected := request_all_matches_response.RequestAllMatchesResponseT{
154 MatchList: []*request_all_matches_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700155 // MatchNumber, SetNumber, CompLevel
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800156 // R1, R2, R3, B1, B2, B3
157 {
158 1, 1, "qual",
159 5, 42, 600, 971, 400, 200,
160 },
161 {
162 2, 1, "qual",
163 6, 43, 601, 972, 401, 201,
164 },
165 {
166 3, 1, "qual",
167 7, 44, 602, 973, 402, 202,
168 },
169 },
170 }
171 if len(expected.MatchList) != len(response.MatchList) {
172 t.Fatal("Expected ", expected, ", but got ", *response)
173 }
174 for i, match := range expected.MatchList {
175 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
176 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
177 }
178 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800179
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800180}
181
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800182// Validates that we can request the full match list.
183func TestRequestMatchesForTeam(t *testing.T) {
184 db := MockDatabase{
185 matches: []db.Match{
186 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700187 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800188 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
189 },
190 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700191 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800192 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
193 },
194 },
195 }
196 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800197 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800198 scoutingServer.Start(8080)
199 defer scoutingServer.Stop()
200
201 builder := flatbuffers.NewBuilder(1024)
202 builder.Finish((&request_matches_for_team.RequestMatchesForTeamT{
203 Team: 971,
204 }).Pack(builder))
205
206 response, err := debug.RequestMatchesForTeam("http://localhost:8080", builder.FinishedBytes())
207 if err != nil {
208 t.Fatal("Failed to request all matches: ", err)
209 }
210
211 expected := request_matches_for_team_response.RequestMatchesForTeamResponseT{
212 MatchList: []*request_matches_for_team_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700213 // MatchNumber, SetNumber, CompLevel
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800214 // R1, R2, R3, B1, B2, B3
215 {
216 1, 1, "qual",
217 5, 42, 600, 971, 400, 200,
218 },
219 },
220 }
221 if len(expected.MatchList) != len(response.MatchList) {
222 t.Fatal("Expected ", expected, ", but got ", *response)
223 }
224 for i, match := range expected.MatchList {
225 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
226 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
227 }
228 }
229}
230
Philipp Schraderacf96232022-03-01 22:03:30 -0800231// Validates that we can request the stats.
232func TestRequestDataScouting(t *testing.T) {
233 db := MockDatabase{
234 stats: []db.Stats{
235 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700236 TeamNumber: 971, MatchNumber: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700237 StartingQuadrant: 1,
238 AutoBallPickedUp: [5]bool{true, false, false, false, true},
239 ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
Philipp Schraderacf96232022-03-01 22:03:30 -0800240 ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700241 PlayedDefense: 7, DefenseReceivedScore: 3, Climbing: 2,
242 Comment: "a lovely comment", CollectedBy: "john",
Philipp Schraderacf96232022-03-01 22:03:30 -0800243 },
244 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700245 TeamNumber: 972, MatchNumber: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700246 StartingQuadrant: 2,
247 AutoBallPickedUp: [5]bool{false, false, true, false, false},
248 ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
Philipp Schraderacf96232022-03-01 22:03:30 -0800249 ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700250 PlayedDefense: 8, DefenseReceivedScore: 1, Climbing: 4,
251 Comment: "another lovely comment", CollectedBy: "andrea",
Philipp Schraderacf96232022-03-01 22:03:30 -0800252 },
253 },
254 }
255 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800256 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderacf96232022-03-01 22:03:30 -0800257 scoutingServer.Start(8080)
258 defer scoutingServer.Stop()
259
260 builder := flatbuffers.NewBuilder(1024)
261 builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
262
263 response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
264 if err != nil {
265 t.Fatal("Failed to request all matches: ", err)
266 }
267
268 expected := request_data_scouting_response.RequestDataScoutingResponseT{
269 StatsList: []*request_data_scouting_response.StatsT{
Philipp Schraderacf96232022-03-01 22:03:30 -0800270 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700271 Team: 971, Match: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700272 MissedShotsAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
273 MissedShotsTele: 1, UpperGoalTele: 2, LowerGoalTele: 3,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700274 DefenseRating: 7,
275 DefenseReceivedRating: 3,
276 CollectedBy: "john",
277 AutoBall1: true, AutoBall2: false, AutoBall3: false,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700278 AutoBall4: false, AutoBall5: true,
279 StartingQuadrant: 1,
280 ClimbLevel: request_data_scouting_response.ClimbLevelFailedWithPlentyOfTime,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700281 Comment: "a lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800282 },
283 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700284 Team: 972, Match: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700285 MissedShotsAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
286 MissedShotsTele: 2, UpperGoalTele: 3, LowerGoalTele: 4,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700287 DefenseRating: 8,
288 DefenseReceivedRating: 1,
289 CollectedBy: "andrea",
290 AutoBall1: false, AutoBall2: false, AutoBall3: true,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700291 AutoBall4: false, AutoBall5: false,
292 StartingQuadrant: 2,
293 ClimbLevel: request_data_scouting_response.ClimbLevelMedium,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700294 Comment: "another lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800295 },
296 },
297 }
298 if len(expected.StatsList) != len(response.StatsList) {
299 t.Fatal("Expected ", expected, ", but got ", *response)
300 }
301 for i, match := range expected.StatsList {
302 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
303 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
304 }
305 }
306}
307
Alex Perry81f96ba2022-03-13 18:26:19 -0700308func TestSubmitNotes(t *testing.T) {
309 database := MockDatabase{}
310 scoutingServer := server.NewScoutingServer()
311 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
312 scoutingServer.Start(8080)
313 defer scoutingServer.Stop()
314
315 builder := flatbuffers.NewBuilder(1024)
316 builder.Finish((&submit_notes.SubmitNotesT{
317 Team: 971,
318 Notes: "Notes",
319 }).Pack(builder))
320
321 _, err := debug.SubmitNotes("http://localhost:8080", builder.FinishedBytes())
322 if err != nil {
323 t.Fatal("Failed to submit notes: ", err)
324 }
325
326 expected := []db.NotesData{
327 {TeamNumber: 971, Notes: []string{"Notes"}},
328 }
329
330 if !reflect.DeepEqual(database.notes, expected) {
331 t.Fatal("Submitted notes did not match", expected, database.notes)
332 }
333}
334
335func TestRequestNotes(t *testing.T) {
336 database := MockDatabase{
337 notes: []db.NotesData{{
338 TeamNumber: 971,
339 Notes: []string{"Notes"},
340 }},
341 }
342 scoutingServer := server.NewScoutingServer()
343 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
344 scoutingServer.Start(8080)
345 defer scoutingServer.Stop()
346
347 builder := flatbuffers.NewBuilder(1024)
348 builder.Finish((&request_notes_for_team.RequestNotesForTeamT{
349 Team: 971,
350 }).Pack(builder))
351 response, err := debug.RequestNotes("http://localhost:8080", builder.FinishedBytes())
352 if err != nil {
353 t.Fatal("Failed to submit notes: ", err)
354 }
355
356 if response.Notes[0].Data != "Notes" {
357 t.Fatal("requested notes did not match", response)
358 }
359}
360
Milo Lin1d59f0c2022-06-22 20:30:58 -0700361func TestRequestShiftSchedule(t *testing.T) {
362 db := MockDatabase{
363 shiftSchedule: []db.Shift{
364 {
365 MatchNumber: 1,
366 R1scouter: "Bob",
367 R2scouter: "James",
368 R3scouter: "Robert",
369 B1scouter: "Alice",
370 B2scouter: "Mary",
371 B3scouter: "Patricia",
372 },
373 {
374 MatchNumber: 2,
375 R1scouter: "Liam",
376 R2scouter: "Noah",
377 R3scouter: "Oliver",
378 B1scouter: "Emma",
379 B2scouter: "Charlotte",
380 B3scouter: "Amelia",
381 },
382 },
383 }
384 scoutingServer := server.NewScoutingServer()
385 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
386 scoutingServer.Start(8080)
387 defer scoutingServer.Stop()
388
389 builder := flatbuffers.NewBuilder(1024)
390 builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
391
392 response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
393 if err != nil {
394 t.Fatal("Failed to request shift schedule: ", err)
395 }
396
397 expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
398 ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
399 {
400 MatchNumber: 1,
401 R1scouter: "Bob",
402 R2scouter: "James",
403 R3scouter: "Robert",
404 B1scouter: "Alice",
405 B2scouter: "Mary",
406 B3scouter: "Patricia",
407 },
408 {
409 MatchNumber: 2,
410 R1scouter: "Liam",
411 R2scouter: "Noah",
412 R3scouter: "Oliver",
413 B1scouter: "Emma",
414 B2scouter: "Charlotte",
415 B3scouter: "Amelia",
416 },
417 },
418 }
419 if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
420 t.Fatal("Expected ", expected, ", but got ", *response)
421 }
422 for i, match := range expected.ShiftSchedule {
423 if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
424 t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
425 }
426 }
427}
428
429func TestSubmitShiftSchedule(t *testing.T) {
430 database := MockDatabase{}
431 scoutingServer := server.NewScoutingServer()
432 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
433 scoutingServer.Start(8080)
434 defer scoutingServer.Stop()
435
436 builder := flatbuffers.NewBuilder(1024)
437 builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
438 ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
439 {MatchNumber: 1,
440 R1scouter: "Bob",
441 R2scouter: "James",
442 R3scouter: "Robert",
443 B1scouter: "Alice",
444 B2scouter: "Mary",
445 B3scouter: "Patricia"},
446 },
447 }).Pack(builder))
448
449 _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
450 if err != nil {
451 t.Fatal("Failed to submit shift schedule: ", err)
452 }
453
454 expected := []db.Shift{
455 {MatchNumber: 1,
456 R1scouter: "Bob",
457 R2scouter: "James",
458 R3scouter: "Robert",
459 B1scouter: "Alice",
460 B2scouter: "Mary",
461 B3scouter: "Patricia"},
462 }
463 if !reflect.DeepEqual(expected, database.shiftSchedule) {
464 t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
465 }
466}
467
Philipp Schraderd3fac192022-03-02 20:35:46 -0800468// Validates that we can download the schedule from The Blue Alliance.
469func TestRefreshMatchList(t *testing.T) {
470 scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
471 return []scraping.Match{
472 {
473 CompLevel: "qual",
474 MatchNumber: 1,
Philipp Schrader45befdd2022-04-08 19:12:44 -0700475 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800476 Alliances: scraping.Alliances{
477 Red: scraping.Alliance{
478 TeamKeys: []string{
479 "100",
480 "200",
481 "300",
482 },
483 },
484 Blue: scraping.Alliance{
485 TeamKeys: []string{
486 "101",
487 "201",
488 "301",
489 },
490 },
491 },
492 WinningAlliance: "",
493 EventKey: "",
494 Time: 0,
495 PredictedTime: 0,
496 ActualTime: 0,
497 PostResultTime: 0,
498 ScoreBreakdowns: scraping.ScoreBreakdowns{},
499 },
500 }, nil
501 }
502
503 database := MockDatabase{}
504 scoutingServer := server.NewScoutingServer()
505 HandleRequests(&database, scrapeMockSchedule, scoutingServer)
506 scoutingServer.Start(8080)
507 defer scoutingServer.Stop()
508
509 builder := flatbuffers.NewBuilder(1024)
510 builder.Finish((&refresh_match_list.RefreshMatchListT{}).Pack(builder))
511
512 response, err := debug.RefreshMatchList("http://localhost:8080", builder.FinishedBytes())
513 if err != nil {
514 t.Fatal("Failed to request all matches: ", err)
515 }
516
517 // Validate the response.
518 expected := refresh_match_list_response.RefreshMatchListResponseT{}
519 if !reflect.DeepEqual(expected, *response) {
520 t.Fatal("Expected ", expected, ", but got ", *response)
521 }
522
523 // Make sure that the data made it into the database.
524 expectedMatches := []db.Match{
525 {
526 MatchNumber: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -0700527 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800528 CompLevel: "qual",
529 R1: 100,
530 R2: 200,
531 R3: 300,
532 B1: 101,
533 B2: 201,
534 B3: 301,
535 },
536 }
537 if !reflect.DeepEqual(expectedMatches, database.matches) {
538 t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
539 }
540}
541
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800542// A mocked database we can use for testing. Add functionality to this as
543// needed for your tests.
544
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800545type MockDatabase struct {
Milo Lin1d59f0c2022-06-22 20:30:58 -0700546 matches []db.Match
547 stats []db.Stats
548 notes []db.NotesData
549 shiftSchedule []db.Shift
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800550}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800551
Philipp Schraderd3fac192022-03-02 20:35:46 -0800552func (database *MockDatabase) AddToMatch(match db.Match) error {
553 database.matches = append(database.matches, match)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800554 return nil
555}
556
Philipp Schrader30005e42022-03-06 13:53:58 -0800557func (database *MockDatabase) AddToStats(stats db.Stats) error {
558 database.stats = append(database.stats, stats)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800559 return nil
560}
561
562func (database *MockDatabase) ReturnMatches() ([]db.Match, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800563 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800564}
565
566func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
Philipp Schraderacf96232022-03-01 22:03:30 -0800567 return database.stats, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800568}
569
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800570func (database *MockDatabase) QueryMatches(requestedTeam int32) ([]db.Match, error) {
571 var matches []db.Match
572 for _, match := range database.matches {
573 for _, team := range []int32{match.R1, match.R2, match.R3, match.B1, match.B2, match.B3} {
574 if team == requestedTeam {
575 matches = append(matches, match)
576 break
577 }
578 }
579 }
580 return matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800581}
582
583func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
584 return []db.Stats{}, nil
585}
Philipp Schraderd3fac192022-03-02 20:35:46 -0800586
Alex Perry81f96ba2022-03-13 18:26:19 -0700587func (database *MockDatabase) QueryNotes(requestedTeam int32) (db.NotesData, error) {
588 var results []string
589 for _, data := range database.notes {
590 if data.TeamNumber == requestedTeam {
591 results = append(results, data.Notes[0])
592 }
593 }
594 return db.NotesData{TeamNumber: requestedTeam, Notes: results}, nil
595}
596
597func (database *MockDatabase) AddNotes(data db.NotesData) error {
598 database.notes = append(database.notes, data)
599 return nil
600}
601
Milo Lin1d59f0c2022-06-22 20:30:58 -0700602func (database *MockDatabase) AddToShift(data db.Shift) error {
603 database.shiftSchedule = append(database.shiftSchedule, data)
604 return nil
605}
606
607func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
608 return database.shiftSchedule, nil
609}
610
611func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
612 return []db.Shift{}, nil
613}
614
Philipp Schraderd3fac192022-03-02 20:35:46 -0800615// Returns an empty match list from the fake The Blue Alliance scraping.
616func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
617 return nil, nil
618}