diff --git a/context.go b/context.go index 14eb9ff..60b4c83 100644 --- a/context.go +++ b/context.go @@ -12,7 +12,6 @@ import ( "bufio" "bytes" "errors" - "flag" "fmt" "hash/crc32" "io" @@ -26,19 +25,21 @@ import ( "runtime" "strconv" "syscall" - "testing" "time" - "code.google.com/p/goprotobuf/proto" + "github.com/golang/protobuf/proto" - "appengine" - "appengine/user" - "appengine_internal" - basepb "appengine_internal/base" + "golang.org/x/net/context" + "google.golang.org/appengine/user" + "google.golang.org/appengine/internal" + basepb "google.golang.org/appengine/internal/base" ) +// Trim out extraneous noise from logs +var logTrimRegexp = regexp.MustCompile(` \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}`) + // Statically verify that Context implements appengine.Context. -var _ appengine.Context = (*Context)(nil) +var _ context.Context = (*Context)(nil) // httpClient is used to communicate with the helper child process's // webserver. We can't use http.DefaultClient anymore, as it's now @@ -52,10 +53,16 @@ const AppServerFileName = "dev_appserver.py" const aeFakeName = "appenginetestingfake" // Using -loglevel on the command line temporarily overrides the options in NewContext -var overrideLogLevel = flag.String("loglevel", "", "[appenginetesting] forces all tests to have LogLevel of one of the following: child,debug,info,warning,error,critical") +var overrideLogLevel string func init() { - flag.Parse() + // TODO: Verify this works? + // Check for override loglevel + for i, a := range os.Args { + if a == "-loglevel" { + overrideLogLevel = os.Args[i+1] + } + } } // Context implements appengine.Context by running a dev_appserver.py @@ -69,7 +76,7 @@ type Context struct { fakeAppDir string // temp dir for application files queues []string // list of queues to support debug LogLevel // send the output of the application to console - testing *testing.T + testing TestingT wroteToLog bool // used in TestLogging modules []ModuleConfig // list of the modules that should start up on each test } @@ -79,6 +86,10 @@ type ModuleConfig struct { Path string // can be relative to the current working directory and should include the yaml file } +func (c *Context) Deadline() (time.Time, bool) { + return nil, false +} + func (c *Context) AppID() string { return c.appid } @@ -87,7 +98,8 @@ func (c *Context) logf(level LogLevel, format string, args ...interface{}) { if c.debug > level { return } - s := fmt.Sprintf("%s\t%s", level, fmt.Sprintf(format, args...)) + s := fmt.Sprintf("%s\t%s\n", level, fmt.Sprintf(format, args...)) + s = logTrimRegexp.ReplaceAllLiteralString(s, " ") if c.testing == nil { log.Println(s) } else { @@ -177,7 +189,7 @@ func (c *Context) Logout() { c.req.Header.Del("X-AppEngine-User-Federated-Provider") } -func (c *Context) Call(service, method string, in, out appengine_internal.ProtoMessage, opts *appengine_internal.CallOptions) error { +func (c *Context) Call(service, method string, in, out internal.ProtoMessage, opts *internal.CallOptions) error { if service == "__go__" { if method == "GetNamespace" { out.(*basepb.StringProto).Value = proto.String(c.req.Header.Get("X-AppEngine-Current-Namespace")) @@ -190,7 +202,7 @@ func (c *Context) Call(service, method string, in, out appengine_internal.ProtoM } cn := c.GetCurrentNamespace() if cn != "" { - if mod, ok := appengine_internal.NamespaceMods[service]; ok { + if mod, ok := internal.NamespaceMods[service]; ok { mod(in, cn) } } @@ -252,7 +264,7 @@ type Options struct { AppId string // Required if using any Modules TaskQueues []string Debug LogLevel - Testing *testing.T + Testing TestingT Modules []ModuleConfig } @@ -383,6 +395,7 @@ func (c *Context) startChild() error { python, devAppserver, "--clear_datastore=true", + "--datastore_consistency_policy=consistent", "--skip_sdk_update_check=true", fmt.Sprintf("--storage_path=%s/data.datastore", c.fakeAppDir), fmt.Sprintf("--log_level=%s", appLog), @@ -399,6 +412,7 @@ func (c *Context) startChild() error { python, append([]string{devAppserver, "--clear_datastore=true", + "--datastore_consistency_policy=consistent", "--skip_sdk_update_check=true", fmt.Sprintf("--storage_path=%s/data.datastore", c.fakeAppDir), fmt.Sprintf("--log_level=%s", appLog), @@ -509,7 +523,7 @@ func NewContext(opts *Options) (*Context, error) { debug: opts.debug(), } - switch *overrideLogLevel { + switch overrideLogLevel { case "": // do nothing, no value set case "child": c.debug = LogChild @@ -524,7 +538,7 @@ func NewContext(opts *Options) (*Context, error) { case "critical": c.debug = LogCritical default: - log.Fatalf("[appenginetesting] loglevel given %s, not a valid option, use one of child, debug, info, warning, error, or critical.", *overrideLogLevel) + log.Fatalf("[appenginetesting] loglevel given %s, not a valid option, use one of child, debug, info, warning, error, or critical.", overrideLogLevel) } if opts != nil { diff --git a/testingt.go b/testingt.go new file mode 100644 index 0000000..53b245e --- /dev/null +++ b/testingt.go @@ -0,0 +1,20 @@ +package appenginetesting + +//The interface returned by GinkgoT(). This covers most of the methods +//in the testing package's T. +type TestingT interface { + Fail() + Error(args ...interface{}) + Errorf(format string, args ...interface{}) + FailNow() + Fatal(args ...interface{}) + Fatalf(format string, args ...interface{}) + Log(args ...interface{}) + Logf(format string, args ...interface{}) + Failed() bool + Parallel() + Skip(args ...interface{}) + Skipf(format string, args ...interface{}) + SkipNow() + Skipped() bool +}