github.com/bazelbuild/rules_webtesting@v0.2.0/go/wsl/wsl_test.go (about) 1 package wsl 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "io" 9 "net/http" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/bazelbuild/rules_webtesting/go/bazel" 15 "github.com/bazelbuild/rules_webtesting/go/portpicker" 16 ) 17 18 func TestHandleHealthz(t *testing.T) { 19 handler := createHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), "", func() {}) 20 21 w := newFakeResponseWriter() 22 r, err := http.NewRequest(http.MethodGet, "http://localhost/healthz", nil) 23 if err != nil { 24 t.Fatal(err) 25 } 26 27 handler.ServeHTTP(w, r) 28 29 if w.status != http.StatusOK { 30 t.Errorf(`Got status %d, want %d`, w.status, http.StatusOK) 31 } 32 33 if !strings.Contains(string(w.Bytes()), "ok") { 34 t.Errorf(`Got %q, want to contain "ok"`, string(w.Bytes())) 35 } 36 } 37 38 func TestHandleQuitQuitQuit(t *testing.T) { 39 cancelCalled := 0 40 41 cancel := func() { 42 cancelCalled = cancelCalled + 1 43 } 44 45 handler := createHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), "", cancel) 46 47 w := newFakeResponseWriter() 48 r, err := http.NewRequest(http.MethodGet, "http://localhost/quitquitquit", nil) 49 if err != nil { 50 t.Fatal(err) 51 } 52 53 handler.ServeHTTP(w, r) 54 55 if w.status != http.StatusOK { 56 t.Errorf(`Got status %d, want %d`, w.status, http.StatusOK) 57 } 58 59 if !strings.Contains(string(w.Bytes()), "shutting down") { 60 t.Errorf(`Got %q, want to contain "shutting down"`, string(w.Bytes())) 61 } 62 63 if cancelCalled != 1 { 64 t.Errorf("Cancel was called %d times, want 1 time", cancelCalled) 65 } 66 } 67 68 func TestHandleSession(t *testing.T) { 69 hubCalled := 0 70 71 hub := http.HandlerFunc(func(http.ResponseWriter, *http.Request) { 72 hubCalled = hubCalled + 1 73 }) 74 75 handler := createHandler(hub, "", func() {}) 76 77 r, err := http.NewRequest(http.MethodGet, "http://localhost/session", nil) 78 if err != nil { 79 t.Fatal(err) 80 } 81 82 handler.ServeHTTP(newFakeResponseWriter(), r) 83 84 if hubCalled != 1 { 85 t.Errorf("Hub was called %d times, want 1 time", hubCalled) 86 } 87 88 r, err = http.NewRequest(http.MethodGet, "http://localhost/session/id", nil) 89 handler.ServeHTTP(newFakeResponseWriter(), r) 90 91 if hubCalled != 2 { 92 t.Errorf("Hub was called %d times, want 2 time", hubCalled) 93 } 94 } 95 96 func TestHandleGoogleStaticFile(t *testing.T) { 97 testData, err := bazel.Runfile("testdata/") 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 handler := createHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), testData, func() {}) 103 104 t.Run("exists", func(t *testing.T) { 105 w := newFakeResponseWriter() 106 r, _ := http.NewRequest(http.MethodGet, "http://localhost/google/staticfile/testpage.html", nil) 107 108 handler.ServeHTTP(w, r) 109 110 if w.status != http.StatusOK { 111 t.Errorf(`Got status %d, want %d`, w.status, http.StatusOK) 112 } 113 114 if !strings.Contains(string(w.Bytes()), "Test Page") { 115 t.Errorf(`Got %q, want to contain "Test Page"`, string(w.Bytes())) 116 } 117 }) 118 119 t.Run("does not exist", func(t *testing.T) { 120 w := newFakeResponseWriter() 121 r, _ := http.NewRequest(http.MethodGet, "http://localhost/google/staticfile/does-not-exist.txt", nil) 122 123 handler.ServeHTTP(w, r) 124 125 if w.status != http.StatusNotFound { 126 t.Errorf(`Got status %d, want %d`, w.status, http.StatusNotFound) 127 } 128 }) 129 } 130 131 func TestHandleStatus(t *testing.T) { 132 handler := createHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), "", func() {}) 133 134 r, err := http.NewRequest(http.MethodGet, "http://localhost/status", nil) 135 if err != nil { 136 t.Fatal(err) 137 } 138 139 frw := newFakeResponseWriter() 140 141 handler.ServeHTTP(frw, r) 142 143 if frw.status != http.StatusOK { 144 t.Errorf("Got status %d, want %d", frw.status, http.StatusOK) 145 } 146 147 value := struct { 148 Status *int 149 Value *struct { 150 Build map[string]string 151 OS map[string]string 152 Ready *bool 153 Message *string 154 } 155 }{} 156 157 if err := json.NewDecoder(frw).Decode(&value); err != nil { 158 t.Fatal(err) 159 } 160 161 if value.Status == nil || *value.Status != 0 { 162 t.Errorf("Got status %v, want 0", value.Status) 163 } 164 165 if value.Value == nil { 166 t.Fatal("Got nil value, want non-nil") 167 } 168 169 if value.Value.Ready == nil || !*value.Value.Ready { 170 t.Errorf("Got %v Value.Ready, want true", value.Value.Ready) 171 } 172 173 if value.Value.Message == nil { 174 t.Error("Got nil Value.Message, want non-nil") 175 } 176 177 if value.Value.Build == nil { 178 t.Error("Got nil Value.Build, want non-nil") 179 } 180 181 if value.Value.OS == nil { 182 t.Error("Got nil Value.OS, want non-nil") 183 } 184 } 185 186 func TestHandleRoot(t *testing.T) { 187 handler := createHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), "", func() {}) 188 189 w := newFakeResponseWriter() 190 r, err := http.NewRequest(http.MethodGet, "http://localhost/", nil) 191 if err != nil { 192 t.Fatal(err) 193 } 194 195 handler.ServeHTTP(w, r) 196 197 if w.status != http.StatusNotFound { 198 t.Errorf(`Got status %d, want %d`, w.status, http.StatusNotFound) 199 } 200 } 201 202 func TestStartAndShutdownServer(t *testing.T) { 203 handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { 204 io.WriteString(w, "ok") 205 }) 206 207 port, err := portpicker.PickUnusedPort() 208 if err != nil { 209 t.Fatal(err) 210 } 211 212 ctx, cancel := context.WithCancel(context.Background()) 213 214 errChan := make(chan error) 215 216 go func() { 217 errChan <- startServer(ctx, port, handler) 218 }() 219 220 // Give server plenty of time to get started 221 time.Sleep(100 * time.Millisecond) 222 223 addr := fmt.Sprintf("http://localhost:%d", port) 224 225 resp, err := http.Get(addr) 226 if err != nil { 227 t.Fatal(err) 228 } 229 230 if resp.StatusCode != http.StatusOK { 231 t.Fatalf("Got %d status, expected 200", resp.StatusCode) 232 } 233 234 cancel() 235 236 timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), 5*time.Second) 237 defer timeoutCancel() 238 239 select { 240 case <-timeoutCtx.Done(): 241 t.Fatal("expected server to stop with 5 seconds") 242 case err := <-errChan: 243 if err != nil { 244 t.Error(err) 245 } 246 } 247 248 _, err = http.Get(addr) 249 if err == nil { 250 t.Fatal("Got nil err, want err") 251 } 252 } 253 254 func newFakeResponseWriter() *fakeResponseWriter { 255 return &fakeResponseWriter{ 256 Buffer: &bytes.Buffer{}, 257 status: http.StatusOK, 258 header: http.Header(map[string][]string{}), 259 } 260 } 261 262 type fakeResponseWriter struct { 263 *bytes.Buffer 264 status int 265 header http.Header 266 } 267 268 func (frw *fakeResponseWriter) Header() http.Header { 269 return frw.header 270 } 271 272 func (frw *fakeResponseWriter) WriteHeader(status int) { 273 frw.status = status 274 }