| package restful |
| |
| import ( |
| "net/http" |
| "net/http/httptest" |
| "testing" |
| ) |
| |
| const ( |
| pathGetFriends = "/get/{userId}/friends" |
| ) |
| |
| func TestParameter(t *testing.T) { |
| p := &Parameter{&ParameterData{Name: "name", Description: "desc"}} |
| p.AllowMultiple(true) |
| p.DataType("int") |
| p.Required(true) |
| values := map[string]string{"a": "b"} |
| p.AllowableValues(values) |
| p.bePath() |
| |
| ws := new(WebService) |
| ws.Param(p) |
| if ws.pathParameters[0].Data().Name != "name" { |
| t.Error("path parameter (or name) invalid") |
| } |
| } |
| func TestWebService_CanCreateParameterKinds(t *testing.T) { |
| ws := new(WebService) |
| if ws.BodyParameter("b", "b").Kind() != BodyParameterKind { |
| t.Error("body parameter expected") |
| } |
| if ws.PathParameter("p", "p").Kind() != PathParameterKind { |
| t.Error("path parameter expected") |
| } |
| if ws.QueryParameter("q", "q").Kind() != QueryParameterKind { |
| t.Error("query parameter expected") |
| } |
| } |
| |
| func TestCapturePanic(t *testing.T) { |
| tearDown() |
| Add(newPanicingService()) |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/fire", nil) |
| httpRequest.Header.Set("Accept", "*/*") |
| httpWriter := httptest.NewRecorder() |
| // override the default here |
| DefaultContainer.DoNotRecover(false) |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 500 != httpWriter.Code { |
| t.Error("500 expected on fire") |
| } |
| } |
| |
| func TestCapturePanicWithEncoded(t *testing.T) { |
| tearDown() |
| Add(newPanicingService()) |
| DefaultContainer.EnableContentEncoding(true) |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/fire", nil) |
| httpRequest.Header.Set("Accept", "*/*") |
| httpRequest.Header.Set("Accept-Encoding", "gzip") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 500 != httpWriter.Code { |
| t.Error("500 expected on fire, got", httpWriter.Code) |
| } |
| } |
| |
| func TestNotFound(t *testing.T) { |
| tearDown() |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/missing", nil) |
| httpRequest.Header.Set("Accept", "*/*") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 404 != httpWriter.Code { |
| t.Error("404 expected on missing") |
| } |
| } |
| |
| func TestMethodNotAllowed(t *testing.T) { |
| tearDown() |
| Add(newGetOnlyService()) |
| httpRequest, _ := http.NewRequest("POST", "http://here.com/get", nil) |
| httpRequest.Header.Set("Accept", "*/*") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 405 != httpWriter.Code { |
| t.Error("405 expected method not allowed") |
| } |
| } |
| |
| func TestSelectedRoutePath_Issue100(t *testing.T) { |
| tearDown() |
| Add(newSelectedRouteTestingService()) |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/get/232452/friends", nil) |
| httpRequest.Header.Set("Accept", "*/*") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if http.StatusOK != httpWriter.Code { |
| t.Error(http.StatusOK, "expected,", httpWriter.Code, "received.") |
| } |
| } |
| |
| func TestContentType415_Issue170(t *testing.T) { |
| tearDown() |
| Add(newGetOnlyJsonOnlyService()) |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 200 != httpWriter.Code { |
| t.Errorf("Expected 200, got %d", httpWriter.Code) |
| } |
| } |
| |
| func TestNoContentTypePOST(t *testing.T) { |
| tearDown() |
| Add(newPostNoConsumesService()) |
| httpRequest, _ := http.NewRequest("POST", "http://here.com/post", nil) |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 204 != httpWriter.Code { |
| t.Errorf("Expected 204, got %d", httpWriter.Code) |
| } |
| } |
| |
| func TestContentType415_POST_Issue170(t *testing.T) { |
| tearDown() |
| Add(newPostOnlyJsonOnlyService()) |
| httpRequest, _ := http.NewRequest("POST", "http://here.com/post", nil) |
| httpRequest.Header.Set("Content-Type", "application/json") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 200 != httpWriter.Code { |
| t.Errorf("Expected 200, got %d", httpWriter.Code) |
| } |
| } |
| |
| // go test -v -test.run TestContentType406PlainJson ...restful |
| func TestContentType406PlainJson(t *testing.T) { |
| tearDown() |
| TraceLogger(testLogger{t}) |
| Add(newGetPlainTextOrJsonService()) |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) |
| httpRequest.Header.Set("Accept", "text/plain") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if got, want := httpWriter.Code, 200; got != want { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| } |
| |
| func TestRemoveRoute(t *testing.T) { |
| tearDown() |
| TraceLogger(testLogger{t}) |
| ws := newGetPlainTextOrJsonService() |
| Add(ws) |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) |
| httpRequest.Header.Set("Accept", "text/plain") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if got, want := httpWriter.Code, 200; got != want { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| |
| // dynamic apis are disabled, should error and do nothing |
| if err := ws.RemoveRoute("/get", "GET"); err == nil { |
| t.Error("unexpected non-error") |
| } |
| |
| httpWriter = httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if got, want := httpWriter.Code, 200; got != want { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| |
| ws.SetDynamicRoutes(true) |
| if err := ws.RemoveRoute("/get", "GET"); err != nil { |
| t.Errorf("unexpected error %v", err) |
| } |
| |
| httpWriter = httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if got, want := httpWriter.Code, 404; got != want { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| } |
| func TestRemoveLastRoute(t *testing.T) { |
| tearDown() |
| TraceLogger(testLogger{t}) |
| ws := newGetPlainTextOrJsonServiceMultiRoute() |
| Add(ws) |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) |
| httpRequest.Header.Set("Accept", "text/plain") |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if got, want := httpWriter.Code, 200; got != want { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| |
| // dynamic apis are disabled, should error and do nothing |
| if err := ws.RemoveRoute("/get", "GET"); err == nil { |
| t.Error("unexpected non-error") |
| } |
| |
| httpWriter = httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if got, want := httpWriter.Code, 200; got != want { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| |
| ws.SetDynamicRoutes(true) |
| if err := ws.RemoveRoute("/get", "GET"); err != nil { |
| t.Errorf("unexpected error %v", err) |
| } |
| |
| httpWriter = httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if got, want := httpWriter.Code, 404; got != want { |
| t.Errorf("got %v, want %v", got, want) |
| } |
| } |
| |
| // go test -v -test.run TestContentTypeOctet_Issue170 ...restful |
| func TestContentTypeOctet_Issue170(t *testing.T) { |
| tearDown() |
| Add(newGetConsumingOctetStreamService()) |
| // with content-type |
| httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) |
| httpRequest.Header.Set("Content-Type", MIME_OCTET) |
| httpWriter := httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 200 != httpWriter.Code { |
| t.Errorf("Expected 200, got %d", httpWriter.Code) |
| } |
| // without content-type |
| httpRequest, _ = http.NewRequest("GET", "http://here.com/get", nil) |
| httpWriter = httptest.NewRecorder() |
| DefaultContainer.dispatch(httpWriter, httpRequest) |
| if 200 != httpWriter.Code { |
| t.Errorf("Expected 200, got %d", httpWriter.Code) |
| } |
| } |
| |
| type exampleBody struct{} |
| |
| func TestParameterDataTypeDefaults(t *testing.T) { |
| tearDown() |
| ws := new(WebService) |
| route := ws.POST("/post").Reads(&exampleBody{}, "") |
| if route.parameters[0].data.DataType != "*restful.exampleBody" { |
| t.Errorf("body parameter incorrect name: %#v", route.parameters[0].data) |
| } |
| } |
| |
| func TestParameterDataTypeCustomization(t *testing.T) { |
| tearDown() |
| ws := new(WebService) |
| ws.TypeNameHandler(func(sample interface{}) string { |
| return "my.custom.type.name" |
| }) |
| route := ws.POST("/post").Reads(&exampleBody{}, "") |
| if route.parameters[0].data.DataType != "my.custom.type.name" { |
| t.Errorf("body parameter incorrect name: %#v", route.parameters[0].data) |
| } |
| } |
| |
| func newPanicingService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Route(ws.GET("/fire").To(doPanic)) |
| return ws |
| } |
| |
| func newGetOnlyService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Route(ws.GET("/get").To(doPanic)) |
| return ws |
| } |
| |
| func newPostOnlyJsonOnlyService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Consumes("application/json") |
| ws.Route(ws.POST("/post").To(doNothing)) |
| return ws |
| } |
| |
| func newGetOnlyJsonOnlyService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Consumes("application/json") |
| ws.Route(ws.GET("/get").To(doNothing)) |
| return ws |
| } |
| |
| func newGetPlainTextOrJsonService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Produces("text/plain", "application/json") |
| ws.Route(ws.GET("/get").To(doNothing)) |
| return ws |
| } |
| |
| func newGetPlainTextOrJsonServiceMultiRoute() *WebService { |
| ws := new(WebService).Path("") |
| ws.Produces("text/plain", "application/json") |
| ws.Route(ws.GET("/get").To(doNothing)) |
| ws.Route(ws.GET("/status").To(doNothing)) |
| return ws |
| } |
| |
| func newGetConsumingOctetStreamService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Consumes("application/octet-stream") |
| ws.Route(ws.GET("/get").To(doNothing)) |
| return ws |
| } |
| |
| func newPostNoConsumesService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Route(ws.POST("/post").To(return204)) |
| return ws |
| } |
| |
| func newSelectedRouteTestingService() *WebService { |
| ws := new(WebService).Path("") |
| ws.Route(ws.GET(pathGetFriends).To(selectedRouteChecker)) |
| return ws |
| } |
| |
| func selectedRouteChecker(req *Request, resp *Response) { |
| if req.SelectedRoutePath() != pathGetFriends { |
| resp.InternalServerError() |
| } |
| } |
| |
| func doPanic(req *Request, resp *Response) { |
| println("lightning...") |
| panic("fire") |
| } |
| |
| func doNothing(req *Request, resp *Response) { |
| } |
| |
| func return204(req *Request, resp *Response) { |
| resp.WriteHeader(204) |
| } |