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  }