"fmt"
"net/http"
+ . "git.tizen.org/tools/boruta"
"github.com/dimfeld/httptreemux"
)
// Returned values are directly converted to JSON responses.
type responseData interface{}
+// reqIDPack is used as input for JSON (un)marshaller.
+type reqIDPack struct {
+ ReqID
+}
+
// reqHandler denotes function that parses HTTP request and returns responseData.
type reqHandler func(*http.Request, map[string]string) responseData
// API provides HTTP API handlers.
type API struct {
- r *httptreemux.TreeMux
+ r *httptreemux.TreeMux
+ reqs Requests
}
// jsonMustMarshal tries to marshal responseData to JSON. Panics if error occurs.
// NewAPI takes router and registers HTTP API in it. httptreemux.PanicHandler
// function is set. Also other setting of the router may be modified.
-func NewAPI(router *httptreemux.TreeMux) (api *API) {
+func NewAPI(router *httptreemux.TreeMux, requestsAPI Requests) (api *API) {
api = new(API)
+ api.reqs = requestsAPI
+
api.r = router
api.r.PanicHandler = panicHandler
"github.com/stretchr/testify/assert"
)
-const contentTypeJSON = "application/json"
+const (
+ contentTypeJSON = "application/json"
+ validReqJSON = `{
+ "ID":1,
+ "State":"WAITING",
+ "Job":null,
+ "Priority":8,
+ "Deadline":"2200-12-31T01:02:03Z",
+ "ValidAfter":"2100-01-01T04:05:06Z",
+ "Caps":{
+ "architecture":"armv7l",
+ "monitor":"yes"
+ },
+ "Owner":{}
+ }`
+)
var update bool
wm *mocks.MockWorkers
}
+var (
+ // malformedJSONTestTempl may be used by functions that need to check
+ // for malformed JSON to initialize test. Every test must set path, name
+ // and method appropriately.
+ malformedJSONTestTempl = &requestTest{
+ name: "malformed-json",
+ path: "",
+ methods: []string{},
+ json: `{"Priority{}`,
+ contentType: contentTypeJSON,
+ status: http.StatusBadRequest,
+ }
+)
+
func TestMain(m *testing.M) {
flag.BoolVar(&update, "update", false, "update testdata")
flag.Parse()
rq: mocks.NewMockRequests(ctrl),
wm: mocks.NewMockWorkers(ctrl),
}
- return assert.New(t), m, NewAPI(httptreemux.New())
+ return assert.New(t), m, NewAPI(httptreemux.New(), m.rq)
}
func (m *allMocks) finish() {
m.ctrl.Finish()
}
+func testFromTempl(templ *requestTest, name string, path string,
+ methods ...string) (ret requestTest) {
+ ret = *templ
+ ret.name = name + templ.name
+ ret.path = path
+ if len(methods) != 0 {
+ ret.methods = methods
+ }
+ return
+}
+
func runTests(assert *assert.Assertions, api *API, tests []requestTest) {
srv := httptest.NewServer(api.r)
defer srv.Close()
package v1
import (
+ "encoding/json"
"net/http"
+
+ . "git.tizen.org/tools/boruta"
)
// newRequestHandler parses HTTP request for creating new Boruta request and
// calls NewRequest().
func (api *API) newRequestHandler(r *http.Request, ps map[string]string) responseData {
- return newServerError(ErrNotImplemented, "new request")
+ var newReq ReqInfo
+ defer r.Body.Close()
+
+ if err := json.NewDecoder(r.Body).Decode(&newReq); err != nil {
+ return newServerError(err)
+ }
+
+ //FIXME: currently UserInfo is ignored. Change when user support is added.
+ rid, err := api.reqs.NewRequest(newReq.Caps, newReq.Priority, UserInfo{},
+ newReq.ValidAfter.UTC(), newReq.Deadline.UTC())
+ if err != nil {
+ return newServerError(err)
+ }
+
+ return reqIDPack{rid}
}
// closeRequestHandler parses HTTP request for closing existing Boruta request
package v1
import (
+ "encoding/json"
"net/http"
"testing"
+
+ . "git.tizen.org/tools/boruta"
+ "git.tizen.org/tools/boruta/requests"
)
func TestNewRequestHandler(t *testing.T) {
assert, m, api := initTest(t)
defer m.finish()
+ prefix := "new-req-"
+ path := "/api/v1/reqs/"
+ methods := []string{http.MethodPost}
+ malformedJSONTest := testFromTempl(malformedJSONTestTempl, prefix, path, methods...)
+
+ var req ReqInfo
+ err := json.Unmarshal([]byte(validReqJSON), &req)
+ assert.Nil(err)
+
+ m.rq.EXPECT().NewRequest(req.Caps, req.Priority, req.Owner, req.ValidAfter,
+ req.Deadline).Return(ReqID(1), nil)
+ m.rq.EXPECT().NewRequest(req.Caps, Priority(32), req.Owner, req.ValidAfter,
+ req.Deadline).Return(ReqID(0), requests.ErrPriority)
+
tests := []requestTest{
{
- name: "new-req",
- path: "/api/v1/reqs/",
- methods: []string{http.MethodPost},
- json: ``,
+ // valid request
+ name: prefix + "valid",
+ path: path,
+ methods: methods,
+ json: validReqJSON,
contentType: contentTypeJSON,
- status: http.StatusNotImplemented,
+ status: http.StatusCreated,
+ },
+ {
+ // bad request - priority out of bounds
+ name: prefix + "bad-prio",
+ path: path,
+ methods: methods,
+ json: `{"Priority":32,"Deadline":"2200-12-31T01:02:03Z","ValidAfter":"2100-01-01T04:05:06Z","Caps":{"architecture":"armv7l","monitor":"yes"}}`,
+ contentType: contentTypeJSON,
+ status: http.StatusBadRequest,
},
+ // bad request - malformed request JSON
+ malformedJSONTest,
}
runTests(assert, api, tests)
+++ /dev/null
-{"error":"not implemented yet: new request"}
\ No newline at end of file
--- /dev/null
+{"error":"invalid request: requested priority out of bounds"}
\ No newline at end of file
--- /dev/null
+{"error":"invalid request: unexpected EOF"}
\ No newline at end of file
--- /dev/null
+{"ReqID":1}
\ No newline at end of file