func TestBasicQuery_Conds(t *testing.T) { q := store.NewQuery(). AddCond("HelloWorld =", "foo bar"). AddCond("FooBar !=", "hello world") cs := q.GetConds().GetAll() success := true if cs[0].Prop != "HelloWorld =" { t.Errorf("First cond Prop is not defined correctly. "+ "Expected \"%s\" but get \"%s\"", "HelloWorld =", cs[0].Prop) success = false } else if cs[0].Value != "foo bar" { t.Errorf("First cond Value is not defined correctly. "+ "Expected \"%s\" but get \"%s\"", "foobar", cs[0].Value) success = false } if cs[1].Prop != "FooBar !=" { t.Errorf("Second cond Prop is not defined correctly. "+ "Expected \"%s\" but get \"%s\"", "FooBar !=", cs[1].Prop) success = false } else if cs[1].Value != "hello world" { t.Errorf("Second cond Value is not defined correctly. "+ "Expected \"%s\" but get \"%s\"", "hello world", cs[1].Value) success = false } if success { t.Log("Query cond routine works expectedly") } }
func TestBasicQuery_Sorts(t *testing.T) { q := store.NewQuery(). Sort("HelloWorld"). Sort("-FooBar") ss := q.GetSorts().GetAll() success := true if ss[0].String() != "HelloWorld" { t.Errorf("First sort is not defined correctly. "+ "Expected \"%s\" but get \"%s\"", "HelloWorld", ss[0]) success = false } if ss[1].String() != "-FooBar" { t.Errorf("Second cond Prop is not defined correctly. "+ "Expected \"%s\" but get \"%s\"", "-FooBar", ss[1]) success = false } if success { t.Log("Query cond routine works expectedly") } }
func TestConds_branching(t *testing.T) { var err error fn := "./test3.tmp" // two branch query cond1 := store.NewConds(). Add("HelloWorld =", "foo bar"). Add("FooBar !=", "hello world") cond2 := store.NewConds(). Add("HelloWorld =", "foo bar 2"). Add("FooBar !=", "hello world") q := store.NewQuery(). AddCond("", cond1). AddCond("", cond2) q.GetConds().SetRel(store.Or) // test source source := upperio.NewSource(testUpperDb(fn)) // add dummy data to the database if err := testUpperDbData(source); err != nil { t.Fatal(err.Error()) } // connect to database again conn, err := source.Open() if err != nil { t.Error(err.Error()) } defer conn.Close() // query connection sess := conn.Raw().(db.Database) coll, err := sess.Collection("dummy_data") res := coll.Find(upperio.Conds(q.GetConds())) var tds []testData res.All(&tds) expLen := 2 if l := len(tds); l != expLen { t.Errorf("result set size expected: %d, got: %d\ntest data set:\t%#v", expLen, l, tds) } // clean up the temp database err = os.Remove(fn) if err != nil { t.Error(err.Error()) } }
func TestConds(t *testing.T) { var err error fn := "./test2.tmp" q := store.NewQuery(). AddCond("HelloWorld =", "foo bar"). AddCond("FooBar !=", "hello world") // dummy source source := upperio.NewSource(testUpperDb(fn)) // add dummy data to the database if err := testUpperDbData(source); err != nil { t.Fatal(err.Error()) } // connect to database again conn, err := source.Open() if err != nil { t.Error(err.Error()) } defer conn.Close() // query connection sess := conn.Raw().(db.Database) coll, err := sess.Collection("dummy_data") if err != nil { t.Error(err.Error()) } conds := upperio.Conds(q.GetConds()) res := coll.Find(conds) var tds []testData res.All(&tds) if len(tds) != 1 { t.Errorf("Incorrect test data set: %#v", tds) } // clean up the temp database err = os.Remove(fn) if err != nil { t.Error(err.Error()) } }
func TestDBSavePassword(t *testing.T) { var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") randSeq := func(n int) string { b := make([]rune, n) for i := range b { b[i] = letters[rand.Intn(len(letters))] } return string(b) } pass := randSeq(20) // test store context type tempKey int const ( testDB tempKey = iota ) db, err := defaultTestSrc().Open() if err != nil { t.Errorf("unexpected error: %#v", err.Error()) } us, err := oauth2.UserStoreProvider(db.Raw()) if err != nil { t.Errorf("unexpected error: %#v", err.Error()) } u1 := &oauth2.User{Username: "******"} u1.Password = u1.Hash(pass) us.Create(nil, u1) users := []oauth2.User{} us.Search(store.NewQuery().AddCond("id", u1.ID)).All(&users) if want, have := 1, len(users); want != have { t.Errorf("expected users to have %d value, got %d instead (users=%#v)", want, have, users) } u2 := users[0] if want, have := u1.Password, u2.Password; !u2.PasswordIs(pass) { t.Errorf("password mismatch. expected %#v, got %#v", want, have) } }
func TestSort(t *testing.T) { q := store.NewQuery() q.GetSorts().Add("para1").Add("-para2").Add("-para3") res := upperio.Sort(q) expLen := 3 if l := len(res); l != expLen { t.Errorf("result length expected: %d, get: %d", expLen, l) t.FailNow() } if expStr := "para1"; res[0] != expStr { t.Errorf("result[0] expected: %d, get: %d", expStr, res[0]) } if expStr := "-para2"; res[1] != expStr { t.Errorf("result[1] expected: %d, get: %d", expStr, res[1]) } if expStr := "-para3"; res[2] != expStr { t.Errorf("result[2] expected: %d, get: %d", expStr, res[2]) } }
// One returns the first Client matches condition(s) func (s *ClientStore) One( c store.Conds, ep store.EntityPtr) (err error) { // retrieve results from database l := &[]Client{} q := store.NewQuery().SetConds(c) // dump results into pointer of map / struct err = s.Search(q).All(l) if err != nil { return } // if not found, report if len(*l) == 0 { err = store.ErrorNotFound return } // assign the value of given point // to the first retrieved value (*ep.(*Client)) = (*l)[0] return nil }
func TestConds_empty(t *testing.T) { q := store.NewQuery() if cs := upperio.Conds(q.GetConds()); cs != nil { t.Errorf("Conds with empty new query should return nil. Instead got %#v", cs) } }
func UserStoreServices(paths httpservice.Paths, endpoints map[string]endpoint.Endpoint) (handlers httpservice.Services) { // variables to use later noun := paths.Noun() storeKey := KeyUser getStore := func(ctx context.Context) (s *UserStore, err error) { raw, err := store.Get(ctx, storeKey) if err != nil { return } s, ok := raw.(*UserStore) if !ok { err = fmt.Errorf(`store.Get(KeyUser) does not return *KeyUser`) return } return } // define default middlewares var prepareCreate endpoint.Middleware = func(inner endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (respond interface{}, err error) { // placeholder: anything you want to do with the entity // before append to database httpservice.EnforceCreate(request) return inner(ctx, request) } } var prepareUpdate endpoint.Middleware = func(inner endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { sReq := request.(*httpservice.Request) // get context information r := gourdctx.HTTPRequest(ctx) if r == nil { serr := store.ErrorInternal serr.ServerMsg = "missing request in context" err = serr return } el := &[]User{} q := sReq.Query // get store s, err := getStore(ctx) if err != nil { serr := store.ErrorInternal serr.ServerMsg = fmt.Sprintf("error obtaining %s store (%s)", storeKey, err) err = serr return } defer s.Close() // find the previous content of the id err = s.Search(q).All(el) if err != nil { serr := store.ErrorInternal serr.ServerMsg = fmt.Sprintf("error searching %s: %s", noun.Singular(), err) err = serr return } // tell the inner if len(*el) > 0 { sReq.Previous = &(*el)[0] } // enforce agreement on sReq.Payload with previous sReq.Entity httpservice.EnforceUpdate(sReq.Previous, sReq.Payload) // placeholder: anything you want to do with the entity // before update to database return inner(ctx, sReq) } } var prepareList endpoint.Middleware = func(inner endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { response, err = inner(ctx, request) if err != nil { return } vmap := response.(map[string]interface{}) list := vmap[noun.Plural()].(*[]User) if list == nil || *list == nil { *list = make([]User, 0) } vmap[noun.Plural()] = list // placeholder: anything you want to do with the entity // list response return vmap, nil } } // wrap inner response with default protocol var prepareProtocol endpoint.Middleware = func(inner endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { v, err := inner(ctx, request) if err != nil { return } switch v.(type) { case map[string]interface{}: response = store.ExpandResponse(v.(map[string]interface{})) default: response = store.NewResponse(noun.Plural(), v) } return } } // generates response permission checker middleware checkPermBefore := func(permission string) endpoint.Middleware { return func(inner endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { m := perm.GetMux(ctx) err = m.Allow(ctx, permission, request) if err != nil { return } return inner(ctx, request) } } } // generates request permission checker middleware checkPermAfter := func(permission string) endpoint.Middleware { return func(inner endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { v, err := inner(ctx, request) if err != nil { return } m := perm.GetMux(ctx) err = m.Allow(ctx, permission, request, v) if err != nil { return } response = v return } } } // // ==== raw decode functions // decodeServiceIDReq := func(ctx context.Context, r *http.Request) (request *httpservice.Request, err error) { id := r.URL.Query().Get(":id") // will change cond := store.NewConds().Add("id", id) request = &httpservice.Request{ Request: r, Query: store.NewQuery().SetConds(cond), } return } decodeJSONEntity := func(ctx context.Context, r *http.Request) (entity *User, err error) { // allocate entity entity = &User{} // decode request dec := json.NewDecoder(r.Body) err = dec.Decode(entity) return } // // ==== httptransport.DecodeRequestFunc implementations // // decodeIDReq generically decoded :id field // (works with pat based URL routing, router specific) var decodeIDReq httptransport.DecodeRequestFunc = func(ctx context.Context, r *http.Request) (request interface{}, err error) { return decodeServiceIDReq(ctx, r) } // decodeListReq decode query for list endpoint var decodeListReq httptransport.DecodeRequestFunc = func(ctx context.Context, r *http.Request) (request interface{}, err error) { sReq := &httpservice.Request{ Request: r, Query: store.NewQuery(), } // parse sort parameter sortStr := r.FormValue("sorts") if sortStr != "" { sorts := strings.Split(sortStr, ",") for _, sort := range sorts { sReq.Query.Sort(sort) } } // parse paging request parameter offset, limit := func(r *http.Request) (o, l uint64) { ostr := r.FormValue("offset") lstr := r.FormValue("limit") if ostr != "" { if ot, err := strconv.ParseUint(ostr, 10, 64); err == nil { o = ot } } if lstr != "" { if lt, err := strconv.ParseUint(lstr, 10, 64); err == nil { l = lt } } return }(r) // retrieve sReq.Query.SetOffset(offset) sReq.Query.SetLimit(limit) request = sReq return } // decodeJSONReq returns a DecodeRequestFunc that decode request // into allocated memory structure var decodeJSONReq httptransport.DecodeRequestFunc = func(ctx context.Context, r *http.Request) (request interface{}, err error) { return decodeJSONEntity(ctx, r) } // decodeUpdate returns a DecodeRequestFunc that decode request var decodeUpdate httptransport.DecodeRequestFunc = func(ctx context.Context, r *http.Request) (request interface{}, err error) { sReq, err := decodeServiceIDReq(ctx, r) if err != nil { return } sReq.Payload, err = decodeJSONEntity(ctx, r) if err != nil { return } request = sReq return } // // ==== httpservce.Services // // define middleware chains of all RESTful endpoints handlers = make(map[string]*httpservice.Service) handlers["create"] = httpservice.NewJSONService( paths.Plural(), endpoints["create"]) handlers["create"].Weight = 1 handlers["create"].Methods = []string{"POST"} handlers["create"].DecodeFunc = decodeJSONReq handlers["create"].Middlewares.Add(httpservice.MWProtocol, prepareProtocol) handlers["create"].Middlewares.Add(httpservice.MWPrepare, prepareCreate) handlers["create"].Middlewares.Add(httpservice.MWInner, checkPermBefore("create "+noun.Singular())) handlers["retrieve"] = httpservice.NewJSONService( paths.Singular(), endpoints["retrieve"]) handlers["retrieve"].Methods = []string{"GET"} handlers["retrieve"].DecodeFunc = decodeIDReq handlers["retrieve"].Middlewares.Add(httpservice.MWProtocol, prepareProtocol) handlers["retrieve"].Middlewares.Add(httpservice.MWPrepare, prepareList) handlers["retrieve"].Middlewares.Add(httpservice.MWInner, checkPermAfter("retrieve "+noun.Singular())) handlers["update"] = httpservice.NewJSONService( paths.Singular(), endpoints["update"]) handlers["update"].Methods = []string{"PUT"} handlers["update"].DecodeFunc = decodeUpdate handlers["update"].Middlewares.Add(httpservice.MWProtocol, prepareProtocol) handlers["update"].Middlewares.Add(httpservice.MWPrepare, prepareUpdate) handlers["update"].Middlewares.Add(httpservice.MWInner, checkPermBefore("update "+noun.Singular())) handlers["list"] = httpservice.NewJSONService( paths.Plural(), endpoints["list"]) handlers["list"].Weight = 1 handlers["list"].Methods = []string{"GET"} handlers["list"].DecodeFunc = decodeListReq handlers["list"].Middlewares.Add(httpservice.MWProtocol, prepareProtocol) handlers["list"].Middlewares.Add(httpservice.MWPrepare, prepareList) handlers["list"].Middlewares.Add(httpservice.MWInner, checkPermAfter("list "+noun.Singular())) handlers["delete"] = httpservice.NewJSONService( paths.Singular(), endpoints["delete"]) handlers["delete"].Methods = []string{"DELETE"} handlers["delete"].DecodeFunc = decodeIDReq handlers["delete"].Middlewares.Add(httpservice.MWProtocol, prepareProtocol) handlers["delete"].Middlewares.Add(httpservice.MWInner, checkPermBefore("delete "+noun.Singular())) return }