blob: 26256be03604dc14406dd33d21824af7e67bd43d [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 Schradercbf5c6a2022-02-27 23:25:19 -080011 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080012 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080013 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
14 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080015 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
16 _ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
17 "github.com/frc971/971-Robot-Code/scouting/webserver/server"
18 flatbuffers "github.com/google/flatbuffers/go"
19)
20
21// Validates that an unhandled address results in a 404.
22func Test404(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080023 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080024 scoutingServer := server.NewScoutingServer()
Philipp Schrader8747f1b2022-02-23 23:56:22 -080025 HandleRequests(&db, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080026 scoutingServer.Start(8080)
27 defer scoutingServer.Stop()
28
29 resp, err := http.Get("http://localhost:8080/requests/foo")
30 if err != nil {
31 t.Fatalf("Failed to get data: %v", err)
32 }
33 if resp.StatusCode != http.StatusNotFound {
34 t.Fatalf("Expected error code 404, but got %d instead", resp.Status)
35 }
36}
37
38// Validates that we can submit new data scouting data.
39func TestSubmitDataScoutingError(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 Schrader8747f1b2022-02-23 23:56:22 -080042 HandleRequests(&db, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080043 scoutingServer.Start(8080)
44 defer scoutingServer.Stop()
45
46 resp, err := http.Post("http://localhost:8080/requests/submit/data_scouting", "application/octet-stream", bytes.NewReader([]byte("")))
47 if err != nil {
48 t.Fatalf("Failed to send request: %v", err)
49 }
50 if resp.StatusCode != http.StatusBadRequest {
51 t.Fatal("Unexpected status code. Got", resp.Status)
52 }
53
54 responseBytes, err := io.ReadAll(resp.Body)
55 if err != nil {
56 t.Fatal("Failed to read response bytes:", err)
57 }
58 errorResponse := error_response.GetRootAsErrorResponse(responseBytes, 0)
59
60 errorMessage := string(errorResponse.ErrorMessage())
61 if errorMessage != "Failed to parse SubmitDataScouting: runtime error: index out of range [3] with length 0" {
62 t.Fatal("Got mismatched error message:", errorMessage)
63 }
64}
65
66// Validates that we can submit new data scouting data.
67func TestSubmitDataScouting(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080068 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080069 scoutingServer := server.NewScoutingServer()
Philipp Schrader8747f1b2022-02-23 23:56:22 -080070 HandleRequests(&db, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080071 scoutingServer.Start(8080)
72 defer scoutingServer.Stop()
73
74 builder := flatbuffers.NewBuilder(1024)
75 builder.Finish((&submit_data_scouting.SubmitDataScoutingT{
Sabina Leavere66c2fc2022-02-24 16:56:15 -080076 Team: 971,
77 Match: 1,
78 MissedShotsAuto: 9971,
79 UpperGoalAuto: 9971,
80 LowerGoalAuto: 9971,
81 MissedShotsTele: 9971,
82 UpperGoalTele: 9971,
83 LowerGoalTele: 9971,
84 DefenseRating: 9971,
85 Climbing: 9971,
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080086 }).Pack(builder))
87
88 resp, err := http.Post("http://localhost:8080/requests/submit/data_scouting", "application/octet-stream", bytes.NewReader(builder.FinishedBytes()))
89 if err != nil {
90 t.Fatalf("Failed to send request: %v", err)
91 }
92 if resp.StatusCode != http.StatusNotImplemented {
93 t.Fatal("Unexpected status code. Got", resp.Status)
94 }
95 // TODO(phil): We have nothing to validate yet. Fix that.
Philipp Schraderd9096a32022-02-24 17:53:09 -080096 // TODO(phil): Can we use scouting/webserver/requests/debug here?
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080097}
Philipp Schrader8747f1b2022-02-23 23:56:22 -080098
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080099// Validates that we can request the full match list.
100func TestRequestAllMatches(t *testing.T) {
101 db := MockDatabase{
102 matches: []db.Match{
103 {
104 MatchNumber: 1, Round: 1, CompLevel: "qual",
105 R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
106 },
107 {
108 MatchNumber: 2, Round: 1, CompLevel: "qual",
109 R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
110 },
111 {
112 MatchNumber: 3, Round: 1, CompLevel: "qual",
113 R1: 7, R2: 44, R3: 602, B1: 973, B2: 402, B3: 202,
114 },
115 },
116 }
117 scoutingServer := server.NewScoutingServer()
118 HandleRequests(&db, scoutingServer)
119 scoutingServer.Start(8080)
120 defer scoutingServer.Stop()
121
122 builder := flatbuffers.NewBuilder(1024)
123 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
124
125 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
126 if err != nil {
127 t.Fatal("Failed to request all matches: ", err)
128 }
129
130 expected := request_all_matches_response.RequestAllMatchesResponseT{
131 MatchList: []*request_all_matches_response.MatchT{
132 // MatchNumber, Round, CompLevel
133 // R1, R2, R3, B1, B2, B3
134 {
135 1, 1, "qual",
136 5, 42, 600, 971, 400, 200,
137 },
138 {
139 2, 1, "qual",
140 6, 43, 601, 972, 401, 201,
141 },
142 {
143 3, 1, "qual",
144 7, 44, 602, 973, 402, 202,
145 },
146 },
147 }
148 if len(expected.MatchList) != len(response.MatchList) {
149 t.Fatal("Expected ", expected, ", but got ", *response)
150 }
151 for i, match := range expected.MatchList {
152 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
153 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
154 }
155 }
156}
157
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800158// A mocked database we can use for testing. Add functionality to this as
159// needed for your tests.
160
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800161type MockDatabase struct {
162 matches []db.Match
163}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800164
165func (database *MockDatabase) AddToMatch(db.Match) error {
166 return nil
167}
168
169func (database *MockDatabase) AddToStats(db.Stats) error {
170 return nil
171}
172
173func (database *MockDatabase) ReturnMatches() ([]db.Match, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800174 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800175}
176
177func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
178 return []db.Stats{}, nil
179}
180
181func (database *MockDatabase) QueryMatches(int) ([]db.Match, error) {
182 return []db.Match{}, nil
183}
184
185func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
186 return []db.Stats{}, nil
187}