blob: 27a45e6b432844b8f285fbd69d6040ca434cf84c [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{
Emily Markovabf24c9e2023-02-08 20:31:11 -0800128 matches: []db.TeamMatch{
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800129 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800130 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800131 Alliance: "R", AlliancePosition: 1, TeamNumber: 5,
132 },
133 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800134 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800135 Alliance: "R", AlliancePosition: 2, TeamNumber: 42,
136 },
137 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800138 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800139 Alliance: "R", AlliancePosition: 3, TeamNumber: 600,
140 },
141 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800142 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800143 Alliance: "B", AlliancePosition: 1, TeamNumber: 971,
144 },
145 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800146 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800147 Alliance: "B", AlliancePosition: 2, TeamNumber: 400,
148 },
149 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800150 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800151 Alliance: "B", AlliancePosition: 3, TeamNumber: 200,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800152 },
153 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800154 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800155 Alliance: "R", AlliancePosition: 1, TeamNumber: 6,
156 },
157 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800158 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800159 Alliance: "R", AlliancePosition: 2, TeamNumber: 43,
160 },
161 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800162 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800163 Alliance: "R", AlliancePosition: 3, TeamNumber: 601,
164 },
165 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800166 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800167 Alliance: "B", AlliancePosition: 1, TeamNumber: 972,
168 },
169 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800170 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800171 Alliance: "B", AlliancePosition: 2, TeamNumber: 401,
172 },
173 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800174 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800175 Alliance: "B", AlliancePosition: 3, TeamNumber: 201,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800176 },
177 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800178 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800179 Alliance: "R", AlliancePosition: 1, TeamNumber: 7,
180 },
181 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800182 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800183 Alliance: "R", AlliancePosition: 2, TeamNumber: 44,
184 },
185 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800186 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800187 Alliance: "R", AlliancePosition: 3, TeamNumber: 602,
188 },
189 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800190 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800191 Alliance: "B", AlliancePosition: 1, TeamNumber: 973,
192 },
193 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800194 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800195 Alliance: "B", AlliancePosition: 2, TeamNumber: 402,
196 },
197 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800198 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800199 Alliance: "B", AlliancePosition: 3, TeamNumber: 202,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800200 },
201 },
202 }
203 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800204 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800205 scoutingServer.Start(8080)
206 defer scoutingServer.Stop()
207
208 builder := flatbuffers.NewBuilder(1024)
209 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
210
211 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
212 if err != nil {
213 t.Fatal("Failed to request all matches: ", err)
214 }
215
216 expected := request_all_matches_response.RequestAllMatchesResponseT{
217 MatchList: []*request_all_matches_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700218 // MatchNumber, SetNumber, CompLevel
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800219 // R1, R2, R3, B1, B2, B3
220 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800221 1, 1, "qm",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800222 5, 42, 600, 971, 400, 200,
223 },
224 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800225 2, 1, "qm",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800226 6, 43, 601, 972, 401, 201,
227 },
228 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800229 3, 1, "qm",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800230 7, 44, 602, 973, 402, 202,
231 },
232 },
233 }
234 if len(expected.MatchList) != len(response.MatchList) {
235 t.Fatal("Expected ", expected, ", but got ", *response)
236 }
237 for i, match := range expected.MatchList {
238 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
239 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
240 }
241 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800242
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800243}
244
Philipp Schraderacf96232022-03-01 22:03:30 -0800245// Validates that we can request the stats.
246func TestRequestDataScouting(t *testing.T) {
247 db := MockDatabase{
248 stats: []db.Stats{
249 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700250 TeamNumber: 971, MatchNumber: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700251 StartingQuadrant: 1,
252 AutoBallPickedUp: [5]bool{true, false, false, false, true},
253 ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
Philipp Schraderacf96232022-03-01 22:03:30 -0800254 ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700255 PlayedDefense: 7, DefenseReceivedScore: 3, Climbing: 2,
256 Comment: "a lovely comment", CollectedBy: "john",
Philipp Schraderacf96232022-03-01 22:03:30 -0800257 },
258 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700259 TeamNumber: 972, MatchNumber: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700260 StartingQuadrant: 2,
261 AutoBallPickedUp: [5]bool{false, false, true, false, false},
262 ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
Philipp Schraderacf96232022-03-01 22:03:30 -0800263 ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700264 PlayedDefense: 8, DefenseReceivedScore: 1, Climbing: 4,
265 Comment: "another lovely comment", CollectedBy: "andrea",
Philipp Schraderacf96232022-03-01 22:03:30 -0800266 },
267 },
268 }
269 scoutingServer := server.NewScoutingServer()
Philipp Schraderd3fac192022-03-02 20:35:46 -0800270 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
Philipp Schraderacf96232022-03-01 22:03:30 -0800271 scoutingServer.Start(8080)
272 defer scoutingServer.Stop()
273
274 builder := flatbuffers.NewBuilder(1024)
275 builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
276
277 response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
278 if err != nil {
279 t.Fatal("Failed to request all matches: ", err)
280 }
281
282 expected := request_data_scouting_response.RequestDataScoutingResponseT{
283 StatsList: []*request_data_scouting_response.StatsT{
Philipp Schraderacf96232022-03-01 22:03:30 -0800284 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700285 Team: 971, Match: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700286 MissedShotsAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
287 MissedShotsTele: 1, UpperGoalTele: 2, LowerGoalTele: 3,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700288 DefenseRating: 7,
289 DefenseReceivedRating: 3,
290 CollectedBy: "john",
291 AutoBall1: true, AutoBall2: false, AutoBall3: false,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700292 AutoBall4: false, AutoBall5: true,
293 StartingQuadrant: 1,
294 ClimbLevel: request_data_scouting_response.ClimbLevelFailedWithPlentyOfTime,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700295 Comment: "a lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800296 },
297 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700298 Team: 972, Match: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700299 MissedShotsAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
300 MissedShotsTele: 2, UpperGoalTele: 3, LowerGoalTele: 4,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700301 DefenseRating: 8,
302 DefenseReceivedRating: 1,
303 CollectedBy: "andrea",
304 AutoBall1: false, AutoBall2: false, AutoBall3: true,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700305 AutoBall4: false, AutoBall5: false,
306 StartingQuadrant: 2,
307 ClimbLevel: request_data_scouting_response.ClimbLevelMedium,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700308 Comment: "another lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800309 },
310 },
311 }
312 if len(expected.StatsList) != len(response.StatsList) {
313 t.Fatal("Expected ", expected, ", but got ", *response)
314 }
315 for i, match := range expected.StatsList {
316 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
317 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
318 }
319 }
320}
321
Alex Perry81f96ba2022-03-13 18:26:19 -0700322func TestSubmitNotes(t *testing.T) {
323 database := MockDatabase{}
324 scoutingServer := server.NewScoutingServer()
325 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
326 scoutingServer.Start(8080)
327 defer scoutingServer.Stop()
328
329 builder := flatbuffers.NewBuilder(1024)
330 builder.Finish((&submit_notes.SubmitNotesT{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800331 Team: 971,
332 Notes: "Notes",
333 GoodDriving: true,
334 BadDriving: false,
335 SketchyClimb: true,
336 SolidClimb: false,
337 GoodDefense: true,
338 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700339 }).Pack(builder))
340
341 _, err := debug.SubmitNotes("http://localhost:8080", builder.FinishedBytes())
342 if err != nil {
343 t.Fatal("Failed to submit notes: ", err)
344 }
345
346 expected := []db.NotesData{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800347 {
348 TeamNumber: 971,
349 Notes: "Notes",
350 GoodDriving: true,
351 BadDriving: false,
352 SketchyClimb: true,
353 SolidClimb: false,
354 GoodDefense: true,
355 BadDefense: false,
356 },
Alex Perry81f96ba2022-03-13 18:26:19 -0700357 }
358
359 if !reflect.DeepEqual(database.notes, expected) {
360 t.Fatal("Submitted notes did not match", expected, database.notes)
361 }
362}
363
364func TestRequestNotes(t *testing.T) {
365 database := MockDatabase{
366 notes: []db.NotesData{{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800367 TeamNumber: 971,
368 Notes: "Notes",
369 GoodDriving: true,
370 BadDriving: false,
371 SketchyClimb: true,
372 SolidClimb: false,
373 GoodDefense: true,
374 BadDefense: false,
Alex Perry81f96ba2022-03-13 18:26:19 -0700375 }},
376 }
377 scoutingServer := server.NewScoutingServer()
378 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
379 scoutingServer.Start(8080)
380 defer scoutingServer.Stop()
381
382 builder := flatbuffers.NewBuilder(1024)
383 builder.Finish((&request_notes_for_team.RequestNotesForTeamT{
384 Team: 971,
385 }).Pack(builder))
386 response, err := debug.RequestNotes("http://localhost:8080", builder.FinishedBytes())
387 if err != nil {
388 t.Fatal("Failed to submit notes: ", err)
389 }
390
391 if response.Notes[0].Data != "Notes" {
392 t.Fatal("requested notes did not match", response)
393 }
394}
395
Milo Lin1d59f0c2022-06-22 20:30:58 -0700396func TestRequestShiftSchedule(t *testing.T) {
397 db := MockDatabase{
398 shiftSchedule: []db.Shift{
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 scoutingServer := server.NewScoutingServer()
420 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
421 scoutingServer.Start(8080)
422 defer scoutingServer.Stop()
423
424 builder := flatbuffers.NewBuilder(1024)
425 builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
426
427 response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
428 if err != nil {
429 t.Fatal("Failed to request shift schedule: ", err)
430 }
431
432 expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
433 ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
434 {
435 MatchNumber: 1,
436 R1scouter: "Bob",
437 R2scouter: "James",
438 R3scouter: "Robert",
439 B1scouter: "Alice",
440 B2scouter: "Mary",
441 B3scouter: "Patricia",
442 },
443 {
444 MatchNumber: 2,
445 R1scouter: "Liam",
446 R2scouter: "Noah",
447 R3scouter: "Oliver",
448 B1scouter: "Emma",
449 B2scouter: "Charlotte",
450 B3scouter: "Amelia",
451 },
452 },
453 }
454 if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
455 t.Fatal("Expected ", expected, ", but got ", *response)
456 }
457 for i, match := range expected.ShiftSchedule {
458 if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
459 t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
460 }
461 }
462}
463
464func TestSubmitShiftSchedule(t *testing.T) {
465 database := MockDatabase{}
466 scoutingServer := server.NewScoutingServer()
467 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
468 scoutingServer.Start(8080)
469 defer scoutingServer.Stop()
470
471 builder := flatbuffers.NewBuilder(1024)
472 builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
473 ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
474 {MatchNumber: 1,
475 R1scouter: "Bob",
476 R2scouter: "James",
477 R3scouter: "Robert",
478 B1scouter: "Alice",
479 B2scouter: "Mary",
480 B3scouter: "Patricia"},
481 },
482 }).Pack(builder))
483
484 _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
485 if err != nil {
486 t.Fatal("Failed to submit shift schedule: ", err)
487 }
488
489 expected := []db.Shift{
490 {MatchNumber: 1,
491 R1scouter: "Bob",
492 R2scouter: "James",
493 R3scouter: "Robert",
494 B1scouter: "Alice",
495 B2scouter: "Mary",
496 B3scouter: "Patricia"},
497 }
498 if !reflect.DeepEqual(expected, database.shiftSchedule) {
499 t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
500 }
501}
502
Philipp Schraderd3fac192022-03-02 20:35:46 -0800503// Validates that we can download the schedule from The Blue Alliance.
504func TestRefreshMatchList(t *testing.T) {
505 scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
506 return []scraping.Match{
507 {
508 CompLevel: "qual",
509 MatchNumber: 1,
Philipp Schrader45befdd2022-04-08 19:12:44 -0700510 SetNumber: 2,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800511 Alliances: scraping.Alliances{
512 Red: scraping.Alliance{
513 TeamKeys: []string{
514 "100",
515 "200",
516 "300",
517 },
518 },
519 Blue: scraping.Alliance{
520 TeamKeys: []string{
521 "101",
522 "201",
523 "301",
524 },
525 },
526 },
527 WinningAlliance: "",
528 EventKey: "",
529 Time: 0,
530 PredictedTime: 0,
531 ActualTime: 0,
532 PostResultTime: 0,
533 ScoreBreakdowns: scraping.ScoreBreakdowns{},
534 },
535 }, nil
536 }
537
538 database := MockDatabase{}
539 scoutingServer := server.NewScoutingServer()
540 HandleRequests(&database, scrapeMockSchedule, scoutingServer)
541 scoutingServer.Start(8080)
542 defer scoutingServer.Stop()
543
544 builder := flatbuffers.NewBuilder(1024)
545 builder.Finish((&refresh_match_list.RefreshMatchListT{}).Pack(builder))
546
547 response, err := debug.RefreshMatchList("http://localhost:8080", builder.FinishedBytes())
548 if err != nil {
549 t.Fatal("Failed to request all matches: ", err)
550 }
551
552 // Validate the response.
553 expected := refresh_match_list_response.RefreshMatchListResponseT{}
554 if !reflect.DeepEqual(expected, *response) {
555 t.Fatal("Expected ", expected, ", but got ", *response)
556 }
557
558 // Make sure that the data made it into the database.
Emily Markovabf24c9e2023-02-08 20:31:11 -0800559 expectedMatches := []db.TeamMatch{
Philipp Schraderd3fac192022-03-02 20:35:46 -0800560 {
Emily Markovabf24c9e2023-02-08 20:31:11 -0800561 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
562 Alliance: "R", AlliancePosition: 1, TeamNumber: 100,
563 },
564 {
565 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
566 Alliance: "R", AlliancePosition: 2, TeamNumber: 200,
567 },
568 {
569 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
570 Alliance: "R", AlliancePosition: 3, TeamNumber: 300,
571 },
572 {
573 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
574 Alliance: "B", AlliancePosition: 1, TeamNumber: 101,
575 },
576 {
577 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
578 Alliance: "B", AlliancePosition: 2, TeamNumber: 201,
579 },
580 {
581 MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
582 Alliance: "B", AlliancePosition: 3, TeamNumber: 301,
Philipp Schraderd3fac192022-03-02 20:35:46 -0800583 },
584 }
Emily Markovabf24c9e2023-02-08 20:31:11 -0800585
Philipp Schraderd3fac192022-03-02 20:35:46 -0800586 if !reflect.DeepEqual(expectedMatches, database.matches) {
587 t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
588 }
589}
590
Filip Kujawa210a03b2022-11-24 14:41:11 -0800591func TestSubmitDriverRanking(t *testing.T) {
592 database := MockDatabase{}
593 scoutingServer := server.NewScoutingServer()
594 HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
595 scoutingServer.Start(8080)
596 defer scoutingServer.Stop()
597
598 builder := flatbuffers.NewBuilder(1024)
599 builder.Finish((&submit_driver_ranking.SubmitDriverRankingT{
600 MatchNumber: 36,
601 Rank1: 1234,
602 Rank2: 1235,
603 Rank3: 1236,
604 }).Pack(builder))
605
606 _, err := debug.SubmitDriverRanking("http://localhost:8080", builder.FinishedBytes())
607 if err != nil {
608 t.Fatal("Failed to submit driver ranking: ", err)
609 }
610
611 expected := []db.DriverRankingData{
612 {MatchNumber: 36, Rank1: 1234, Rank2: 1235, Rank3: 1236},
613 }
614
615 if !reflect.DeepEqual(database.driver_ranking, expected) {
616 t.Fatal("Submitted notes did not match", expected, database.notes)
617 }
618}
619
Filip Kujawaf882e022022-12-14 13:14:08 -0800620// Validates that we can request the driver rankings.
621func TestRequestDriverRankings(t *testing.T) {
622 db := MockDatabase{
623 driver_ranking: []db.DriverRankingData{
624 {
625 MatchNumber: 36,
626 Rank1: 1234,
627 Rank2: 1235,
628 Rank3: 1236,
629 },
630 {
631 MatchNumber: 36,
632 Rank1: 101,
633 Rank2: 202,
634 Rank3: 303,
635 },
636 },
637 }
638 scoutingServer := server.NewScoutingServer()
639 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
640 scoutingServer.Start(8080)
641 defer scoutingServer.Stop()
642
643 builder := flatbuffers.NewBuilder(1024)
644 builder.Finish((&request_all_driver_rankings.RequestAllDriverRankingsT{}).Pack(builder))
645
646 response, err := debug.RequestAllDriverRankings("http://localhost:8080", builder.FinishedBytes())
647 if err != nil {
648 t.Fatal("Failed to request all driver rankings: ", err)
649 }
650
651 expected := request_all_driver_rankings_response.RequestAllDriverRankingsResponseT{
652 DriverRankingList: []*request_all_driver_rankings_response.RankingT{
653 {
654 MatchNumber: 36,
655 Rank1: 1234,
656 Rank2: 1235,
657 Rank3: 1236,
658 },
659 {
660 MatchNumber: 36,
661 Rank1: 101,
662 Rank2: 202,
663 Rank3: 303,
664 },
665 },
666 }
667 if len(expected.DriverRankingList) != len(response.DriverRankingList) {
668 t.Fatal("Expected ", expected, ", but got ", *response)
669 }
670 for i, match := range expected.DriverRankingList {
671 if !reflect.DeepEqual(*match, *response.DriverRankingList[i]) {
672 t.Fatal("Expected for driver ranking", i, ":", *match, ", but got:", *response.DriverRankingList[i])
673 }
674 }
675}
676
677// Validates that we can request all notes.
678func TestRequestAllNotes(t *testing.T) {
679 db := MockDatabase{
680 notes: []db.NotesData{
681 {
682 TeamNumber: 971,
683 Notes: "Notes",
684 GoodDriving: true,
685 BadDriving: false,
686 SketchyClimb: true,
687 SolidClimb: false,
688 GoodDefense: true,
689 BadDefense: false,
690 },
691 {
692 TeamNumber: 972,
693 Notes: "More Notes",
694 GoodDriving: false,
695 BadDriving: false,
696 SketchyClimb: false,
697 SolidClimb: true,
698 GoodDefense: false,
699 BadDefense: true,
700 },
701 },
702 }
703 scoutingServer := server.NewScoutingServer()
704 HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
705 scoutingServer.Start(8080)
706 defer scoutingServer.Stop()
707
708 builder := flatbuffers.NewBuilder(1024)
709 builder.Finish((&request_all_notes.RequestAllNotesT{}).Pack(builder))
710
711 response, err := debug.RequestAllNotes("http://localhost:8080", builder.FinishedBytes())
712 if err != nil {
713 t.Fatal("Failed to request all notes: ", err)
714 }
715
716 expected := request_all_notes_response.RequestAllNotesResponseT{
717 NoteList: []*request_all_notes_response.NoteT{
718 {
719 Team: 971,
720 Notes: "Notes",
721 GoodDriving: true,
722 BadDriving: false,
723 SketchyClimb: true,
724 SolidClimb: false,
725 GoodDefense: true,
726 BadDefense: false,
727 },
728 {
729 Team: 972,
730 Notes: "More Notes",
731 GoodDriving: false,
732 BadDriving: false,
733 SketchyClimb: false,
734 SolidClimb: true,
735 GoodDefense: false,
736 BadDefense: true,
737 },
738 },
739 }
740 if len(expected.NoteList) != len(response.NoteList) {
741 t.Fatal("Expected ", expected, ", but got ", *response)
742 }
743 for i, note := range expected.NoteList {
744 if !reflect.DeepEqual(*note, *response.NoteList[i]) {
745 t.Fatal("Expected for note", i, ":", *note, ", but got:", *response.NoteList[i])
746 }
747 }
748}
749
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800750// A mocked database we can use for testing. Add functionality to this as
751// needed for your tests.
752
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800753type MockDatabase struct {
Emily Markovabf24c9e2023-02-08 20:31:11 -0800754 matches []db.TeamMatch
Filip Kujawa210a03b2022-11-24 14:41:11 -0800755 stats []db.Stats
756 notes []db.NotesData
757 shiftSchedule []db.Shift
758 driver_ranking []db.DriverRankingData
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800759}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800760
Emily Markovabf24c9e2023-02-08 20:31:11 -0800761func (database *MockDatabase) AddToMatch(match db.TeamMatch) error {
Philipp Schraderd3fac192022-03-02 20:35:46 -0800762 database.matches = append(database.matches, match)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800763 return nil
764}
765
Philipp Schrader30005e42022-03-06 13:53:58 -0800766func (database *MockDatabase) AddToStats(stats db.Stats) error {
767 database.stats = append(database.stats, stats)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800768 return nil
769}
770
Emily Markovabf24c9e2023-02-08 20:31:11 -0800771func (database *MockDatabase) ReturnMatches() ([]db.TeamMatch, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800772 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800773}
774
775func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
Philipp Schraderacf96232022-03-01 22:03:30 -0800776 return database.stats, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800777}
778
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800779func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
780 return []db.Stats{}, nil
781}
Philipp Schraderd3fac192022-03-02 20:35:46 -0800782
Philipp Schradereecb8962022-06-01 21:02:42 -0700783func (database *MockDatabase) QueryNotes(requestedTeam int32) ([]string, error) {
Alex Perry81f96ba2022-03-13 18:26:19 -0700784 var results []string
785 for _, data := range database.notes {
786 if data.TeamNumber == requestedTeam {
Philipp Schradereecb8962022-06-01 21:02:42 -0700787 results = append(results, data.Notes)
Alex Perry81f96ba2022-03-13 18:26:19 -0700788 }
789 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700790 return results, nil
Alex Perry81f96ba2022-03-13 18:26:19 -0700791}
792
Filip Kujawaf947cb42022-11-21 10:00:30 -0800793func (database *MockDatabase) AddNotes(data db.NotesData) error {
794 database.notes = append(database.notes, data)
Alex Perry81f96ba2022-03-13 18:26:19 -0700795 return nil
796}
797
Filip Kujawaf882e022022-12-14 13:14:08 -0800798func (database *MockDatabase) ReturnAllNotes() ([]db.NotesData, error) {
799 return database.notes, nil
800}
801
Milo Lin1d59f0c2022-06-22 20:30:58 -0700802func (database *MockDatabase) AddToShift(data db.Shift) error {
803 database.shiftSchedule = append(database.shiftSchedule, data)
804 return nil
805}
806
807func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
808 return database.shiftSchedule, nil
809}
810
811func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
812 return []db.Shift{}, nil
813}
814
Filip Kujawa210a03b2022-11-24 14:41:11 -0800815func (database *MockDatabase) AddDriverRanking(data db.DriverRankingData) error {
816 database.driver_ranking = append(database.driver_ranking, data)
817 return nil
818}
819
Filip Kujawaf882e022022-12-14 13:14:08 -0800820func (database *MockDatabase) ReturnAllDriverRankings() ([]db.DriverRankingData, error) {
821 return database.driver_ranking, nil
822}
823
Philipp Schraderd3fac192022-03-02 20:35:46 -0800824// Returns an empty match list from the fake The Blue Alliance scraping.
825func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
826 return nil, nil
827}