Example #1
0
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")
	}
}
Example #2
0
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")
	}
}
Example #3
0
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())
	}

}
Example #4
0
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())
	}

}
Example #5
0
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)
	}
}
Example #6
0
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])
	}
}
Example #7
0
// 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
}
Example #8
0
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)
	}
}
Example #9
0
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
}