diff --git a/src/numbers/numbers_test.go b/src/numbers/numbers_test.go index a50f5e2..57ed479 100644 --- a/src/numbers/numbers_test.go +++ b/src/numbers/numbers_test.go @@ -1,9 +1,12 @@ package main import ( + "encoding/json" + "fmt" "net/http" "net/http/httptest" "testing" + "time" ) // Tests valid and invalid URLs via 'validateURL'. @@ -109,4 +112,110 @@ func TestHandler(t *testing.T) { t.Errorf("Body not as expected, got %s, expected %s", body, expected) } } + + // valid numbers, all in time + { + ts1 := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{2, 3, 5, 7, 11, 13}, 0))) + defer ts1.Close() + ts2 := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{1, 1, 2, 3, 5, 8, 13, 21}, 0))) + defer ts2.Close() + ts3 := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23}, 0))) + defer ts3.Close() + ts4 := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{5, 17, 3, 19, 76, 24, 1, 5, 10, 34, 8, 27, 7}, 0))) + defer ts4.Close() + + req, err := http.NewRequest("GET", fmt.Sprintf("/numbers?u=%s&u=%s&u=%s&u=%s", ts1.URL, ts2.URL, ts3.URL, ts4.URL), nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(numbersHandler) + handler.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("Handler returned status code %v, expected %v", status, http.StatusOK) + } + body := rr.Body.String() + expected := "{\"Numbers\":[1,2,3,5,7,8,9,10,11,13,15,17,19,21,23,24,27,34,76]}\n" + if body != expected { + t.Errorf("Body not as expected, got %s, expected %s", body, expected) + } + } + + // valid numbers, skipping those that are not in time or respond with "service unavailable" + { + ts1 := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{2, 3, 5, 7, 11, 13}, 200))) + defer ts1.Close() + ts2 := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{1, 1, 2, 3, 5, 8, 13, 21}, 300))) + defer ts2.Close() + ts3 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "service unavailable", http.StatusServiceUnavailable) + })) + defer ts3.Close() + ts4 := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{5, 17, 3, 19, 76, 24, 1, 5, 10, 34, 8, 27, 7}, 500))) + defer ts4.Close() + + req, err := http.NewRequest("GET", fmt.Sprintf("/numbers?u=%s&u=%s&u=%s&u=%s", ts1.URL, ts2.URL, ts3.URL, ts4.URL), nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(numbersHandler) + handler.ServeHTTP(rr, req) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("Handler returned status code %v, expected %v", status, http.StatusOK) + } + body := rr.Body.String() + expected := "{\"Numbers\":[1,2,3,5,7,8,11,13,21]}\n" + if body != expected { + t.Errorf("Body not as expected, got %s, expected %s", body, expected) + } + } + + // ensure response time is below 500ms + { + ts := httptest.NewServer(http.HandlerFunc(numbersHandlerInTime([]int{5, 17, 3, 19, 76, 24, 1, 5, 10, 34, 8, 27, 7}, 500))) + defer ts.Close() + + req, err := http.NewRequest("GET", fmt.Sprintf("/numbers?u=%s", ts.URL), nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(numbersHandler) + start := time.Now() + handler.ServeHTTP(rr, req) + end := time.Now() + elapsed := end.Sub(start) + fmt.Println(elapsed) + + if status := rr.Code; status != http.StatusOK { + t.Errorf("Handler returned status code %v, expected %v", status, http.StatusOK) + } + body := rr.Body.String() + expected := "{\"Numbers\":[]}\n" + if body != expected { + t.Errorf("Body not as expected, got %s, expected %s", body, expected) + } + + if elapsed > 500000000 { + t.Errorf("Time response not within 500ms, got %d", elapsed) + } + } + +} + +func numbersHandlerInTime(numbers []int, waitPeriod int) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + time.Sleep(time.Duration(waitPeriod) * time.Millisecond) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + json.NewEncoder(w).Encode(map[string]interface{}{"Numbers": numbers}) + } }