vendor: Update vendoring for the exec client and server implementations

Signed-off-by: Jacek J. Łakis <jacek.lakis@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Jacek J. Łakis 2017-02-08 14:57:52 +01:00 committed by Samuel Ortiz
parent d25b88583f
commit bf51655a7b
2124 changed files with 809703 additions and 5 deletions

42
vendor/google.golang.org/appengine/aetest/doc.go generated vendored Normal file
View file

@ -0,0 +1,42 @@
/*
Package aetest provides an API for running dev_appserver for use in tests.
An example test file:
package foo_test
import (
"testing"
"google.golang.org/appengine/memcache"
"google.golang.org/appengine/aetest"
)
func TestFoo(t *testing.T) {
ctx, done, err := aetest.NewContext()
if err != nil {
t.Fatal(err)
}
defer done()
it := &memcache.Item{
Key: "some-key",
Value: []byte("some-value"),
}
err = memcache.Set(ctx, it)
if err != nil {
t.Fatalf("Set err: %v", err)
}
it, err = memcache.Get(ctx, "some-key")
if err != nil {
t.Fatalf("Get err: %v; want no error", err)
}
if g, w := string(it.Value), "some-value" ; g != w {
t.Errorf("retrieved Item.Value = %q, want %q", g, w)
}
}
The environment variable APPENGINE_DEV_APPSERVER specifies the location of the
dev_appserver.py executable to use. If unset, the system PATH is consulted.
*/
package aetest

51
vendor/google.golang.org/appengine/aetest/instance.go generated vendored Normal file
View file

@ -0,0 +1,51 @@
package aetest
import (
"io"
"net/http"
"golang.org/x/net/context"
"google.golang.org/appengine"
)
// Instance represents a running instance of the development API Server.
type Instance interface {
// Close kills the child api_server.py process, releasing its resources.
io.Closer
// NewRequest returns an *http.Request associated with this instance.
NewRequest(method, urlStr string, body io.Reader) (*http.Request, error)
}
// Options is used to specify options when creating an Instance.
type Options struct {
// AppID specifies the App ID to use during tests.
// By default, "testapp".
AppID string
// StronglyConsistentDatastore is whether the local datastore should be
// strongly consistent. This will diverge from production behaviour.
StronglyConsistentDatastore bool
}
// NewContext starts an instance of the development API server, and returns
// a context that will route all API calls to that server, as well as a
// closure that must be called when the Context is no longer required.
func NewContext() (context.Context, func(), error) {
inst, err := NewInstance(nil)
if err != nil {
return nil, nil, err
}
req, err := inst.NewRequest("GET", "/", nil)
if err != nil {
inst.Close()
return nil, nil, err
}
ctx := appengine.NewContext(req)
return ctx, func() {
inst.Close()
}, nil
}
// PrepareDevAppserver is a hook which, if set, will be called before the
// dev_appserver.py is started, each time it is started. If aetest.NewContext
// is invoked from the goapp test tool, this hook is unnecessary.
var PrepareDevAppserver func() error

View file

@ -0,0 +1,21 @@
// +build appengine
package aetest
import "appengine/aetest"
// NewInstance launches a running instance of api_server.py which can be used
// for multiple test Contexts that delegate all App Engine API calls to that
// instance.
// If opts is nil the default values are used.
func NewInstance(opts *Options) (Instance, error) {
aetest.PrepareDevAppserver = PrepareDevAppserver
var aeOpts *aetest.Options
if opts != nil {
aeOpts = &aetest.Options{
AppID: opts.AppID,
StronglyConsistentDatastore: opts.StronglyConsistentDatastore,
}
}
return aetest.NewInstance(aeOpts)
}

View file

