github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/api/receiver/create_run_test.go (about) 1 //go:build small 2 // +build small 3 4 // Copyright 2018 The WPT Dashboard Project. All rights reserved. 5 // Use of this source code is governed by a BSD-style license that can be 6 // found in the LICENSE file. 7 8 package receiver 9 10 import ( 11 "encoding/json" 12 "io" 13 "net/http" 14 "net/http/httptest" 15 "strings" 16 "testing" 17 "time" 18 19 "github.com/golang/mock/gomock" 20 "github.com/stretchr/testify/assert" 21 "github.com/web-platform-tests/wpt.fyi/api/checks/mock_checks" 22 "github.com/web-platform-tests/wpt.fyi/api/receiver/mock_receiver" 23 "github.com/web-platform-tests/wpt.fyi/shared" 24 "github.com/web-platform-tests/wpt.fyi/shared/sharedtest" 25 ) 26 27 func TestHandleResultsCreate(t *testing.T) { 28 mockCtrl := gomock.NewController(t) 29 defer mockCtrl.Finish() 30 31 sha := "0123456789012345678901234567890123456789" 32 payload := map[string]interface{}{ 33 "id": 12345, 34 "browser_name": "firefox", 35 "browser_version": "59.0", 36 "os_name": "linux", 37 "os_version": "4.4", 38 "revision": sha[:10], 39 "full_revision_hash": sha, 40 "labels": []string{"foo", "bar"}, 41 "time_start": "2018-06-21T18:39:54.218000+00:00", 42 "time_end": "2018-06-21T20:03:49Z", 43 "_random_extra_key_": "some_value", 44 } 45 body, err := json.Marshal(payload) 46 assert.Nil(t, err) 47 req := httptest.NewRequest("POST", "/api/results/create", strings.NewReader(string(body))) 48 req.SetBasicAuth("_processor", "secret-token") 49 pAtR := shared.ProductAtRevision{ 50 Product: shared.Product{ 51 BrowserName: "firefox", 52 BrowserVersion: "59.0", 53 OSName: "linux", 54 OSVersion: "4.4", 55 }, 56 Revision: sha[:10], 57 FullRevisionHash: sha, 58 } 59 testRunIn := &shared.TestRun{ 60 ID: 12345, 61 TimeStart: time.Date(2018, time.June, 21, 18, 39, 54, 218000000, time.UTC), 62 TimeEnd: time.Date(2018, time.June, 21, 20, 3, 49, 0, time.UTC), 63 Labels: []string{"foo", "bar"}, 64 ProductAtRevision: pAtR, 65 } 66 testKey := &sharedtest.MockKey{TypeName: "TestRun", ID: 12345} 67 pendingRun := shared.PendingTestRun{ 68 ID: 12345, 69 Stage: shared.StageValid, 70 ProductAtRevision: pAtR, 71 } 72 73 mockAE := mock_receiver.NewMockAPI(mockCtrl) 74 mockAE.EXPECT().Context().AnyTimes().Return(sharedtest.NewTestContext()) 75 mockS := mock_checks.NewMockAPI(mockCtrl) 76 gomock.InOrder( 77 mockAE.EXPECT().GetUploader("_processor").Return(shared.Uploader{"_processor", "secret-token"}, nil), 78 mockAE.EXPECT().AddTestRun(sharedtest.SameProductSpec(testRunIn.String())).Return(testKey, nil), 79 mockS.EXPECT().ScheduleResultsProcessing(sha, sharedtest.SameProductSpec("firefox")).Return(nil), 80 mockAE.EXPECT().UpdatePendingTestRun(pendingRun).Return(nil), 81 ) 82 83 w := httptest.NewRecorder() 84 HandleResultsCreate(mockAE, mockS, w, req) 85 resp := w.Result() 86 assert.Equal(t, http.StatusCreated, resp.StatusCode) 87 88 var testRunOut shared.TestRun 89 body, _ = io.ReadAll(resp.Body) 90 err = json.Unmarshal(body, &testRunOut) 91 assert.Nil(t, err) 92 // Fields outside of ProductAtRevision are not included in the matcher, so check them now: 93 assert.Equal(t, testRunIn.ID, testRunOut.ID) 94 assert.Equal(t, testRunIn.Labels, testRunOut.Labels) 95 assert.Equal(t, testRunIn.TimeStart, testRunOut.TimeStart) 96 assert.Equal(t, testRunIn.TimeEnd, testRunOut.TimeEnd) 97 } 98 99 func TestHandleResultsCreate_NoTimestamps(t *testing.T) { 100 mockCtrl := gomock.NewController(t) 101 defer mockCtrl.Finish() 102 103 sha := "0123456789012345678901234567890123456789" 104 payload := map[string]interface{}{ 105 "browser_name": "firefox", 106 "browser_version": "59.0", 107 "os_name": "linux", 108 "revision": sha[:10], 109 "full_revision_hash": sha, 110 } 111 body, err := json.Marshal(payload) 112 assert.Nil(t, err) 113 req := httptest.NewRequest("POST", "/api/results/create", strings.NewReader(string(body))) 114 req.SetBasicAuth("_processor", "secret-token") 115 pAtR := shared.ProductAtRevision{ 116 Product: shared.Product{ 117 BrowserName: "firefox", 118 BrowserVersion: "59.0", 119 OSName: "linux", 120 }, 121 Revision: sha[:10], 122 FullRevisionHash: sha, 123 } 124 testRunIn := &shared.TestRun{ProductAtRevision: pAtR} 125 testKey := &sharedtest.MockKey{TypeName: "TestRun", ID: 123} 126 pendingRun := shared.PendingTestRun{ 127 ID: 123, 128 Stage: shared.StageValid, 129 ProductAtRevision: pAtR, 130 } 131 132 mockAE := mock_receiver.NewMockAPI(mockCtrl) 133 mockAE.EXPECT().Context().AnyTimes().Return(sharedtest.NewTestContext()) 134 mockS := mock_checks.NewMockAPI(mockCtrl) 135 gomock.InOrder( 136 mockAE.EXPECT().GetUploader("_processor").Return(shared.Uploader{"_processor", "secret-token"}, nil), 137 mockAE.EXPECT().AddTestRun(sharedtest.SameProductSpec(testRunIn.String())).Return(testKey, nil), 138 mockS.EXPECT().ScheduleResultsProcessing(sha, sharedtest.SameProductSpec("firefox")).Return(nil), 139 mockAE.EXPECT().UpdatePendingTestRun(pendingRun).Return(nil), 140 ) 141 142 w := httptest.NewRecorder() 143 HandleResultsCreate(mockAE, mockS, w, req) 144 resp := w.Result() 145 assert.Equal(t, http.StatusCreated, resp.StatusCode) 146 147 var testRun shared.TestRun 148 body, _ = io.ReadAll(resp.Body) 149 err = json.Unmarshal(body, &testRun) 150 assert.Nil(t, err) 151 assert.False(t, testRun.CreatedAt.IsZero()) 152 assert.False(t, testRun.TimeStart.IsZero()) 153 assert.Equal(t, testRun.TimeStart, testRun.TimeEnd) 154 } 155 156 func TestHandleResultsCreate_BadRevision(t *testing.T) { 157 mockCtrl := gomock.NewController(t) 158 defer mockCtrl.Finish() 159 mockS := mock_checks.NewMockAPI(mockCtrl) 160 mockAE := mock_receiver.NewMockAPI(mockCtrl) 161 mockAE.EXPECT().Context().AnyTimes().Return(sharedtest.NewTestContext()) 162 mockAE.EXPECT().GetUploader("_processor").AnyTimes().Return(shared.Uploader{"_processor", "secret-token"}, nil) 163 164 payload := map[string]interface{}{ 165 "browser_name": "firefox", 166 "browser_version": "59.0", 167 "os_name": "linux", 168 "revision": "0123456789", 169 } 170 body, err := json.Marshal(payload) 171 assert.Nil(t, err) 172 t.Run("Missing full_revision_hash", func(t *testing.T) { 173 req := httptest.NewRequest("POST", "/api/results/create", strings.NewReader(string(body))) 174 req.SetBasicAuth("_processor", "secret-token") 175 w := httptest.NewRecorder() 176 177 HandleResultsCreate(mockAE, mockS, w, req) 178 resp := w.Result() 179 assert.Equal(t, http.StatusBadRequest, resp.StatusCode) 180 }) 181 182 payload["full_revision_hash"] = "9876543210987654321098765432109876543210" 183 body, err = json.Marshal(payload) 184 assert.Nil(t, err) 185 t.Run("Incorrect full_revision_hash", func(t *testing.T) { 186 req := httptest.NewRequest("POST", "/api/results/create", strings.NewReader(string(body))) 187 req.SetBasicAuth("_processor", "secret-token") 188 w := httptest.NewRecorder() 189 190 HandleResultsCreate(mockAE, mockS, w, req) 191 resp := w.Result() 192 assert.Equal(t, http.StatusBadRequest, resp.StatusCode) 193 }) 194 } 195 196 func TestHandleResultsCreate_NoBasicAuth(t *testing.T) { 197 mockCtrl := gomock.NewController(t) 198 defer mockCtrl.Finish() 199 200 req := httptest.NewRequest("POST", "/api/results/create", nil) 201 resp := httptest.NewRecorder() 202 mockAE := mock_receiver.NewMockAPI(mockCtrl) 203 mockAE.EXPECT().Context().AnyTimes().Return(sharedtest.NewTestContext()) 204 mockS := mock_checks.NewMockAPI(mockCtrl) 205 206 HandleResultsCreate(mockAE, mockS, resp, req) 207 assert.Equal(t, http.StatusUnauthorized, resp.Code) 208 } 209 210 func TestHandleResultsCreate_WrongUser(t *testing.T) { 211 mockCtrl := gomock.NewController(t) 212 defer mockCtrl.Finish() 213 214 req := httptest.NewRequest("POST", "/api/results/create", nil) 215 req.SetBasicAuth("wrong-user", "secret-token") 216 resp := httptest.NewRecorder() 217 mockAE := mock_receiver.NewMockAPI(mockCtrl) 218 mockAE.EXPECT().Context().AnyTimes().Return(sharedtest.NewTestContext()) 219 mockAE.EXPECT().GetUploader("wrong-user").Return(shared.Uploader{"wrong-user", "secret-token"}, nil) 220 mockS := mock_checks.NewMockAPI(mockCtrl) 221 222 HandleResultsCreate(mockAE, mockS, resp, req) 223 assert.Equal(t, http.StatusUnauthorized, resp.Code) 224 } 225 226 func TestHandleResultsCreate_WrongPassword(t *testing.T) { 227 mockCtrl := gomock.NewController(t) 228 defer mockCtrl.Finish() 229 230 req := httptest.NewRequest("POST", "/api/results/create", nil) 231 req.SetBasicAuth("_processor", "wrong-password") 232 resp := httptest.NewRecorder() 233 mockAE := mock_receiver.NewMockAPI(mockCtrl) 234 mockAE.EXPECT().Context().AnyTimes().Return(sharedtest.NewTestContext()) 235 mockAE.EXPECT().GetUploader("_processor").Return(shared.Uploader{"_processor", "secret-token"}, nil) 236 mockS := mock_checks.NewMockAPI(mockCtrl) 237 238 HandleResultsCreate(mockAE, mockS, resp, req) 239 assert.Equal(t, http.StatusUnauthorized, resp.Code) 240 }