"encoding/json"
"fmt"
"net/http"
+ "strconv"
. "git.tizen.org/tools/boruta"
"github.com/dimfeld/httptreemux"
return
}
+
+func parseReqID(id string) (ReqID, error) {
+ reqid, err := strconv.ParseUint(id, 10, 64)
+ return ReqID(reqid), err
+}
"strings"
"testing"
+ . "git.tizen.org/tools/boruta"
"git.tizen.org/tools/boruta/mocks"
"github.com/dimfeld/httptreemux"
"github.com/golang/mock/gomock"
const (
contentTypeJSON = "application/json"
+ invalidID = "test"
validReqJSON = `{
"ID":1,
"State":"WAITING",
wm *mocks.MockWorkers
}
+// TestTempl variables shouldn't be used directly, but rather as an input for
+// testFromTempl() function.
var (
// malformedJSONTestTempl may be used by functions that need to check
// for malformed JSON to initialize test. Every test must set path, name
contentType: contentTypeJSON,
status: http.StatusBadRequest,
}
+
+ // invalidIDTestTempl may be used by functions that need to check for
+ // cases where malformed ID is given in a URL to initialize test.
+ // Every test must set path, name and method appropriately.
+ invalidIDTestTempl = &requestTest{
+ name: "bad-id",
+ path: "",
+ methods: []string{},
+ json: ``,
+ contentType: contentTypeJSON,
+ status: http.StatusBadRequest,
+ }
+
+ // notFoundTestTempl may be used by functions that need to check for
+ // not existing requests to initialize test. Every test must set path,
+ // name and method appropriately.
+ notFoundTestTempl = &requestTest{
+ name: "missing",
+ path: "",
+ methods: []string{},
+ json: ``,
+ contentType: contentTypeJSON,
+ status: http.StatusNotFound,
+ }
)
func TestMain(m *testing.M) {
Err: "invalid request: more details",
Status: http.StatusBadRequest,
}
+ notFound := &serverError{
+ Err: NotFoundError("Fern Flower").Error(),
+ Status: http.StatusNotFound,
+ }
assert.Equal(badRequest, newServerError(errors.New("foo")))
assert.Equal(missingBody, newServerError(io.EOF))
assert.Equal(notImplemented, newServerError(ErrNotImplemented))
assert.Equal(internalErr, newServerError(ErrInternalServerError))
assert.Equal(customErr, newServerError(ErrBadRequest, "more details"))
+ assert.Equal(notFound, newServerError(NotFoundError("Fern Flower")))
assert.Nil(newServerError(nil))
}
assert.Equal(expected, body, tcaseErrStr)
}
}
+
+func TestParseReqID(t *testing.T) {
+ assert := assert.New(t)
+ reqid, err := parseReqID("1")
+ assert.Nil(err)
+ assert.Equal(ReqID(1), reqid)
+ _, err = parseReqID(invalidID)
+ assert.NotNil(err)
+}
"errors"
"io"
"net/http"
+
+ . "git.tizen.org/tools/boruta"
)
// serverError represents error that occured while creating response.
ErrInternalServerError = errors.New("internal server error")
// ErrBadRequest is returned when User request is invalid.
ErrBadRequest = errors.New("invalid request")
+ // ErrBadID is returned when User provided ID which can't be parsed into
+ // uint.
+ ErrBadID = errors.New("ID provided in URL isn't valid")
)
+// isNotFoundError returns true if passed error is of type NotFoundError.
+func isNotFoundError(err error) bool {
+ _, ok := err.(NotFoundError)
+ return ok
+}
+
// newServerError provides pointer to initialized serverError.
func newServerError(err error, details ...string) (ret *serverError) {
if err == nil {
if len(details) > 0 {
ret.Err += ": " + details[0]
}
+ if isNotFoundError(err) {
+ ret.Status = http.StatusNotFound
+ return
+ }
switch err {
case ErrNotImplemented:
// closeRequestHandler parses HTTP request for closing existing Boruta request
// and calls CloseRequest().
func (api *API) closeRequestHandler(r *http.Request, ps map[string]string) responseData {
- return newServerError(ErrNotImplemented, "close request")
+ defer r.Body.Close()
+
+ reqid, err := parseReqID(ps["id"])
+ if err != nil {
+ return newServerError(ErrBadID)
+ }
+
+ return newServerError(api.reqs.CloseRequest(reqid))
}
// updateRequestHandler parses HTTP request for modification of existing Boruta
import (
"encoding/json"
+ "fmt"
"net/http"
"testing"
assert, m, api := initTest(t)
defer m.finish()
+ methods := []string{http.MethodPost}
+ pathfmt := "/api/v1/reqs/%s/close"
+ prefix := "close-req-"
+
+ invalidIDTest := testFromTempl(invalidIDTestTempl, prefix, fmt.Sprintf(pathfmt, invalidID), methods...)
+ notFoundTest := testFromTempl(notFoundTestTempl, prefix, fmt.Sprintf(pathfmt, "2"), methods...)
+ m.rq.EXPECT().CloseRequest(ReqID(1)).Return(nil)
+ m.rq.EXPECT().CloseRequest(ReqID(2)).Return(NotFoundError("Request"))
+
tests := []requestTest{
+ // Close valid request in state WAIT (cancel).
{
- name: "close-req",
- path: "/api/v1/reqs/8/close",
- methods: []string{http.MethodPost},
+ name: prefix + "valid",
+ path: fmt.Sprintf(pathfmt, "1"),
+ methods: methods,
json: ``,
contentType: contentTypeJSON,
- status: http.StatusNotImplemented,
+ status: http.StatusNoContent,
},
+ // Try to close request with invalid ID.
+ invalidIDTest,
+ // Try to close request which doesn't exist.
+ notFoundTest,
}
runTests(assert, api, tests)
+++ /dev/null
-{"error":"not implemented yet: close request"}
\ No newline at end of file
--- /dev/null
+{"error":"invalid request: ID provided in URL isn't valid"}
\ No newline at end of file
--- /dev/null
+{"error":"Request not found"}
\ No newline at end of file