@ -0,0 +1,116 @@
package aetest
import (
"os"
"testing"
"google.golang.org/appengine"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine/memcache"
"google.golang.org/appengine/user"
)
func TestBasicAPICalls(t *testing.T) {
// Only run the test if APPENGINE_DEV_APPSERVER is explicitly set.
if os.Getenv("APPENGINE_DEV_APPSERVER") == "" {
t.Skip("APPENGINE_DEV_APPSERVER not set")
}
inst, err := NewInstance(nil)
if err != nil {
t.Fatalf("NewInstance: %v", err)
}
defer inst.Close()
req, err := inst.NewRequest("GET", "http://example.com/page", nil)
if err != nil {
t.Fatalf("NewRequest: %v", err)
}
ctx := appengine.NewContext(req)
it := &memcache.Item{
Key: "some-key",
Value: []byte("some-value"),
}
err = memcache.Set(ctx, it)
if err != nil {
t.Fatalf("Set err: %v", err)
}
it, err = memcache.Get(ctx, "some-key")
if err != nil {
t.Fatalf("Get err: %v; want no error", err)
}
if g, w := string(it.Value), "some-value"; g != w {
t.Errorf("retrieved Item.Value = %q, want %q", g, w)
}
type Entity struct{ Value string }
e := &Entity{Value: "foo"}
k := datastore.NewIncompleteKey(ctx, "Entity", nil)
k, err = datastore.Put(ctx, k, e)
if err != nil {
t.Fatalf("datastore.Put: %v", err)
}
e = new(Entity)
if err := datastore.Get(ctx, k, e); err != nil {
t.Fatalf("datastore.Get: %v", err)
}
if g, w := e.Value, "foo"; g != w {
t.Errorf("retrieved Entity.Value = %q, want %q", g, w)
}
}
func TestContext(t *testing.T) {
// Only run the test if APPENGINE_DEV_APPSERVER is explicitly set.
if os.Getenv("APPENGINE_DEV_APPSERVER") == "" {
t.Skip("APPENGINE_DEV_APPSERVER not set")
}
// Check that the context methods work.
_, done, err := NewContext()
if err != nil {
t.Fatalf("NewContext: %v", err)
}
done()
}
func TestUsers(t *testing.T) {
// Only run the test if APPENGINE_DEV_APPSERVER is explicitly set.
if os.Getenv("APPENGINE_DEV_APPSERVER") == "" {
t.Skip("APPENGINE_DEV_APPSERVER not set")
}
inst, err := NewInstance(nil)
if err != nil {
t.Fatalf("NewInstance: %v", err)
}
defer inst.Close()
req, err := inst.NewRequest("GET", "http://example.com/page", nil)
if err != nil {
t.Fatalf("NewRequest: %v", err)
}
ctx := appengine.NewContext(req)
if user := user.Current(ctx); user != nil {
t.Errorf("user.Current initially %v, want nil", user)
}
u := &user.User{
Email: "gopher@example.com",
Admin: true,
}
Login(u, req)
if got := user.Current(ctx); got.Email != u.Email {
t.Errorf("user.Current: %v, want %v", got, u)
}
if admin := user.IsAdmin(ctx); !admin {
t.Errorf("user.IsAdmin: %t, want true", admin)
}
Logout(req)
if user := user.Current(ctx); user != nil {
t.Errorf("user.Current after logout %v, want nil", user)
}
}

View file

