blob: ed8a3b5eb27d91b0465b3ef63c06eee03299a96d [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"
Philipp Schraderd1c4bef2022-02-28 22:51:30 -080024 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team"
25 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070026 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
Milo Lin1d59f0c2022-06-22 20:30:58 -070027 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule"
28 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080029 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
Philipp Schrader30005e42022-03-06 13:53:58 -080030 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
Filip Kujawa210a03b2022-11-24 14:41:11 -080031 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking"
Alex Perry81f96ba2022-03-13 18:26:19 -070032 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes"
Milo Lin1d59f0c2022-06-22 20:30:58 -070033 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080034 "github.com/frc971/971-Robot-Code/scouting/webserver/server"
35 flatbuffers "github.com/google/flatbuffers/go"
36)
37
38// Validates that an unhandled address results in a 404.
39func Test404(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080040 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080041 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080042 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080043 scoutingServer.Start(8080)
44 defer scoutingServer.Stop()
45
46 resp, err := http.Get("http://localhost:8080/requests/foo")
47 if err != nil {
48 t.Fatalf("Failed to get data: %v", err)
49 }
50 if resp.StatusCode != http.StatusNotFound {
51 t.Fatalf("Expected error code 404, but got %d instead", resp.Status)
52 }
53}
54
55// Validates that we can submit new data scouting data.
56func TestSubmitDataScoutingError(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080057 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080058 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080059 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080060 scoutingServer.Start(8080)
61 defer scoutingServer.Stop()
62
63 resp, err := http.Post("http://localhost:8080/requests/submit/data_scouting", "application/octet-stream", bytes.NewReader([]byte("")))
64 if err != nil {
65 t.Fatalf("Failed to send request: %v", err)
66 }
67 if resp.StatusCode != http.StatusBadRequest {
68 t.Fatal("Unexpected status code. Got", resp.Status)
69 }
70
71 responseBytes, err := io.ReadAll(resp.Body)
72 if err != nil {
73 t.Fatal("Failed to read response bytes:", err)
74 }
75 errorResponse := error_response.GetRootAsErrorResponse(responseBytes, 0)
76
77 errorMessage := string(errorResponse.ErrorMessage())
78 if errorMessage != "Failed to parse SubmitDataScouting: runtime error: index out of range [3] with length 0" {
79 t.Fatal("Got mismatched error message:", errorMessage)
80 }
81}
82
83// Validates that we can submit new data scouting data.
84func TestSubmitDataScouting(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080085 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080086 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -080087 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080088 scoutingServer.Start(8080)
89 defer scoutingServer.Stop()
90
91 builder := flatbuffers.NewBuilder(1024)
92 builder.Finish((&submit_data_scouting.SubmitDataScoutingT{
Philipp Schraderfa45d742022-03-18 19:29:05 -070093 Team: 971,
94 Match: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -070095 SetNumber: 8,
Philipp Schrader4535b7e2022-04-08 20:27:00 -070096 CompLevel: "quals",
Philipp Schraderfa45d742022-03-18 19:29:05 -070097 StartingQuadrant: 2,
98 AutoBall1: true,
99 AutoBall2: false,
100 AutoBall3: false,
101 AutoBall4: false,
102 AutoBall5: false,
103 MissedShotsAuto: 9971,
104 UpperGoalAuto: 9971,
105 LowerGoalAuto: 9971,
106 MissedShotsTele: 9971,
107 UpperGoalTele: 9971,
108 LowerGoalTele: 9971,
109 DefenseRating: 9971,
110 DefenseReceivedRating: 4,
111 ClimbLevel: submit_data_scouting.ClimbLevelLow,
112 Comment: "this is a comment",
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800113 }).Pack(builder))
114
Philipp Schrader30005e42022-03-06 13:53:58 -0800115 response, err := debug.SubmitDataScouting("http://localhost:8080", builder.FinishedBytes())
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800116 if err != nil {
Philipp Schrader30005e42022-03-06 13:53:58 -0800117 t.Fatal("Failed to submit data scouting: ", err)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800118 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800119
120 // We get an empty response back. Validate that.
121 expected := submit_data_scouting_response.SubmitDataScoutingResponseT{}
122 if !reflect.DeepEqual(expected, *response) {
123 t.Fatal("Expected ", expected, ", but got:", *response)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800124 }
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800125}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800126
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800127// Validates that we can request the full match list.
128func TestRequestAllMatches(t *testing.T) {
129 db := MockDatabase{
130 matches: []db.Match{
131 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700132 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800133 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
134 },
135 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700136 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800137 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
138 },
139 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700140 MatchNumber: 3, SetNumber: 1, CompLevel: "qual",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800141 R1: 7, R2: 44, R3: 602, B1: 973, B2: 402, B3: 202,
142 },
143 },
144 }
145 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800146 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800147 scoutingServer.Start(8080)
148 defer scoutingServer.Stop()
149
150 builder := flatbuffers.NewBuilder(1024)
151 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
152
153 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
154 if err != nil {
155 t.Fatal("Failed to request all matches: ", err)
156 }
157
158 expected := request_all_matches_response.RequestAllMatchesResponseT{
159 MatchList: []*request_all_matches_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700160 // MatchNumber, SetNumber, CompLevel
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800161 // R1, R2, R3, B1, B2, B3
162 {
163 1, 1, "qual",
164 5, 42, 600, 971, 400, 200,
165 },
166 {
167 2, 1, "qual",
168 6, 43, 601, 972, 401, 201,
169 },
170 {
171 3, 1, "qual",
172 7, 44, 602, 973, 402, 202,
173 },
174 },
175 }
176 if len(expected.MatchList) != len(response.MatchList) {
177 t.Fatal("Expected ", expected, ", but got ", *response)
178 }
179 for i, match := range expected.MatchList {
180 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
181 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
182 }
183 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800184
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800185}
186
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800187// Validates that we can request the full match list.
188func TestRequestMatchesForTeam(t *testing.T) {
189 db := MockDatabase{
190 matches: []db.Match{
191 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700192 MatchNumber: 1, SetNumber: 1, CompLevel: "qual",
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800193 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
194 },
195 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700196 MatchNumber: 2, SetNumber: 1, CompLevel: "qual",
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800197 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
198 },
199 },
200 }
201 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800202 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800203 scoutingServer.Start(8080)
204 defer scoutingServer.Stop()
205
206 builder := flatbuffers.NewBuilder(1024)
207 builder.Finish((&request_matches_for_team.RequestMatchesForTeamT{
208 Team: 971,
209 }).Pack(builder))
210
211 response, err := debug.RequestMatchesForTeam("http://localhost:8080", builder.FinishedBytes())
212 if err != nil {
213 t.Fatal("Failed to request all matches: ", err)
214 }
215
216 expected := request_matches_for_team_response.RequestMatchesForTeamResponseT{
217 MatchList: []*request_matches_for_team_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700218 // MatchNumber, SetNumber, CompLevel
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800219 // R1, R2, R3, B1, B2, B3
220 {
221 1, 1, "qual",
222 5, 42, 600, 971, 400, 200,
223 },
224 },
225 }
226 if len(expected.MatchList) != len(response.MatchList) {
227 t.Fatal("Expected ", expected, ", but got ", *response)
228 }
229 for i, match := range expected.MatchList {
230 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
231 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
232 }
233 }
234}
235
Philipp Schraderacf96232022-03-01 22:03:30 -0800236// Validates that we can request the stats.
237func TestRequestDataScouting(t *testing.T) {
238 db := MockDatabase{
239 stats: []db.Stats{
240 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700241 TeamNumber: 971, MatchNumber: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700242 StartingQuadrant: 1,
243 AutoBallPickedUp: [5]bool{true, false, false, false, true},
244 ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
Philipp Schraderacf96232022-03-01 22:03:30 -0800245 ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700246 PlayedDefense: 7, DefenseReceivedScore: 3, Climbing: 2,
247 Comment: "a lovely comment", CollectedBy: "john",
Philipp Schraderacf96232022-03-01 22:03:30 -0800248 },
249 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700250 TeamNumber: 972, MatchNumber: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700251 StartingQuadrant: 2,
252 AutoBallPickedUp: [5]bool{false, false, true, false, false},
253 ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
Philipp Schraderacf96232022-03-01 22:03:30 -0800254 ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700255 PlayedDefense: 8, DefenseReceivedScore: 1, Climbing: 4,
256 Comment: "another lovely comment", CollectedBy: "andrea",
Philipp Schraderacf96232022-03-01 22:03:30 -0800257 },
258 },
259 }
260 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800261 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderacf96232022-03-01 22:03:30 -0800262 scoutingServer.Start(8080)
263 defer scoutingServer.Stop()
264
265 builder := flatbuffers.NewBuilder(1024)
266 builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
267
268 response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
269 if err != nil {
270 t.Fatal("Failed to request all matches: ", err)
271 }
272
273 expected := request_data_scouting_response.RequestDataScoutingResponseT{
274 StatsList: []*request_data_scouting_response.StatsT{
Philipp Schraderacf96232022-03-01 22:03:30 -0800275 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700276 Team: 971, Match: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700277 MissedShotsAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
278 MissedShotsTele: 1, UpperGoalTele: 2, LowerGoalTele: 3,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700279 DefenseRating: 7,
280 DefenseReceivedRating: 3,
281 CollectedBy: "john",
282 AutoBall1: true, AutoBall2: false, AutoBall3: false,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700283 AutoBall4: false, AutoBall5: true,
284 StartingQuadrant: 1,
285 ClimbLevel: request_data_scouting_response.ClimbLevelFailedWithPlentyOfTime,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700286 Comment: "a lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800287 },
288 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700289 Team: 972, Match: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700290 MissedShotsAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
291 MissedShotsTele: 2, UpperGoalTele: 3, LowerGoalTele: 4,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700292 DefenseRating: 8,
293 DefenseReceivedRating: 1,
294 CollectedBy: "andrea",
295 AutoBall1: false, AutoBall2: false, AutoBall3: true,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700296 AutoBall4: false, AutoBall5: false,
297 StartingQuadrant: 2,
298 ClimbLevel: request_data_scouting_response.ClimbLevelMedium,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700299 Comment: "another lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800300 },
301 },
302 }
303 if len(expected.StatsList) != len(response.StatsList) {
304 t.Fatal("Expected ", expected, ", but got ", *response)
305 }
306 for i, match := range expected.StatsList {
307 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
308 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
309 }
310 }
311}
312
Alex Perry81f96ba2022-03-13 18:26:19 -0700313func TestSubmitNotes(t *testing.T) {
314 database := MockDatabase{}
315 scoutingServer := server.NewScoutingServer()
316 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
317 scoutingServer.Start(8080)
318 defer scoutingServer.Stop()
319
320 builder := flatbuffers.NewBuilder(1024)
321 builder.Finish((&submit_notes.SubmitNotesT{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800322 Team: 971,
323 Notes: "Notes",
324 GoodDriving: true,
325 BadDriving: false,
326 SketchyClimb: true,
327 SolidClimb: false,
328 GoodDefense: true,
329 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700330 }).Pack(builder))
331
332 _, err := debug.SubmitNotes("http://localhost:8080", builder.FinishedBytes())
333 if err != nil {
334 t.Fatal("Failed to submit notes: ", err)
335 }
336
337 expected := []db.NotesData{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800338 {
339 TeamNumber: 971,
340 Notes: "Notes",
341 GoodDriving: true,
342 BadDriving: false,
343 SketchyClimb: true,
344 SolidClimb: false,
345 GoodDefense: true,
346 BadDefense: false,
347 },
Alex Perry81f96ba2022-03-13 18:26:19 -0700348 }
349
350 if !reflect.DeepEqual(database.notes, expected) {
351 t.Fatal("Submitted notes did not match", expected, database.notes)
352 }
353}
354
355func TestRequestNotes(t *testing.T) {
356 database := MockDatabase{
357 notes: []db.NotesData{{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800358 TeamNumber: 971,
359 Notes: "Notes",
360 GoodDriving: true,
361 BadDriving: false,
362 SketchyClimb: true,
363 SolidClimb: false,
364 GoodDefense: true,
365 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700366 }},
367 }
368 scoutingServer := server.NewScoutingServer()
369 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
370 scoutingServer.Start(8080)
371 defer scoutingServer.Stop()
372
373 builder := flatbuffers.NewBuilder(1024)
374 builder.Finish((&request_notes_for_team.RequestNotesForTeamT{
375 Team: 971,
376 }).Pack(builder))
377 response, err := debug.RequestNotes("http://localhost:8080", builder.FinishedBytes())
378 if err != nil {
379 t.Fatal("Failed to submit notes: ", err)
380 }
381
382 if response.Notes[0].Data != "Notes" {
383 t.Fatal("requested notes did not match", response)
384 }
385}
386
Milo Lin1d59f0c2022-06-22 20:30:58 -0700387func TestRequestShiftSchedule(t *testing.T) {
388 db := MockDatabase{
389 shiftSchedule: []db.Shift{
390 {
391 MatchNumber: 1,
392 R1scouter: "Bob",
393 R2scouter: "James",
394 R3scouter: "Robert",
395 B1scouter: "Alice",
396 B2scouter: "Mary",
397 B3scouter: "Patricia",
398 },
399 {
400 MatchNumber: 2,
401 R1scouter: "Liam",
402 R2scouter: "Noah",
403 R3scouter: "Oliver",
404 B1scouter: "Emma",
405 B2scouter: "Charlotte",
406 B3scouter: "Amelia",
407 },
408 },
409 }
410 scoutingServer := server.NewScoutingServer()
411 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
412 scoutingServer.Start(8080)
413 defer scoutingServer.Stop()
414
415 builder := flatbuffers.NewBuilder(1024)
416 builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
417
418 response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
419 if err != nil {
420 t.Fatal("Failed to request shift schedule: ", err)
421 }
422
423 expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
424 ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
425 {
426 MatchNumber: 1,
427 R1scouter: "Bob",
428 R2scouter: "James",
429 R3scouter: "Robert",
430 B1scouter: "Alice",
431 B2scouter: "Mary",
432 B3scouter: "Patricia",
433 },
434 {
435 MatchNumber: 2,
436 R1scouter: "Liam",
437 R2scouter: "Noah",
438 R3scouter: "Oliver",
439 B1scouter: "Emma",
440 B2scouter: "Charlotte",
441 B3scouter: "Amelia",
442 },
443 },
444 }
445 if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
446 t.Fatal("Expected ", expected, ", but got ", *response)
447 }
448 for i, match := range expected.ShiftSchedule {
449 if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
450 t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
451 }
452 }
453}
454
455func TestSubmitShiftSchedule(t *testing.T) {
456 database := MockDatabase{}
457 scoutingServer := server.NewScoutingServer()
458 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
459 scoutingServer.Start(8080)
460 defer scoutingServer.Stop()
461
462 builder := flatbuffers.NewBuilder(1024)
463 builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
464 ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
465 {MatchNumber: 1,
466 R1scouter: "Bob",
467 R2scouter: "James",
468 R3scouter: "Robert",
469 B1scouter: "Alice",
470 B2scouter: "Mary",
471 B3scouter: "Patricia"},
472 },
473 }).Pack(builder))
474
475 _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
476 if err != nil {
477 t.Fatal("Failed to submit shift schedule: ", err)
478 }
479
480 expected := []db.Shift{
481 {MatchNumber: 1,
482 R1scouter: "Bob",
483 R2scouter: "James",
484 R3scouter: "Robert",
485 B1scouter: "Alice",
486 B2scouter: "Mary",
487 B3scouter: "Patricia"},
488 }
489 if !reflect.DeepEqual(expected, database.shiftSchedule) {
490 t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
491 }
492}
493
Philipp Schraderd3fac192022-03-02 20:35:46 -0800494// Validates that we can download the schedule from The Blue Alliance.
495func TestRefreshMatchList(t *testing.T) {
496 scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
497 return []scraping.Match{
498 {
499 CompLevel: "qual",
500 MatchNumber: 1,
Philipp Schrader45befdd2022-04-08 19:12:44 -0700501 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800502 Alliances: scraping.Alliances{
503 Red: scraping.Alliance{
504 TeamKeys: []string{
505 "100",
506 "200",
507 "300",
508 },
509 },
510 Blue: scraping.Alliance{
511 TeamKeys: []string{
512 "101",
513 "201",
514 "301",
515 },
516 },
517 },
518 WinningAlliance: "",
519 EventKey: "",
520 Time: 0,
521 PredictedTime: 0,
522 ActualTime: 0,
523 PostResultTime: 0,
524 ScoreBreakdowns: scraping.ScoreBreakdowns{},
525 },
526 }, nil
527 }
528
529 database := MockDatabase{}
530 scoutingServer := server.NewScoutingServer()
531 HandleRequests(&database, scrapeMockSchedule, scoutingServer)
532 scoutingServer.Start(8080)
533 defer scoutingServer.Stop()
534
535 builder := flatbuffers.NewBuilder(1024)
536 builder.Finish((&refresh_match_list.RefreshMatchListT{}).Pack(builder))
537
538 response, err := debug.RefreshMatchList("http://localhost:8080", builder.FinishedBytes())
539 if err != nil {
540 t.Fatal("Failed to request all matches: ", err)
541 }
542
543 // Validate the response.
544 expected := refresh_match_list_response.RefreshMatchListResponseT{}
545 if !reflect.DeepEqual(expected, *response) {
546 t.Fatal("Expected ", expected, ", but got ", *response)
547 }
548
549 // Make sure that the data made it into the database.
550 expectedMatches := []db.Match{
551 {
552 MatchNumber: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -0700553 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800554 CompLevel: "qual",
555 R1: 100,
556 R2: 200,
557 R3: 300,
558 B1: 101,
559 B2: 201,
560 B3: 301,
561 },
562 }
563 if !reflect.DeepEqual(expectedMatches, database.matches) {
564 t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
565 }
566}
567
Filip Kujawa210a03b2022-11-24 14:41:11 -0800568func TestSubmitDriverRanking(t *testing.T) {
569 database := MockDatabase{}
570 scoutingServer := server.NewScoutingServer()
571 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
572 scoutingServer.Start(8080)
573 defer scoutingServer.Stop()
574
575 builder := flatbuffers.NewBuilder(1024)
576 builder.Finish((&submit_driver_ranking.SubmitDriverRankingT{
577 MatchNumber: 36,
578 Rank1: 1234,
579 Rank2: 1235,
580 Rank3: 1236,
581 }).Pack(builder))
582
583 _, err := debug.SubmitDriverRanking("http://localhost:8080", builder.FinishedBytes())
584 if err != nil {
585 t.Fatal("Failed to submit driver ranking: ", err)
586 }
587
588 expected := []db.DriverRankingData{
589 {MatchNumber: 36, Rank1: 1234, Rank2: 1235, Rank3: 1236},
590 }
591
592 if !reflect.DeepEqual(database.driver_ranking, expected) {
593 t.Fatal("Submitted notes did not match", expected, database.notes)
594 }
595}
596
Filip Kujawaf882e022022-12-14 13:14:08 -0800597// Validates that we can request the driver rankings.
598func TestRequestDriverRankings(t *testing.T) {
599 db := MockDatabase{
600 driver_ranking: []db.DriverRankingData{
601 {
602 MatchNumber: 36,
603 Rank1: 1234,
604 Rank2: 1235,
605 Rank3: 1236,
606 },
607 {
608 MatchNumber: 36,
609 Rank1: 101,
610 Rank2: 202,
611 Rank3: 303,
612 },
613 },
614 }
615 scoutingServer := server.NewScoutingServer()
616 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
617 scoutingServer.Start(8080)
618 defer scoutingServer.Stop()
619
620 builder := flatbuffers.NewBuilder(1024)
621 builder.Finish((&request_all_driver_rankings.RequestAllDriverRankingsT{}).Pack(builder))
622
623 response, err := debug.RequestAllDriverRankings("http://localhost:8080", builder.FinishedBytes())
624 if err != nil {
625 t.Fatal("Failed to request all driver rankings: ", err)
626 }
627
628 expected := request_all_driver_rankings_response.RequestAllDriverRankingsResponseT{
629 DriverRankingList: []*request_all_driver_rankings_response.RankingT{
630 {
631 MatchNumber: 36,
632 Rank1: 1234,
633 Rank2: 1235,
634 Rank3: 1236,
635 },
636 {
637 MatchNumber: 36,
638 Rank1: 101,
639 Rank2: 202,
640 Rank3: 303,
641 },
642 },
643 }
644 if len(expected.DriverRankingList) != len(response.DriverRankingList) {
645 t.Fatal("Expected ", expected, ", but got ", *response)
646 }
647 for i, match := range expected.DriverRankingList {
648 if !reflect.DeepEqual(*match, *response.DriverRankingList[i]) {
649 t.Fatal("Expected for driver ranking", i, ":", *match, ", but got:", *response.DriverRankingList[i])
650 }
651 }
652}
653
654// Validates that we can request all notes.
655func TestRequestAllNotes(t *testing.T) {
656 db := MockDatabase{
657 notes: []db.NotesData{
658 {
659 TeamNumber: 971,
660 Notes: "Notes",
661 GoodDriving: true,
662 BadDriving: false,
663 SketchyClimb: true,
664 SolidClimb: false,
665 GoodDefense: true,
666 BadDefense: false,
667 },
668 {
669 TeamNumber: 972,
670 Notes: "More Notes",
671 GoodDriving: false,
672 BadDriving: false,
673 SketchyClimb: false,
674 SolidClimb: true,
675 GoodDefense: false,
676 BadDefense: true,
677 },
678 },
679 }
680 scoutingServer := server.NewScoutingServer()
681 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
682 scoutingServer.Start(8080)
683 defer scoutingServer.Stop()
684
685 builder := flatbuffers.NewBuilder(1024)
686 builder.Finish((&request_all_notes.RequestAllNotesT{}).Pack(builder))
687
688 response, err := debug.RequestAllNotes("http://localhost:8080", builder.FinishedBytes())
689 if err != nil {
690 t.Fatal("Failed to request all notes: ", err)
691 }
692
693 expected := request_all_notes_response.RequestAllNotesResponseT{
694 NoteList: []*request_all_notes_response.NoteT{
695 {
696 Team: 971,
697 Notes: "Notes",
698 GoodDriving: true,
699 BadDriving: false,
700 SketchyClimb: true,
701 SolidClimb: false,
702 GoodDefense: true,
703 BadDefense: false,
704 },
705 {
706 Team: 972,
707 Notes: "More Notes",
708 GoodDriving: false,
709 BadDriving: false,
710 SketchyClimb: false,
711 SolidClimb: true,
712 GoodDefense: false,
713 BadDefense: true,
714 },
715 },
716 }
717 if len(expected.NoteList) != len(response.NoteList) {
718 t.Fatal("Expected ", expected, ", but got ", *response)
719 }
720 for i, note := range expected.NoteList {
721 if !reflect.DeepEqual(*note, *response.NoteList[i]) {
722 t.Fatal("Expected for note", i, ":", *note, ", but got:", *response.NoteList[i])
723 }
724 }
725}
726
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800727// A mocked database we can use for testing. Add functionality to this as
728// needed for your tests.
729
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800730type MockDatabase struct {
Filip Kujawa210a03b2022-11-24 14:41:11 -0800731 matches []db.Match
732 stats []db.Stats
733 notes []db.NotesData
734 shiftSchedule []db.Shift
735 driver_ranking []db.DriverRankingData
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800736}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800737
Philipp Schraderd3fac192022-03-02 20:35:46 -0800738func (database *MockDatabase) AddToMatch(match db.Match) error {
739 database.matches = append(database.matches, match)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800740 return nil
741}
742
Philipp Schrader30005e42022-03-06 13:53:58 -0800743func (database *MockDatabase) AddToStats(stats db.Stats) error {
744 database.stats = append(database.stats, stats)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800745 return nil
746}
747
748func (database *MockDatabase) ReturnMatches() ([]db.Match, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800749 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800750}
751
752func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
Philipp Schraderacf96232022-03-01 22:03:30 -0800753 return database.stats, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800754}
755
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800756func (database *MockDatabase) QueryMatches(requestedTeam int32) ([]db.Match, error) {
757 var matches []db.Match
758 for _, match := range database.matches {
759 for _, team := range []int32{match.R1, match.R2, match.R3, match.B1, match.B2, match.B3} {
760 if team == requestedTeam {
761 matches = append(matches, match)
762 break
763 }
764 }
765 }
766 return matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800767}
768
769func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
770 return []db.Stats{}, nil
771}
Philipp Schraderd3fac192022-03-02 20:35:46 -0800772
Philipp Schradereecb8962022-06-01 21:02:42 -0700773func (database *MockDatabase) QueryNotes(requestedTeam int32) ([]string, error) {
Alex Perry81f96ba2022-03-13 18:26:19 -0700774 var results []string
775 for _, data := range database.notes {
776 if data.TeamNumber == requestedTeam {
Philipp Schradereecb8962022-06-01 21:02:42 -0700777 results = append(results, data.Notes)
Alex Perry81f96ba2022-03-13 18:26:19 -0700778 }
779 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700780 return results, nil
Alex Perry81f96ba2022-03-13 18:26:19 -0700781}
782
Filip Kujawaf947cb42022-11-21 10:00:30 -0800783func (database *MockDatabase) AddNotes(data db.NotesData) error {
784 database.notes = append(database.notes, data)
Alex Perry81f96ba2022-03-13 18:26:19 -0700785 return nil
786}
787
Filip Kujawaf882e022022-12-14 13:14:08 -0800788func (database *MockDatabase) ReturnAllNotes() ([]db.NotesData, error) {
789 return database.notes, nil
790}
791
Milo Lin1d59f0c2022-06-22 20:30:58 -0700792func (database *MockDatabase) AddToShift(data db.Shift) error {
793 database.shiftSchedule = append(database.shiftSchedule, data)
794 return nil
795}
796
797func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
798 return database.shiftSchedule, nil
799}
800
801func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
802 return []db.Shift{}, nil
803}
804
Filip Kujawa210a03b2022-11-24 14:41:11 -0800805func (database *MockDatabase) AddDriverRanking(data db.DriverRankingData) error {
806 database.driver_ranking = append(database.driver_ranking, data)
807 return nil
808}
809
Filip Kujawaf882e022022-12-14 13:14:08 -0800810func (database *MockDatabase) ReturnAllDriverRankings() ([]db.DriverRankingData, error) {
811 return database.driver_ranking, nil
812}
813
Philipp Schraderd3fac192022-03-02 20:35:46 -0800814// Returns an empty match list from the fake The Blue Alliance scraping.
815func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
816 return nil, nil
817}