import (
"bytes"
+ "encoding/json"
+ "io"
+ "net/http"
"net/http/httptest"
+ "net/url"
+ "git.arvados.org/arvados.git/sdk/go/arvadostest"
check "gopkg.in/check.v1"
)
+type testReq struct {
+ method string
+ path string
+ token string // default is ActiveTokenV2; use noToken to omit
+ param map[string]interface{}
+ attrs map[string]interface{}
+ attrsKey string
+ header http.Header
+
+ // variations on request formatting
+ json bool
+ jsonAttrsTop bool
+ jsonStringParam bool
+ tokenInBody bool
+ tokenInQuery bool
+ noContentType bool
+
+ body *bytes.Buffer
+}
+
+const noToken = "(no token)"
+
+func (tr *testReq) Request() *http.Request {
+ param := map[string]interface{}{}
+ for k, v := range tr.param {
+ param[k] = v
+ }
+
+ if tr.body != nil {
+ // caller provided a buffer
+ } else if tr.json {
+ if tr.jsonAttrsTop {
+ for k, v := range tr.attrs {
+ if tr.jsonStringParam {
+ j, err := json.Marshal(v)
+ if err != nil {
+ panic(err)
+ }
+ param[k] = string(j)
+ } else {
+ param[k] = v
+ }
+ }
+ } else if tr.attrs != nil {
+ if tr.jsonStringParam {
+ j, err := json.Marshal(tr.attrs)
+ if err != nil {
+ panic(err)
+ }
+ param[tr.attrsKey] = string(j)
+ } else {
+ param[tr.attrsKey] = tr.attrs
+ }
+ }
+ tr.body = bytes.NewBuffer(nil)
+ err := json.NewEncoder(tr.body).Encode(param)
+ if err != nil {
+ panic(err)
+ }
+ } else {
+ values := make(url.Values)
+ for k, v := range param {
+ if vs, ok := v.(string); ok && !tr.jsonStringParam {
+ values.Set(k, vs)
+ } else {
+ jv, err := json.Marshal(v)
+ if err != nil {
+ panic(err)
+ }
+ values.Set(k, string(jv))
+ }
+ }
+ if tr.attrs != nil {
+ jattrs, err := json.Marshal(tr.attrs)
+ if err != nil {
+ panic(err)
+ }
+ values.Set(tr.attrsKey, string(jattrs))
+ }
+ tr.body = bytes.NewBuffer(nil)
+ io.WriteString(tr.body, values.Encode())
+ }
+ method := tr.method
+ if method == "" {
+ method = "GET"
+ }
+ path := tr.path
+ if path == "" {
+ path = "example/test/path"
+ }
+ req := httptest.NewRequest(method, "https://an.example/"+path, tr.body)
+ token := tr.token
+ if token == "" {
+ token = arvadostest.ActiveTokenV2
+ }
+ if token != noToken {
+ req.Header.Set("Authorization", "Bearer "+token)
+ }
+ if tr.json {
+ req.Header.Set("Content-Type", "application/json")
+ } else {
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ }
+ for k, v := range tr.header {
+ req.Header[k] = append([]string(nil), v...)
+ }
+ return req
+}
+
+func (tr *testReq) bodyContent() string {
+ return string(tr.body.Bytes())
+}
+
func (s *RouterSuite) TestAttrsInBody(c *check.C) {
- for _, body := range []string{
- `{"foo":"bar"}`,
- `{"model_name": {"foo":"bar"}}`,
+ attrs := map[string]interface{}{"foo": "bar"}
+ for _, tr := range []testReq{
+ {attrsKey: "model_name", json: true, attrs: attrs},
+ {attrsKey: "model_name", json: true, attrs: attrs, jsonAttrsTop: true},
+ {attrsKey: "model_name", json: true, attrs: attrs, jsonAttrsTop: true, jsonStringParam: true},
+ {attrsKey: "model_name", json: true, attrs: attrs, jsonAttrsTop: false, jsonStringParam: true},
} {
- c.Logf("body: %s", body)
- req := httptest.NewRequest("POST", "https://an.example/ctrl", bytes.NewBufferString(body))
- req.Header.Set("Content-Type", "application/json")
- params, err := s.rtr.loadRequestParams(req, "model_name")
- c.Assert(err, check.IsNil)
+ c.Logf("tr: %#v", tr)
+ req := tr.Request()
+ params, err := s.rtr.loadRequestParams(req, tr.attrsKey)
c.Logf("params: %#v", params)
+ c.Assert(err, check.IsNil)
c.Check(params, check.NotNil)
c.Assert(params["attrs"], check.FitsTypeOf, map[string]interface{}{})
c.Check(params["attrs"].(map[string]interface{})["foo"], check.Equals, "bar")
}
}
+
+func (s *RouterSuite) TestBoolParam(c *check.C) {
+ testKey := "ensure_unique_name"
+
+ for i, tr := range []testReq{
+ {method: "POST", param: map[string]interface{}{testKey: false}, json: true},
+ {method: "POST", param: map[string]interface{}{testKey: false}},
+ {method: "POST", param: map[string]interface{}{testKey: "false"}},
+ {method: "POST", param: map[string]interface{}{testKey: "0"}},
+ {method: "POST", param: map[string]interface{}{testKey: ""}},
+ } {
+ c.Logf("#%d, tr: %#v", i, tr)
+ req := tr.Request()
+ c.Logf("tr.body: %s", tr.bodyContent())
+ params, err := s.rtr.loadRequestParams(req, tr.attrsKey)
+ c.Logf("params: %#v", params)
+ c.Assert(err, check.IsNil)
+ c.Check(params, check.NotNil)
+ c.Check(params[testKey], check.Equals, false)
+ }
+
+ for i, tr := range []testReq{
+ {method: "POST", param: map[string]interface{}{testKey: true}, json: true},
+ {method: "POST", param: map[string]interface{}{testKey: true}},
+ {method: "POST", param: map[string]interface{}{testKey: "true"}},
+ {method: "POST", param: map[string]interface{}{testKey: "1"}},
+ } {
+ c.Logf("#%d, tr: %#v", i, tr)
+ req := tr.Request()
+ c.Logf("tr.body: %s", tr.bodyContent())
+ params, err := s.rtr.loadRequestParams(req, tr.attrsKey)
+ c.Logf("params: %#v", params)
+ c.Assert(err, check.IsNil)
+ c.Check(params, check.NotNil)
+ c.Check(params[testKey], check.Equals, true)
+ }
+}
+
+func (s *RouterSuite) TestOrderParam(c *check.C) {
+ for i, tr := range []testReq{
+ {method: "POST", param: map[string]interface{}{"order": ""}, json: true},
+ {method: "POST", param: map[string]interface{}{"order": ""}, json: false},
+ {method: "POST", param: map[string]interface{}{"order": []string{}}, json: true},
+ {method: "POST", param: map[string]interface{}{"order": []string{}}, json: false},
+ {method: "POST", param: map[string]interface{}{}, json: true},
+ {method: "POST", param: map[string]interface{}{}, json: false},
+ } {
+ c.Logf("#%d, tr: %#v", i, tr)
+ req := tr.Request()
+ params, err := s.rtr.loadRequestParams(req, tr.attrsKey)
+ c.Assert(err, check.IsNil)
+ c.Assert(params, check.NotNil)
+ if order, ok := params["order"]; ok && order != nil {
+ c.Check(order, check.DeepEquals, []interface{}{})
+ }
+ }
+
+ for i, tr := range []testReq{
+ {method: "POST", param: map[string]interface{}{"order": "foo,bar desc"}, json: true},
+ {method: "POST", param: map[string]interface{}{"order": "foo,bar desc"}, json: false},
+ {method: "POST", param: map[string]interface{}{"order": "[\"foo\", \"bar desc\"]"}, json: false},
+ {method: "POST", param: map[string]interface{}{"order": []string{"foo", "bar desc"}}, json: true},
+ {method: "POST", param: map[string]interface{}{"order": []string{"foo", "bar desc"}}, json: false},
+ } {
+ c.Logf("#%d, tr: %#v", i, tr)
+ req := tr.Request()
+ params, err := s.rtr.loadRequestParams(req, tr.attrsKey)
+ c.Assert(err, check.IsNil)
+ if _, ok := params["order"].([]string); ok {
+ c.Check(params["order"], check.DeepEquals, []string{"foo", "bar desc"})
+ } else {
+ c.Check(params["order"], check.DeepEquals, []interface{}{"foo", "bar desc"})
+ }
+ }
+}