@ -0,0 +1,276 @@
// +build !appengine
package aetest
import (
"bufio"
"crypto/rand"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
"regexp"
"time"
"golang.org/x/net/context"
"google.golang.org/appengine/internal"
)
// NewInstance launches a running instance of api_server.py which can be used
// for multiple test Contexts that delegate all App Engine API calls to that
// instance.
// If opts is nil the default values are used.
func NewInstance(opts *Options) (Instance, error) {
i := &instance{
opts: opts,
appID: "testapp",
}
if opts != nil && opts.AppID != "" {
i.appID = opts.AppID
}
if err := i.startChild(); err != nil {
return nil, err
}
return i, nil
}
func newSessionID() string {
var buf [16]byte
io.ReadFull(rand.Reader, buf[:])
return fmt.Sprintf("%x", buf[:])
}
// instance implements the Instance interface.
type instance struct {
opts *Options
child *exec.Cmd
apiURL *url.URL // base URL of API HTTP server
adminURL string // base URL of admin HTTP server
appDir string
appID string
relFuncs []func() // funcs to release any associated contexts
}
// NewRequest returns an *http.Request associated with this instance.
func (i *instance) NewRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
req, err := http.NewRequest(method, urlStr, body)
if err != nil {
return nil, err
}
// Associate this request.
release := internal.RegisterTestRequest(req, i.apiURL, func(ctx context.Context) context.Context {
ctx = internal.WithAppIDOverride(ctx, "dev~"+i.appID)
return ctx
})
i.relFuncs = append(i.relFuncs, release)
return req, nil
}
// Close kills the child api_server.py process, releasing its resources.
func (i *instance) Close() (err error) {
for _, rel := range i.relFuncs {
rel()
}
i.relFuncs = nil
if i.child == nil {
return nil
}
defer func() {
i.child = nil
err1 := os.RemoveAll(i.appDir)
if err == nil {
err = err1
}
}()
if p := i.child.Process; p != nil {
errc := make(chan error, 1)
go func() {
errc <- i.child.Wait()
}()
// Call the quit handler on the admin server.
res, err := http.Get(i.adminURL + "/quit")
if err != nil {
p.Kill()
return fmt.Errorf("unable to call /quit handler: %v", err)
}
res.Body.Close()
select {
case <-time.After(15 * time.Second):
p.Kill()
return errors.New("timeout killing child process")
case err = <-errc:
// Do nothing.
}
}
return
}
func fileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
func findPython() (path string, err error) {
for _, name := range []string{"python2.7", "python"} {
path, err = exec.LookPath(name)
if err == nil {
return
}
}
return
}
func findDevAppserver() (string, error) {
if p := os.Getenv("APPENGINE_DEV_APPSERVER"); p != "" {
if fileExists(p) {
return p, nil
}
return "", fmt.Errorf("invalid APPENGINE_DEV_APPSERVER environment variable; path %q doesn't exist", p)
}
return exec.LookPath("dev_appserver.py")
}
var apiServerAddrRE = regexp.MustCompile(`Starting API server at: (\S+)`)
var adminServerAddrRE = regexp.MustCompile(`Starting admin server at: (\S+)`)
func (i *instance) startChild() (err error) {
if PrepareDevAppserver != nil {
if err := PrepareDevAppserver(); err != nil {
return err
}
}
python, err := findPython()
if err != nil {
return fmt.Errorf("Could not find python interpreter: %v", err)
}
devAppserver, err := findDevAppserver()
if err != nil {
return fmt.Errorf("Could not find dev_appserver.py: %v", err)
}
i.appDir, err = ioutil.TempDir("", "appengine-aetest")
if err != nil {
return err
}
defer func() {
if err != nil {
os.RemoveAll(i.appDir)
}
}()
err = os.Mkdir(filepath.Join(i.appDir, "app"), 0755)
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(i.appDir, "app", "app.yaml"), []byte(i.appYAML()), 0644)
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(i.appDir, "app", "stubapp.go"), []byte(appSource), 0644)
if err != nil {
return err
}
appserverArgs := []string{
devAppserver,
"--port=0",
"--api_port=0",
"--admin_port=0",
"--automatic_restart=false",
"--skip_sdk_update_check=true",
"--clear_datastore=true",
"--clear_search_indexes=true",
"--datastore_path", filepath.Join(i.appDir, "datastore"),
}
if i.opts != nil && i.opts.StronglyConsistentDatastore {
appserverArgs = append(appserverArgs, "--datastore_consistency_policy=consistent")
}
appserverArgs = append(appserverArgs, filepath.Join(i.appDir, "app"))
i.child = exec.Command(python,
appserverArgs...,
)
i.child.Stdout = os.Stdout
var stderr io.Reader
stderr, err = i.child.StderrPipe()
if err != nil {
return err
}
stderr = io.TeeReader(stderr, os.Stderr)
if err = i.child.Start(); err != nil {
return err
}
// Read stderr until we have read the URLs of the API server and admin interface.
errc := make(chan error, 1)
go func() {
s := bufio.NewScanner(stderr)
for s.Scan() {
if match := apiServerAddrRE.FindStringSubmatch(s.Text()); match != nil {
u, err := url.Parse(match[1])
if err != nil {
errc <- fmt.Errorf("failed to parse API URL %q: %v", match[1], err)
return
}
i.apiURL = u
}
if match := adminServerAddrRE.FindStringSubmatch(s.Text()); match != nil {
i.adminURL = match[1]
}
if i.adminURL != "" && i.apiURL != nil {
break
}
}
errc <- s.Err()
}()
select {
case <-time.After(15 * time.Second):
if p := i.child.Process; p != nil {
p.Kill()
}
return errors.New("timeout starting child process")
case err := <-errc:
if err != nil {
return fmt.Errorf("error reading child process stderr: %v", err)
}
}
if i.adminURL == "" {
return errors.New("unable to find admin server URL")
}
if i.apiURL == nil {
return errors.New("unable to find API server URL")
}
return nil
}
func (i *instance) appYAML() string {
return fmt.Sprintf(appYAMLTemplate, i.appID)
}
const appYAMLTemplate = `
application: %s
version: 1
runtime: go
api_version: go1
vm: true
handlers:
- url: /.*
script: _go_app
`
const appSource = `
package main
import "google.golang.org/appengine"
func main() { appengine.Main() }
`

36
vendor/google.golang.org/appengine/aetest/user.go generated vendored Normal file
View file

@ -0,0 +1,36 @@
package aetest
import (
"hash/crc32"
"net/http"
"strconv"
"google.golang.org/appengine/user"
)
// Login causes the provided Request to act as though issued by the given user.
func Login(u *user.User, req *http.Request) {
req.Header.Set("X-AppEngine-User-Email", u.Email)
id := u.ID
if id == "" {
id = strconv.Itoa(int(crc32.Checksum([]byte(u.Email), crc32.IEEETable)))
}
req.Header.Set("X-AppEngine-User-Id", id)
req.Header.Set("X-AppEngine-User-Federated-Identity", u.Email)
req.Header.Set("X-AppEngine-User-Federated-Provider", u.FederatedProvider)
if u.Admin {
req.Header.Set("X-AppEngine-User-Is-Admin", "1")
} else {
req.Header.Set("X-AppEngine-User-Is-Admin", "0")
}
}
// Logout causes the provided Request to act as though issued by a logged-out
// user.
func Logout(req *http.Request) {
req.Header.Del("X-AppEngine-User-Email")
req.Header.Del("X-AppEngine-User-Id")
req.Header.Del("X-AppEngine-User-Is-Admin")
req.Header.Del("X-AppEngine-User-Federated-Identity")
req.Header.Del("X-AppEngine-User-Federated-Provider")
}