Example #1
0
func TestNamespaceResetting(t *testing.T) {
	// These environment variables are necessary because *Query.Run will
	// call internal.FullyQualifiedAppID which checks these variables or falls
	// back to the Metadata service that is not available in tests.
	environ := []struct {
		key, value string
	}{
		{"GAE_LONG_APP_ID", "my-app-id"},
		{"GAE_PARTITION", "1"},
	}
	for _, v := range environ {
		old := os.Getenv(v.key)
		os.Setenv(v.key, v.value)
		v.value = old
	}
	defer func() { // Restore old environment after the test completes.
		for _, v := range environ {
			if v.value == "" {
				os.Unsetenv(v.key)
				continue
			}
			os.Setenv(v.key, v.value)
		}
	}()

	namec := make(chan *string, 1)
	c0 := aetesting.FakeSingleContext(t, "datastore_v3", "RunQuery", func(req *pb.Query, res *pb.QueryResult) error {
		namec <- req.NameSpace
		return fmt.Errorf("RPC error")
	})

	// Check that wrapping c0 in a namespace twice works correctly.
	c1, err := appengine.Namespace(c0, "A")
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}
	c2, err := appengine.Namespace(c1, "") // should act as the original context
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}

	q := NewQuery("SomeKind")

	q.Run(c0)
	if ns := <-namec; ns != nil {
		t.Errorf(`RunQuery with c0: ns = %q, want nil`, *ns)
	}

	q.Run(c1)
	if ns := <-namec; ns == nil {
		t.Error(`RunQuery with c1: ns = nil, want "A"`)
	} else if *ns != "A" {
		t.Errorf(`RunQuery with c1: ns = %q, want "A"`, *ns)
	}

	q.Run(c2)
	if ns := <-namec; ns != nil {
		t.Errorf(`RunQuery with c2: ns = %q, want nil`, *ns)
	}
}
Example #2
0
func TestNamespaceResetting(t *testing.T) {
	namec := make(chan *string, 1)
	c0 := aetesting.FakeSingleContext(t, "memcache", "Get", func(req *pb.MemcacheGetRequest, res *pb.MemcacheGetResponse) error {
		namec <- req.NameSpace
		return errRPC
	})

	// Check that wrapping c0 in a namespace twice works correctly.
	c1, err := appengine.Namespace(c0, "A")
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}
	c2, err := appengine.Namespace(c1, "") // should act as the original context
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}

	Get(c0, "key")
	if ns := <-namec; ns != nil {
		t.Errorf(`Get with c0: ns = %q, want nil`, *ns)
	}

	Get(c1, "key")
	if ns := <-namec; ns == nil {
		t.Error(`Get with c1: ns = nil, want "A"`)
	} else if *ns != "A" {
		t.Errorf(`Get with c1: ns = %q, want "A"`, *ns)
	}

	Get(c2, "key")
	if ns := <-namec; ns != nil {
		t.Errorf(`Get with c2: ns = %q, want nil`, *ns)
	}
}
Example #3
0
func TestNamespaceResetting(t *testing.T) {
	var nsField *string
	c := aetesting.FakeSingleContext(t, "memcache", "Get", func(req *pb.MemcacheGetRequest, res *pb.MemcacheGetResponse) error {
		nsField = req.NameSpace
		return errRPC
	})

	// Check that wrapping c in a namespace twice works correctly.
	nc, err := appengine.Namespace(c, "A")
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}
	c0, err := appengine.Namespace(nc, "") // should act as the original context
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}

	Get(c, "key")
	if nsField != nil {
		t.Fatalf("Get with c yielded %q", *nsField)
	}
	Get(nc, "key")
	if nsField == nil || *nsField != "A" {
		t.Fatalf("Get with nc yielded %v", nsField)
	}
	Get(c0, "key")
	if nsField != nil && *nsField != "" {
		t.Fatalf("Get with c0 yielded %q", *nsField)
	}
}
func createInNamespace(c context.Context, namespace string) {
	ns, _ := appengine.Namespace(c, namespace)
	p := new(pet)
	p.Value = 1
	k := datastore.NewKey(ns, "pet", "", 1, nil)
	datastore.Put(ns, k, p)
}
Example #5
0
// CleanupDatastore is to remove all data in datastore
func CleanupDatastore(ctx context.Context, namespaces ...string) error {
	var dummy []interface{}
	logger := wcg.NewLogger(nil)
	logger.Debugf("[Fixture] --------- CleanupDatastore ---------")
	namespaceList := append(namespaces, "")
	for _, ns := range namespaceList {
		logger.Debugf("[Fixture] Cleanup: ns=%q", ns)
		var _ctx = ctx
		if ns != "" {
			_ctx, _ = appengine.Namespace(_ctx, ns)
		}
		err := wcg.RetryUntil(func() error {
			var keys []*datastore.Key
			var err error
			if keys, err = datastore.NewQuery("").KeysOnly().GetAll(_ctx, dummy); err != nil {
				return err
			}
			if err := datastore.DeleteMulti(_ctx, keys); err != nil {
				return err
			}
			count, _ := datastore.NewQuery("").KeysOnly().Count(_ctx)
			if count == 0 {
				return nil
			}
			return fmt.Errorf("Still have %d keys.", count)
		}, 10*time.Second, 100*time.Millisecond)
		if err != nil {
			return err
		}
	}
	return nil
}
Example #6
0
// NewKey returns a new *datastore.Key for `kind`
func (kind *Kind) NewKey(req *wcg.Request, key string, parent *datastore.Key) *datastore.Key {
	ctx, err := appengine.Namespace(gae.NewContext(req), kind.Namespace)
	if err != nil {
		panic(err)
	}
	return datastore.NewKey(ctx, string(kind.Name), key, 0, parent)
}
Example #7
0
func namespace(ctx context.Context) context.Context {
	// assumes the user is logged in.
	ctx, err := appengine.Namespace(ctx, user.Current(ctx).ID)
	if err != nil {
		// ...
	}
	return ctx
}
Example #8
0
// TestGetNamespacedKey ensures issue https://goo.gl/rXU8nK is fixed so that
// memcache uses the namespace from the key instead of the context.
func TestGetNamespacedKey(t *testing.T) {
	c, closeFunc := NewContext(t)
	defer closeFunc()

	const intVal = int64(12)
	type testEntity struct {
		IntVal int64
	}

	namespacedCtx, err := appengine.Namespace(c, "keyNamespace")
	if err != nil {
		t.Fatal(err)
	}

	key := datastore.NewKey(c, "Entity", "", 1, nil)
	namespacedKey := datastore.NewKey(namespacedCtx,
		"Entity", "", key.IntID(), nil)
	entity := &testEntity{intVal}

	if namespacedKey, err = nds.Put(c, namespacedKey, entity); err != nil {
		t.Fatal(err)
	}

	// Prime cache.
	if err := nds.Get(namespacedCtx, namespacedKey, &testEntity{}); err != nil {
		t.Fatal(err)
	}

	// Ensure that we get a value back from the cache by checking if the
	// datastore is called at all.
	entityFromCache := true
	nds.SetDatastoreGetMulti(func(c context.Context,
		keys []*datastore.Key, vals interface{}) error {
		if len(keys) != 0 {
			entityFromCache = false
		}
		return nil
	})
	if err := nds.Get(c, namespacedKey, &testEntity{}); err != nil {
		t.Fatal(err)
	}
	nds.SetDatastoreGetMulti(datastore.GetMulti)

	if !entityFromCache {
		t.Fatal("entity not obtained from cache")
	}

	if err := nds.Delete(namespacedCtx, namespacedKey); err != nil {
		t.Fatal(err)
	}

	entity = &testEntity{}
	if err := nds.Get(c, namespacedKey, entity); err == nil {
		t.Fatalf("expected no such entity error but got %+v", entity)
	} else if err != datastore.ErrNoSuchEntity {
		t.Fatal(err)
	}
}
Example #9
0
// Namespace set the namespace
func (d *Driver) Namespace(namespace string) *Driver {
	var err error
	d.ctx, err = appengine.Namespace(d.ctx, namespace)
	d.namespace = namespace
	if err != nil {
		panic(err)
	}
	return d
}
Example #10
0
func loadJsonToDatastore(ctx context.Context, pkey *datastore.Key, data map[string]interface{}, logger wcg.Logger) error {
	var kind string
	var ns string
	var keyval interface{}
	var key *datastore.Key
	var ok bool
	var err error
	if _, ok = data["_kind"]; !ok {
		return fmt.Errorf("Missing key `_kind`")
	}
	kind = data["_kind"].(string)
	if keyval, ok = data["_key"]; !ok {
		return fmt.Errorf("Missing key `_key`")
	}
	if _, ok = data["_ns"]; ok {
		ns = data["_ns"].(string)
		ctx, err = appengine.Namespace(ctx, ns)
		if err != nil {
			return fmt.Errorf("Could not change the namespace of %q, check _ns value: ", ns, err)
		}
	}

	switch keyval.(type) {
	case int64:
		key = datastore.NewKey(ctx, kind, "", keyval.(int64), pkey)
	case string:
		key = datastore.NewKey(ctx, kind, keyval.(string), 0, pkey)
	default:
		return fmt.Errorf("Invalid `_key` type.")
	}
	if _, err := datastore.Put(ctx, key, jsonSaver(data)); err != nil {
		return err
	}
	// Check the data is actually stored.
	if err := wcg.RetryUntil(func() error {
		var v jsonSaver
		if err := datastore.Get(ctx, key, &v); err != nil {
			return fmt.Errorf(
				"fixture is not synched on '%s:[%s]': internal error?(%v) on ",
				kind, keyval, err,
			)
		}
		return nil
	}, 5*time.Second, 500*time.Millisecond); err != nil {
		return err
	}

	logger.Debugf("[Fixture] %s%s -- %v", ns, key, data)
	if children, ok := data["_children"]; ok {
		for _, v := range children.([]interface{}) {
			if err := loadJsonToDatastore(ctx, key, v.(map[string]interface{}), logger); err != nil {
				return err
			}
		}
	}
	return nil
}
Example #11
0
func storeContext(ctx context.Context) context.Context {
	ctx, err := appengine.Namespace(ctx, Namespace)
	if err != nil {
		// NOTE: appengine.Namespace will only return an error if
		// the passed namespace name itself is invalid.
		panic(err)
	}
	return ctx
}
Example #12
0
func (g giImpl) Namespace(namespace string) (context.Context, error) {
	c, err := appengine.Namespace(g, namespace)
	if err != nil {
		return c, err
	}
	pc := *getProbeCache(g)
	pc.namespace = namespace
	return withProbeCache(c, &pc), nil
}
Example #13
0
// cachedCerts fetches public certificates info from DefaultCertURI and
// caches it for the duration specified in Age header of a response.
func cachedCerts(c context.Context) (*certsList, error) {
	namespacedContext, err := appengine.Namespace(c, certNamespace)
	if err != nil {
		return nil, err
	}

	var certs *certsList

	_, err = memcache.JSON.Get(namespacedContext, DefaultCertURI, &certs)
	if err == nil {
		return certs, nil
	}

	// Cache miss or server error.
	// If any error other than cache miss, it's proably not a good time
	// to use memcache.
	var cacheResults = err == memcache.ErrCacheMiss
	if !cacheResults {
		log.Debugf(c, "%s", err.Error())
	}

	log.Debugf(c, "Fetching provider certs from: %s", DefaultCertURI)
	resp, err := newHTTPClient(c).Get(DefaultCertURI)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, errors.New("Could not reach Cert URI or bad response.")
	}

	certBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(certBytes, &certs)
	if err != nil {
		return nil, err
	}

	if cacheResults {
		expiration := certExpirationTime(resp.Header)
		if expiration > 0 {
			item := &memcache.Item{
				Key:        DefaultCertURI,
				Value:      certBytes,
				Expiration: expiration,
			}
			err = memcache.Set(namespacedContext, item)
			if err != nil {
				log.Errorf(c, "Error adding Certs to memcache: %v", err)
			}
		}
	}
	return certs, nil
}
Example #14
0
func (g giImpl) Namespace(namespace string) (context.Context, error) {
	aeCtx, err := appengine.Namespace(g.aeCtx, namespace)
	if err != nil {
		return g.usrCtx, err
	}
	usrCtx := context.WithValue(g.usrCtx, prodContextKey, aeCtx)
	pc := *getProbeCache(usrCtx)
	pc.namespace = namespace
	return withProbeCache(usrCtx, &pc), nil
}
Example #15
0
// this will generate some random data
// on production this will create 96,768 entitied
func createInNamespace(c context.Context, namespace string) {
	c, _ = appengine.Namespace(c, namespace)

	for m := 1; m <= 12; m++ {
		for d := 1; d <= 28; d++ {
			taken := time.Date(2015, time.Month(m), d, 0, 0, 0, 0, time.UTC)
			generateRandomFn.Call(c, taken)
		}
	}
}
Example #16
0
// Stat returns the BlobInfo for a provided blobKey. If no blob was found for
// that key, Stat returns datastore.ErrNoSuchEntity.
func Stat(c context.Context, blobKey appengine.BlobKey) (*BlobInfo, error) {
	c, _ = appengine.Namespace(c, "") // Blobstore is always in the empty string namespace
	dskey := datastore.NewKey(c, blobInfoKind, string(blobKey), 0, nil)
	bi := &BlobInfo{
		BlobKey: blobKey,
	}
	if err := datastore.Get(c, dskey, bi); err != nil && !isErrFieldMismatch(err) {
		return nil, err
	}
	return bi, nil
}
Example #17
0
func TestDatastoreFixture(t *testing.T) {
	filepath := mkTempfile(`[{
    "_kind": "FixtureKind",
    "_key": "key1",
    "IntValue": 10,
    "FloatValue": 2.4,
    "BoolValue": true,
    "StringValue": "foobar",
    "BytesValue": "[]bytesfoobar",
    "DateTimeValue": "2014-01-02T14:02:50Z",
    "DateValue": "2014-01-02",
    "Slice": ["a", "b", "c"],
    "Struct": {
      "Foo": "bar"
    }
  },{
    "_kind": "FixtureKind",
    "_key": "key1",
    "_ns": "ns1",
    "StringValue": "withns1"
  }
]`)

	assert := wcg.NewAssert(t)
	var fk FixtureKind
	assert.Nil(DatastoreFixture(ts.Context, filepath, nil), "DatastoreFixture")

	key := datastore.NewKey(ts.Context, "FixtureKind", "key1", 0, nil)

	wcg.NewLogger(nil).Infof("GET: %s", key)
	assert.Nil(datastore.Get(ts.Context, key, &fk), "datastore.Get('key1') ")

	assert.EqInt(10, fk.IntValue, "IntValue should be 10")
	assert.EqFloat32(2.4, fk.FloatValue, "FloatValue should be 2.4")
	assert.EqStr("foobar", fk.StringValue, "StringValue should be 'foobar'")
	assert.EqStr("bytesfoobar", string(fk.BytesValue), "BytesValue should be 'foobar'")
	assert.EqInt(3, len(fk.Slice), "len(Slice) should be 3")
	assert.EqStr("a", string(fk.Slice[0]), "Slice[0] should be 'a'")
	assert.EqStr("b", string(fk.Slice[1]), "Slice[0] should be 'a'")
	assert.EqStr("c", string(fk.Slice[2]), "Slice[0] should be 'a'")

	assert.EqTime(time.Date(2014, 01, 02, 14, 02, 50, 0, time.UTC), fk.DateTimeValue, "DateTimeValue should be 2014-01-02T14:02:50Z")
	assert.EqTime(time.Date(2014, 01, 02, 0, 0, 0, 0, time.UTC), fk.DateValue, "DateTimeValue should be 2014-01-02T00:00:00Z")
	assert.EqStr("bar", string(fk.Struct.Foo), "Struct.Foo should be 'bar'")

	// namespace
	ns1, _ := appengine.Namespace(ts.Context, "ns1")
	key = datastore.NewKey(ns1, "FixtureKind", "key1", 0, nil)
	assert.Nil(datastore.Get(ns1, key, &fk), "datastore.Get('key1') /w ns1")
	assert.EqStr("withns1", fk.StringValue, "StringValue should be 'withns1'")
}
Example #18
0
// AEContextNoTxn retrieves the raw "google.golang.org/appengine" compatible
// Context that's not part of a transaction.
func AEContextNoTxn(c context.Context) context.Context {
	aeCtx, _ := c.Value(prodContextNoTxnKey).(context.Context)
	if aeCtx == nil {
		return nil
	}
	aeCtx, err := appengine.Namespace(aeCtx, info.Get(c).GetNamespace())
	if err != nil {
		panic(err)
	}
	if deadline, ok := c.Deadline(); ok {
		aeCtx, _ = context.WithDeadline(aeCtx, deadline)
	}
	return aeCtx
}
Example #19
0
func TestNamespaceResetting(t *testing.T) {
	namec := make(chan *string, 1)
	c0 := aetesting.FakeSingleContext(t, "search", "IndexDocument", func(req *pb.IndexDocumentRequest, res *pb.IndexDocumentResponse) error {
		namec <- req.Params.IndexSpec.Namespace
		return fmt.Errorf("RPC error")
	})

	// Check that wrapping c0 in a namespace twice works correctly.
	c1, err := appengine.Namespace(c0, "A")
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}
	c2, err := appengine.Namespace(c1, "") // should act as the original context
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}

	i := (&Index{})

	i.Put(c0, "something", &searchDoc)
	if ns := <-namec; ns != nil {
		t.Errorf(`Put with c0: ns = %q, want nil`, *ns)
	}

	i.Put(c1, "something", &searchDoc)
	if ns := <-namec; ns == nil {
		t.Error(`Put with c1: ns = nil, want "A"`)
	} else if *ns != "A" {
		t.Errorf(`Put with c1: ns = %q, want "A"`, *ns)
	}

	i.Put(c2, "something", &searchDoc)
	if ns := <-namec; ns != nil {
		t.Errorf(`Put with c2: ns = %q, want nil`, *ns)
	}
}
Example #20
0
func TestNamespaceResetting(t *testing.T) {
	namec := make(chan *string, 1)
	c0 := aetesting.FakeSingleContext(t, "datastore_v3", "RunQuery", func(req *pb.Query, res *pb.QueryResult) error {
		namec <- req.NameSpace
		return fmt.Errorf("RPC error")
	})

	// Check that wrapping c0 in a namespace twice works correctly.
	c1, err := appengine.Namespace(c0, "A")
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}
	c2, err := appengine.Namespace(c1, "") // should act as the original context
	if err != nil {
		t.Fatalf("appengine.Namespace: %v", err)
	}

	q := NewQuery("SomeKind")

	q.Run(c0)
	if ns := <-namec; ns != nil {
		t.Errorf(`RunQuery with c0: ns = %q, want nil`, *ns)
	}

	q.Run(c1)
	if ns := <-namec; ns == nil {
		t.Error(`RunQuery with c1: ns = nil, want "A"`)
	} else if *ns != "A" {
		t.Errorf(`RunQuery with c1: ns = %q, want "A"`, *ns)
	}

	q.Run(c2)
	if ns := <-namec; ns != nil {
		t.Errorf(`RunQuery with c2: ns = %q, want nil`, *ns)
	}
}
Example #21
0
// TestClearNamespacedLocks tests to make sure that locks are cleared when
// RunInTransaction is using a namespace.
func TestClearNamespacedLocks(t *testing.T) {
	c, closeFunc := NewContext(t, nil)
	defer closeFunc()

	c, err := appengine.Namespace(c, "testnamespace")
	if err != nil {
		t.Fatal(err)
	}

	type testEntity struct {
		Val int
	}

	key := datastore.NewKey(c, "TestEntity", "", 1, nil)

	// Prime cache.
	if err := nds.Get(c, key, &testEntity{}); err == nil {
		t.Fatal("expected no such entity")
	} else if err != datastore.ErrNoSuchEntity {
		t.Fatal(err)
	}

	if err := nds.RunInTransaction(c, func(tc context.Context) error {

		if err := nds.Get(tc, key, &testEntity{}); err == nil {
			return errors.New("expected no such entity")
		} else if err != datastore.ErrNoSuchEntity {
			return err
		}

		if _, err := nds.Put(tc, key, &testEntity{3}); err != nil {
			return err
		}
		return nil
	}, nil); err != nil {
		t.Fatal(err)
	}

	entity := &testEntity{}
	if err := nds.Get(c, key, entity); err != nil {
		t.Fatal(err)
	}

	if entity.Val != 3 {
		t.Fatal("incorrect val")
	}
}
Example #22
0
func TestVerifySignedJWT(t *testing.T) {
	r, _, closer := newTestRequest(t, "GET", "/", nil)
	defer closer()
	nc, err := appengine.Namespace(appengine.NewContext(r), certNamespace)
	if err != nil {
		t.Fatal(err)
	}

	item := &memcache.Item{Key: DefaultCertURI, Value: []byte(googCerts)}
	if err := memcache.Set(nc, item); err != nil {
		t.Fatal(err)
	}

	tts := []struct {
		token string
		now   time.Time
		want  *signedJWT
	}{
		{jwtValidTokenString, jwtValidTokenTime, &jwtValidTokenObject},
		{jwtValidTokenString, jwtValidTokenTime.Add(time.Hour * 24), nil},
		{jwtValidTokenString, jwtValidTokenTime.Add(-time.Hour * 24), nil},
		{jwtInvalidKeyToken, jwtValidTokenTime, nil},
		{jwtInvalidAlgToken, jwtValidTokenTime, nil},
		{"invalid.token", jwtValidTokenTime, nil},
		{"another.invalid.token", jwtValidTokenTime, nil},
	}

	ec := NewContext(r)

	for i, tt := range tts {
		jwt, err := verifySignedJWT(ec, tt.token, tt.now.Unix())
		switch {
		case err != nil && tt.want != nil:
			t.Errorf("%d: verifySignedJWT(%q, %d) = %v; want %#v",
				i, tt.token, tt.now.Unix(), err, tt.want)
		case err == nil && tt.want == nil:
			t.Errorf("%d: verifySignedJWT(%q, %d) = %#v; want error",
				i, tt.token, tt.now.Unix(), jwt)
		case err == nil && tt.want != nil:
			if !reflect.DeepEqual(jwt, tt.want) {
				t.Errorf("%d: verifySignedJWT(%q, %d) = %v; want %#v",
					i, tt.token, tt.now.Unix(), jwt, tt.want)
			}
		}
	}
}
Example #23
0
func TestCachedCertsCacheHit(t *testing.T) {
	origTransport := httpTransportFactory
	defer func() { httpTransportFactory = origTransport }()
	httpTransportFactory = func(c context.Context) http.RoundTripper {
		return newTestRoundTripper()
	}

	req, _, closer := newTestRequest(t, "GET", "/", nil)
	defer closer()
	nc, err := appengine.Namespace(appengine.NewContext(req), certNamespace)
	if err != nil {
		t.Fatal(err)
	}

	tts := []struct {
		cacheValue string
		want       *certsList
	}{
		{"", nil},
		{"{}", &certsList{}},
		{`{"keyvalues": [{}]}`, &certsList{[]*certInfo{{}}}},
		{`{"keyvalues": [
	    	{"algorithm": "RS256",
	    	 "exponent": "123",
	    	 "keyid": "some-id",
	    	 "modulus": "123"} ]}`,
			&certsList{[]*certInfo{{"RS256", "123", "some-id", "123"}}}},
	}
	ec := NewContext(req)
	for i, tt := range tts {
		item := &memcache.Item{Key: DefaultCertURI, Value: []byte(tt.cacheValue)}
		if err := memcache.Set(nc, item); err != nil {
			t.Fatal(err)
		}
		out, err := cachedCerts(ec)
		switch {
		case err != nil && tt.want != nil:
			t.Errorf("%d: cachedCerts() error %v", i, err)
		case err == nil && tt.want == nil:
			t.Errorf("%d: cachedCerts() = %#v; want error", i, out)
		case err == nil && tt.want != nil && !reflect.DeepEqual(out, tt.want):
			t.Errorf("cachedCerts() = %#+v (%T); want %#+v (%T)",
				out, out, tt.want, tt.want)
		}
	}
}
Example #24
0
// dsF2R (DS fake-to-real) converts a DSKey back to an SDK *Key.
func dsF2R(aeCtx context.Context, k *ds.Key) (*datastore.Key, error) {
	if k == nil {
		return nil, nil
	}

	// drop aid.
	_, ns, toks := k.Split()
	err := error(nil)
	aeCtx, err = appengine.Namespace(aeCtx, ns)
	if err != nil {
		return nil, err
	}

	ret := datastore.NewKey(aeCtx, toks[0].Kind, toks[0].StringID, toks[0].IntID, nil)
	for _, t := range toks[1:] {
		ret = datastore.NewKey(aeCtx, t.Kind, t.StringID, t.IntID, ret)
	}

	return ret, nil
}
func someHandler(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	err := incrementCounter(ctx, "SomeRequest")
	if err != nil {
		// ... handle err
	}

	// temporarily use a new namespace
	{
		ctx, err := appengine.Namespace(ctx, "-global-")
		if err != nil {
			// ... handle err
		}
		err = incrementCounter(ctx, "SomeRequest")
		if err != nil {
			// ... handle err
		}
	}

	io.WriteString(w, "Updated counters.\n")
}
func someRequest(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)

	// Perform asynchronous requests to update counter.
	// (missing error handling here.)
	t := taskqueue.NewPOSTTask("/_ah/counter", map[string][]string{
		"counter_name": {"someRequest"},
	})

	taskqueue.Add(ctx, t, "")

	// temporarily use a new namespace
	{
		ctx, err := appengine.Namespace(ctx, "-global-")
		if err != nil {
			// ... handle err
		}
		taskqueue.Add(ctx, t, "")
	}

	io.WriteString(w, "Counters will be updated.\n")
}
Example #27
0
func memcacheContext(c context.Context) (context.Context, error) {
	return appengine.Namespace(c, memcacheNamespace)
}
Example #28
0
func TestCachedCertsCacheMiss(t *testing.T) {
	rt := newTestRoundTripper()
	origTransport := httpTransportFactory
	defer func() { httpTransportFactory = origTransport }()
	httpTransportFactory = func(c context.Context) http.RoundTripper {
		return rt
	}

	req, _, closer := newTestRequest(t, "GET", "/", nil)
	defer closer()
	nc, err := appengine.Namespace(appengine.NewContext(req), certNamespace)
	if err != nil {
		t.Fatal(err)
	}
	ec := NewContext(req)

	tts := []*struct {
		respStatus                     int
		respContent, cacheControl, age string
		want                           *certsList
		shouldCache                    bool
	}{
		{200, `{"keyvalues":null}`, "max-age=3600", "600", &certsList{}, true},
		{-1, "", "", "", nil, false},
		{400, "", "", "", nil, false},
		{200, `{"keyvalues":null}`, "", "", &certsList{}, false},
	}

	for i, tt := range tts {
		if tt.respStatus > 0 {
			resp := &http.Response{
				Status:     fmt.Sprintf("%d", tt.respStatus),
				StatusCode: tt.respStatus,
				Body:       ioutil.NopCloser(strings.NewReader(tt.respContent)),
				Header:     make(http.Header),
			}
			resp.Header.Set("cache-control", tt.cacheControl)
			resp.Header.Set("age", tt.age)
			rt.Add(resp)
		}
		memcache.Delete(nc, DefaultCertURI)

		out, err := cachedCerts(ec)
		switch {
		case err != nil && tt.want != nil:
			t.Errorf("%d: cachedCerts() = %v", i, err)
		case err == nil && tt.want == nil:
			t.Errorf("%d: cachedCerts() = %#v; want error", i, out)
		default:
			if !reflect.DeepEqual(out, tt.want) {
				t.Errorf("%d: cachedCerts() = %#v; want %#v", i, out, tt.want)
			}
			if !tt.shouldCache {
				continue
			}
			item, err := memcache.Get(nc, DefaultCertURI)
			if err != nil {
				t.Errorf("%d: memcache.Get(%q) = %v", i, DefaultCertURI, err)
				continue
			}
			cert := string(item.Value)
			if tt.respContent != cert {
				t.Errorf("%d: memcache.Get(%q) = %q; want %q",
					i, DefaultCertURI, cert, tt.respContent)
			}
		}
	}
}
Example #29
0
func TestCurrentUser(t *testing.T) {
	const (
		// Default values from user_service_stub.py of dev_appserver2.
		clientID    = "123456789.apps.googleusercontent.com"
		bearerEmail = "*****@*****.**"
		validScope  = "valid.scope"
	)

	inst, err := aetest.NewInstance(nil)
	if err != nil {
		t.Fatalf("failed to create instance: %v", err)
	}
	defer inst.Close()

	req, err := inst.NewRequest("GET", "/", nil)
	nc, err := appengine.Namespace(appengine.NewContext(req), certNamespace)
	if err != nil {
		t.Fatal(err)
	}
	// googCerts are provided in jwt_test.go
	item := &memcache.Item{Key: DefaultCertURI, Value: []byte(googCerts)}
	if err := memcache.Set(nc, item); err != nil {
		t.Fatal(err)
	}

	origCurrentUTC := currentUTC
	defer func() { currentUTC = origCurrentUTC }()
	currentUTC = func() time.Time {
		return jwtValidTokenTime
	}

	jwtStr, jwt := jwtValidTokenString, jwtValidTokenObject
	tts := []struct {
		token                        string
		scopes, audiences, clientIDs []string
		wantEmail                    string
	}{
		// success
		{jwtStr, []string{EmailScope}, []string{jwt.Audience}, []string{jwt.ClientID}, jwt.Email},
		{"ya29.token", []string{EmailScope}, []string{clientID}, []string{clientID}, bearerEmail},
		{"ya29.token", []string{EmailScope, validScope}, []string{clientID}, []string{clientID}, bearerEmail},
		{"1/token", []string{validScope}, []string{clientID}, []string{clientID}, bearerEmail},

		// failure
		{jwtStr, []string{EmailScope}, []string{"other-client"}, []string{"other-client"}, ""},
		{"some.invalid.jwt", []string{EmailScope}, []string{jwt.Audience}, []string{jwt.ClientID}, ""},
		{"", []string{validScope}, []string{clientID}, []string{clientID}, ""},
		// The following test is commented for now because default implementation
		// of UserServiceStub in dev_appserver2 allows any scope.
		// TODO: figure out how to test this.
		//{"ya29.invalid", []string{"invalid.scope"}, []string{clientID}, []string{clientID}, ""},

		{"doesn't matter", nil, []string{clientID}, []string{clientID}, ""},
		{"doesn't matter", []string{EmailScope}, nil, []string{clientID}, ""},
		{"doesn't matter", []string{EmailScope}, []string{clientID}, nil, ""},
	}

	for i, tt := range tts {
		r, err := inst.NewRequest("GET", "/", nil)
		c := newContext(r, cachingAuthenticatorFactory)
		if tt.token != "" {
			r.Header.Set("authorization", "oauth "+tt.token)
		}

		user, err := CurrentUser(c, tt.scopes, tt.audiences, tt.clientIDs)

		switch {
		case tt.wantEmail == "" && err == nil:
			t.Errorf("%d: CurrentUser(%v, %v, %v) = %v; want error",
				i, tt.scopes, tt.audiences, tt.clientIDs, user)
		case tt.wantEmail != "" && user == nil:
			t.Errorf("%d: CurrentUser(%v, %v, %v) = %v; want email = %q",
				i, tt.scopes, tt.audiences, tt.clientIDs, err, tt.wantEmail)
		case tt.wantEmail != "" && tt.wantEmail != user.Email:
			t.Errorf("%d: CurrentUser(%v, %v, %v) = %v; want email = %q",
				i, tt.scopes, tt.audiences, tt.clientIDs, user, tt.wantEmail)
		}
	}
}
/*
Splits an arbitrary datastore query. This is used to shard queries within a namespace.
This is done in one of two ways:

1. If the query contains an inequality filter, the lower and upper bounds are determined (this
may involve querying the datastore) then the range is split naively. This works well when the
property that is being queried on is uniformly distributed.

2. If the query does not contain an inequality filter. The query will be partitioned by the
entity key. This is done by using the "__scatter__" property to get a random sample of the
keyspace and partitioning based on that. This can result in a poor distribution if there are
equality filters on the query that bias the selection with respect to certain regions of
keyspace.

The following clauses are not supported by this class: An inequality filter of unsupported type.
Filters that are incompatible with datastore cursors such as: Combining multiple clauses with an
OR. A filter on a value being NOT_EQUAL.

TODO: add better explanation of the various splitting scenarios
*/
func (q *Query) split(c context.Context, shards, oversampling int) ([]*Query, error) {
	// NOTE: at this point the query will have a single namespace for the one we're processing
	// all the datastore operations we do for the query should be within that namespace
	c, _ = appengine.Namespace(c, q.namespaces[0])

	equality, pr, err := q.toEqualityListAndRange()
	if err != nil {
		return nil, err
	}

	var propertyRanges []*propertyRange

	switch {
	case shards == 1:
		// no splitting required
		log.Debugf(c, "no split")
		propertyRanges = []*propertyRange{pr}
	case pr.empty():
		// no property range, shard on key space only
		log.Debugf(c, "shard on keyspace")
		propertyRanges, err = q.getScatterSplitPoints(c, shards, oversampling, equality)
		if err != nil {
			return nil, err
		}
	default:
		log.Debugf(c, "shard on property range")
		if pr.lower == nil {
			// set lower filter predicate from datastore so we work out a meaningful range
			v, err := q.getExtremePropertyValue(c, equality, pr.upper.FieldName, Ascending)
			if err != nil {
				return nil, err
			}
			pr.lower = &filter{pr.upper.FieldName, greaterEq, v}
			log.Debugf(c, "got lower %s", pr.lower)
		}
		// set upper filter predicate from datastore so we work out a meaningful range
		if pr.upper == nil {
			v, err := q.getExtremePropertyValue(c, equality, pr.upper.FieldName, Descending)
			if err != nil {
				return nil, err
			}
			pr.upper = &filter{pr.upper.FieldName, lessEq, v}
			log.Debugf(c, "got upper %s", pr.upper)
		}

		propertyRanges = pr.split(shards)
	}

	// build query for the property ranges
	results := []*Query{}
	for _, pr := range propertyRanges {
		query := NewQuery(q.kind)
		query.selection = q.selection
		query.namespaces = q.namespaces
		for _, f := range equality {
			query.filter = append(query.filter, f)
		}
		if pr.lower != nil {
			query.filter = append(query.filter, *pr.lower)
		}
		if pr.upper != nil {
			query.filter = append(query.filter, *pr.upper)
		}

		results = append(results, query)
	}

	return results, nil
}