golang.org/x/build@v0.0.0-20240506185731-218518f32b70/devapp/owners/owners_test.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package owners 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "io" 11 "log" 12 "net/http" 13 "net/http/httptest" 14 "os" 15 "testing" 16 17 "github.com/google/go-cmp/cmp" 18 ) 19 20 func TestMatch(t *testing.T) { 21 testCases := []struct { 22 path string 23 entry *Entry 24 }{ 25 { 26 "net", 27 &Entry{ 28 Primary: []Owner{neild, iant}, 29 }, 30 }, 31 { 32 "crypto/chacha20poly1305/chacha20poly1305.go", 33 &Entry{ 34 Primary: []Owner{filippo, roland, securityTeam}, 35 }, 36 }, 37 { 38 "go/src/archive/zip/a.go", 39 &Entry{ 40 Primary: []Owner{joetsai}, 41 Secondary: []Owner{bradfitz}, 42 }, 43 }, 44 { 45 "go/src/cmd/compile", 46 &Entry{ 47 Primary: []Owner{compilerTeam}, 48 Secondary: []Owner{khr, gri, mdempsky, martisch}, 49 }, 50 }, 51 { 52 "go/path/with/no/owners", nil, 53 }, 54 { 55 "nonexistentrepo/foo/bar", nil, 56 }, 57 } 58 for _, tc := range testCases { 59 matches := match(tc.path) 60 if diff := cmp.Diff(matches, tc.entry); diff != "" { 61 t.Errorf("%s: owners differ (-got +want)\n%s", tc.path, diff) 62 } 63 } 64 } 65 66 func TestHandler(t *testing.T) { 67 testCases := []struct { 68 method string 69 code int 70 paths []string 71 entries map[string]*Entry 72 }{ 73 {"PUT", http.StatusMethodNotAllowed, nil, nil}, 74 {"OPTIONS", http.StatusOK, nil, nil}, 75 { 76 "POST", http.StatusOK, 77 []string{"nonexistent/path"}, 78 map[string]*Entry{"nonexistent/path": nil}, 79 }, 80 { 81 "POST", http.StatusOK, 82 []string{"go/src/archive/zip/a.go"}, 83 map[string]*Entry{"go/src/archive/zip/a.go": {Primary: []Owner{joetsai}, Secondary: []Owner{bradfitz}}}, 84 }, 85 { 86 "POST", http.StatusOK, 87 []string{ 88 "go/src/archive/zip/a.go", 89 "go/src/archive/zip/b.go", 90 }, 91 map[string]*Entry{ 92 "go/src/archive/zip/a.go": {Primary: []Owner{joetsai}, Secondary: []Owner{bradfitz}}, 93 "go/src/archive/zip/b.go": {Primary: []Owner{joetsai}, Secondary: []Owner{bradfitz}}, 94 }, 95 }, 96 { 97 "POST", http.StatusOK, 98 []string{ 99 "go/src/archive/zip/a.go", 100 "crypto/chacha20poly1305/chacha20poly1305.go", 101 }, 102 map[string]*Entry{ 103 "go/src/archive/zip/a.go": {Primary: []Owner{joetsai}, Secondary: []Owner{bradfitz}}, 104 "crypto/chacha20poly1305/chacha20poly1305.go": {Primary: []Owner{filippo, roland, securityTeam}}, 105 }, 106 }, 107 } 108 109 for _, tc := range testCases { 110 var buf bytes.Buffer 111 if tc.paths != nil { 112 var oReq Request 113 oReq.Payload.Paths = tc.paths 114 if err := json.NewEncoder(&buf).Encode(oReq); err != nil { 115 t.Errorf("could not encode request: %v", err) 116 continue 117 } 118 } 119 rStr := buf.String() 120 if rStr == "" { 121 rStr = "<empty>" 122 } 123 t.Logf("Request: %v", rStr) 124 req, err := http.NewRequest(tc.method, "/owners", &buf) 125 if err != nil { 126 t.Errorf("http.NewRequest: %v", err) 127 continue 128 } 129 w := httptest.NewRecorder() 130 Handler(w, req) 131 resp := w.Result() 132 if got, want := resp.StatusCode, tc.code; got != want { 133 t.Errorf("status code: got %v; want %v", got, want) 134 } 135 136 if tc.code != http.StatusOK || tc.method == "OPTIONS" { 137 continue 138 } 139 var oResp Response 140 if err := json.NewDecoder(resp.Body).Decode(&oResp); err != nil { 141 t.Errorf("json decode: %v", err) 142 } 143 if oResp.Error != "" { 144 t.Errorf("got unexpected error in response: %q", oResp.Error) 145 } 146 if diff := cmp.Diff(oResp.Payload.Entries, tc.entries); diff != "" { 147 t.Errorf("%s: (-got +want)\n%s", tc.method, diff) 148 } 149 } 150 } 151 152 func TestIndex(t *testing.T) { 153 req, err := http.NewRequest("GET", "/owners", nil) 154 if err != nil { 155 t.Fatalf("http.NewRequest: %v", err) 156 } 157 w := httptest.NewRecorder() 158 Handler(w, req) 159 resp := w.Result() 160 if got, want := resp.StatusCode, http.StatusOK; got != want { 161 t.Errorf("status code: got %v; want %v", got, want) 162 } 163 } 164 165 func TestBadRequest(t *testing.T) { 166 defer func(old io.Writer) { log.SetOutput(old) }(os.Stderr /* TODO: use log.Writer() when Go 1.14 is out */) 167 var logBuf bytes.Buffer 168 log.SetOutput(&logBuf) 169 defer func() { 170 if t.Failed() { 171 t.Logf("Log output: %s", &logBuf) 172 } 173 }() 174 175 req, err := http.NewRequest("POST", "/owners", bytes.NewBufferString("malformed json")) 176 if err != nil { 177 t.Fatalf("http.NewRequest: %v", err) 178 } 179 w := httptest.NewRecorder() 180 Handler(w, req) 181 resp := w.Result() 182 if got, want := resp.StatusCode, http.StatusBadRequest; got != want { 183 t.Errorf("status code: got %v; want %v", got, want) 184 } 185 if got, want := resp.Header.Get("Content-Type"), "application/json"; got != want { 186 t.Errorf("Content-Type: got %q; want %q", got, want) 187 } 188 var oResp Response 189 if err := json.NewDecoder(resp.Body).Decode(&oResp); err != nil { 190 t.Fatalf("could not decode response: %v", err) 191 } 192 if got, want := oResp.Error, "unable to decode request"; got != want { 193 t.Errorf("response error text: got %q; want %q", got, want) 194 } 195 }