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  }