aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/google.golang.org/appengine/delay
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/google.golang.org/appengine/delay')
-rw-r--r--vendor/google.golang.org/appengine/delay/delay.go295
-rw-r--r--vendor/google.golang.org/appengine/delay/delay_go17.go23
-rw-r--r--vendor/google.golang.org/appengine/delay/delay_go17_test.go55
-rw-r--r--vendor/google.golang.org/appengine/delay/delay_pre17.go19
-rw-r--r--vendor/google.golang.org/appengine/delay/delay_test.go428
5 files changed, 0 insertions, 820 deletions
diff --git a/vendor/google.golang.org/appengine/delay/delay.go b/vendor/google.golang.org/appengine/delay/delay.go
deleted file mode 100644
index 52915a4..0000000
--- a/vendor/google.golang.org/appengine/delay/delay.go
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright 2011 Google Inc. All rights reserved.
-// Use of this source code is governed by the Apache 2.0
-// license that can be found in the LICENSE file.
-
-/*
-Package delay provides a way to execute code outside the scope of a
-user request by using the taskqueue API.
-
-To declare a function that may be executed later, call Func
-in a top-level assignment context, passing it an arbitrary string key
-and a function whose first argument is of type context.Context.
-The key is used to look up the function so it can be called later.
- var laterFunc = delay.Func("key", myFunc)
-It is also possible to use a function literal.
- var laterFunc = delay.Func("key", func(c context.Context, x string) {
- // ...
- })
-
-To call a function, invoke its Call method.
- laterFunc.Call(c, "something")
-A function may be called any number of times. If the function has any
-return arguments, and the last one is of type error, the function may
-return a non-nil error to signal that the function should be retried.
-
-The arguments to functions may be of any type that is encodable by the gob
-package. If an argument is of interface type, it is the client's responsibility
-to register with the gob package whatever concrete type may be passed for that
-argument; see http://golang.org/pkg/gob/#Register for details.
-
-Any errors during initialization or execution of a function will be
-logged to the application logs. Error logs that occur during initialization will
-be associated with the request that invoked the Call method.
-
-The state of a function invocation that has not yet successfully
-executed is preserved by combining the file name in which it is declared
-with the string key that was passed to the Func function. Updating an app
-with pending function invocations is safe as long as the relevant
-functions have the (filename, key) combination preserved.
-
-The delay package uses the Task Queue API to create tasks that call the
-reserved application path "/_ah/queue/go/delay".
-This path must not be marked as "login: required" in app.yaml;
-it must be marked as "login: admin" or have no access restriction.
-*/
-package delay // import "google.golang.org/appengine/delay"
-
-import (
- "bytes"
- "encoding/gob"
- "errors"
- "fmt"
- "net/http"
- "reflect"
- "runtime"
-
- "golang.org/x/net/context"
-
- "google.golang.org/appengine"
- "google.golang.org/appengine/log"
- "google.golang.org/appengine/taskqueue"
-)
-
-// Function represents a function that may have a delayed invocation.
-type Function struct {
- fv reflect.Value // Kind() == reflect.Func
- key string
- err error // any error during initialization
-}
-
-const (
- // The HTTP path for invocations.
- path = "/_ah/queue/go/delay"
- // Use the default queue.
- queue = ""
-)
-
-type contextKey int
-
-var (
- // registry of all delayed functions
- funcs = make(map[string]*Function)
-
- // precomputed types
- errorType = reflect.TypeOf((*error)(nil)).Elem()
-
- // errors
- errFirstArg = errors.New("first argument must be context.Context")
- errOutsideDelayFunc = errors.New("request headers are only available inside a delay.Func")
-
- // context keys
- headersContextKey contextKey = 0
-)
-
-// Func declares a new Function. The second argument must be a function with a
-// first argument of type context.Context.
-// This function must be called at program initialization time. That means it
-// must be called in a global variable declaration or from an init function.
-// This restriction is necessary because the instance that delays a function
-// call may not be the one that executes it. Only the code executed at program
-// initialization time is guaranteed to have been run by an instance before it
-// receives a request.
-func Func(key string, i interface{}) *Function {
- f := &Function{fv: reflect.ValueOf(i)}
-
- // Derive unique, somewhat stable key for this func.
- _, file, _, _ := runtime.Caller(1)
- f.key = file + ":" + key
-
- t := f.fv.Type()
- if t.Kind() != reflect.Func {
- f.err = errors.New("not a function")
- return f
- }
- if t.NumIn() == 0 || !isContext(t.In(0)) {
- f.err = errFirstArg
- return f
- }
-
- // Register the function's arguments with the gob package.
- // This is required because they are marshaled inside a []interface{}.
- // gob.Register only expects to be called during initialization;
- // that's fine because this function expects the same.
- for i := 0; i < t.NumIn(); i++ {
- // Only concrete types may be registered. If the argument has
- // interface type, the client is resposible for registering the
- // concrete types it will hold.
- if t.In(i).Kind() == reflect.Interface {
- continue
- }
- gob.Register(reflect.Zero(t.In(i)).Interface())
- }
-
- if old := funcs[f.key]; old != nil {
- old.err = fmt.Errorf("multiple functions registered for %s in %s", key, file)
- }
- funcs[f.key] = f
- return f
-}
-
-type invocation struct {
- Key string
- Args []interface{}
-}
-
-// Call invokes a delayed function.
-// err := f.Call(c, ...)
-// is equivalent to
-// t, _ := f.Task(...)
-// _, err := taskqueue.Add(c, t, "")
-func (f *Function) Call(c context.Context, args ...interface{}) error {
- t, err := f.Task(args...)
- if err != nil {
- return err
- }
- _, err = taskqueueAdder(c, t, queue)
- return err
-}
-
-// Task creates a Task that will invoke the function.
-// Its parameters may be tweaked before adding it to a queue.
-// Users should not modify the Path or Payload fields of the returned Task.
-func (f *Function) Task(args ...interface{}) (*taskqueue.Task, error) {
- if f.err != nil {
- return nil, fmt.Errorf("delay: func is invalid: %v", f.err)
- }
-
- nArgs := len(args) + 1 // +1 for the context.Context
- ft := f.fv.Type()
- minArgs := ft.NumIn()
- if ft.IsVariadic() {
- minArgs--
- }
- if nArgs < minArgs {
- return nil, fmt.Errorf("delay: too few arguments to func: %d < %d", nArgs, minArgs)
- }
- if !ft.IsVariadic() && nArgs > minArgs {
- return nil, fmt.Errorf("delay: too many arguments to func: %d > %d", nArgs, minArgs)
- }
-
- // Check arg types.
- for i := 1; i < nArgs; i++ {
- at := reflect.TypeOf(args[i-1])
- var dt reflect.Type
- if i < minArgs {
- // not a variadic arg
- dt = ft.In(i)
- } else {
- // a variadic arg
- dt = ft.In(minArgs).Elem()
- }
- // nil arguments won't have a type, so they need special handling.
- if at == nil {
- // nil interface
- switch dt.Kind() {
- case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
- continue // may be nil
- }
- return nil, fmt.Errorf("delay: argument %d has wrong type: %v is not nilable", i, dt)
- }
- switch at.Kind() {
- case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
- av := reflect.ValueOf(args[i-1])
- if av.IsNil() {
- // nil value in interface; not supported by gob, so we replace it
- // with a nil interface value
- args[i-1] = nil
- }
- }
- if !at.AssignableTo(dt) {
- return nil, fmt.Errorf("delay: argument %d has wrong type: %v is not assignable to %v", i, at, dt)
- }
- }
-
- inv := invocation{
- Key: f.key,
- Args: args,
- }
-
- buf := new(bytes.Buffer)
- if err := gob.NewEncoder(buf).Encode(inv); err != nil {
- return nil, fmt.Errorf("delay: gob encoding failed: %v", err)
- }
-
- return &taskqueue.Task{
- Path: path,
- Payload: buf.Bytes(),
- }, nil
-}
-
-// Request returns the special task-queue HTTP request headers for the current
-// task queue handler. Returns an error if called from outside a delay.Func.
-func RequestHeaders(c context.Context) (*taskqueue.RequestHeaders, error) {
- if ret, ok := c.Value(headersContextKey).(*taskqueue.RequestHeaders); ok {
- return ret, nil
- }
- return nil, errOutsideDelayFunc
-}
-
-var taskqueueAdder = taskqueue.Add // for testing
-
-func init() {
- http.HandleFunc(path, func(w http.ResponseWriter, req *http.Request) {
- runFunc(appengine.NewContext(req), w, req)
- })
-}
-
-func runFunc(c context.Context, w http.ResponseWriter, req *http.Request) {
- defer req.Body.Close()
-
- c = context.WithValue(c, headersContextKey, taskqueue.ParseRequestHeaders(req.Header))
-
- var inv invocation
- if err := gob.NewDecoder(req.Body).Decode(&inv); err != nil {
- log.Errorf(c, "delay: failed decoding task payload: %v", err)
- log.Warningf(c, "delay: dropping task")
- return
- }
-
- f := funcs[inv.Key]
- if f == nil {
- log.Errorf(c, "delay: no func with key %q found", inv.Key)
- log.Warningf(c, "delay: dropping task")
- return
- }
-
- ft := f.fv.Type()
- in := []reflect.Value{reflect.ValueOf(c)}
- for _, arg := range inv.Args {
- var v reflect.Value
- if arg != nil {
- v = reflect.ValueOf(arg)
- } else {
- // Task was passed a nil argument, so we must construct
- // the zero value for the argument here.
- n := len(in) // we're constructing the nth argument
- var at reflect.Type
- if !ft.IsVariadic() || n < ft.NumIn()-1 {
- at = ft.In(n)
- } else {
- at = ft.In(ft.NumIn() - 1).Elem()
- }
- v = reflect.Zero(at)
- }
- in = append(in, v)
- }
- out := f.fv.Call(in)
-
- if n := ft.NumOut(); n > 0 && ft.Out(n-1) == errorType {
- if errv := out[n-1]; !errv.IsNil() {
- log.Errorf(c, "delay: func failed (will retry): %v", errv.Interface())
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- }
-}
diff --git a/vendor/google.golang.org/appengine/delay/delay_go17.go b/vendor/google.golang.org/appengine/delay/delay_go17.go
deleted file mode 100644
index 9a59e8b..0000000
--- a/vendor/google.golang.org/appengine/delay/delay_go17.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-// Use of this source code is governed by the Apache 2.0
-// license that can be found in the LICENSE file.
-
-//+build go1.7
-
-package delay
-
-import (
- stdctx "context"
- "reflect"
-
- netctx "golang.org/x/net/context"
-)
-
-var (
- stdContextType = reflect.TypeOf((*stdctx.Context)(nil)).Elem()
- netContextType = reflect.TypeOf((*netctx.Context)(nil)).Elem()
-)
-
-func isContext(t reflect.Type) bool {
- return t == stdContextType || t == netContextType
-}
diff --git a/vendor/google.golang.org/appengine/delay/delay_go17_test.go b/vendor/google.golang.org/appengine/delay/delay_go17_test.go
deleted file mode 100644
index 0e708d0..0000000
--- a/vendor/google.golang.org/appengine/delay/delay_go17_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-// Use of this source code is governed by the Apache 2.0
-// license that can be found in the LICENSE file.
-
-//+build go1.7
-
-package delay
-
-import (
- "bytes"
- stdctx "context"
- "net/http"
- "net/http/httptest"
- "testing"
-
- netctx "golang.org/x/net/context"
- "google.golang.org/appengine/taskqueue"
-)
-
-var (
- stdCtxRuns = 0
- stdCtxFunc = Func("stdctx", func(c stdctx.Context) {
- stdCtxRuns++
- })
-)
-
-func TestStandardContext(t *testing.T) {
- // Fake out the adding of a task.
- var task *taskqueue.Task
- taskqueueAdder = func(_ netctx.Context, tk *taskqueue.Task, queue string) (*taskqueue.Task, error) {
- if queue != "" {
- t.Errorf(`Got queue %q, expected ""`, queue)
- }
- task = tk
- return tk, nil
- }
-
- c := newFakeContext()
- stdCtxRuns = 0 // reset state
- if err := stdCtxFunc.Call(c.ctx); err != nil {
- t.Fatal("Function.Call:", err)
- }
-
- // Simulate the Task Queue service.
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
-
- if stdCtxRuns != 1 {
- t.Errorf("stdCtxRuns: got %d, want 1", stdCtxRuns)
- }
-}
diff --git a/vendor/google.golang.org/appengine/delay/delay_pre17.go b/vendor/google.golang.org/appengine/delay/delay_pre17.go
deleted file mode 100644
index d30c75d..0000000
--- a/vendor/google.golang.org/appengine/delay/delay_pre17.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-// Use of this source code is governed by the Apache 2.0
-// license that can be found in the LICENSE file.
-
-//+build !go1.7
-
-package delay
-
-import (
- "reflect"
-
- "golang.org/x/net/context"
-)
-
-var contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
-
-func isContext(t reflect.Type) bool {
- return t == contextType
-}
diff --git a/vendor/google.golang.org/appengine/delay/delay_test.go b/vendor/google.golang.org/appengine/delay/delay_test.go
deleted file mode 100644
index 3df2bf7..0000000
--- a/vendor/google.golang.org/appengine/delay/delay_test.go
+++ /dev/null
@@ -1,428 +0,0 @@
-// Copyright 2011 Google Inc. All rights reserved.
-// Use of this source code is governed by the Apache 2.0
-// license that can be found in the LICENSE file.
-
-package delay
-
-import (
- "bytes"
- "encoding/gob"
- "errors"
- "fmt"
- "net/http"
- "net/http/httptest"
- "reflect"
- "testing"
-
- "github.com/golang/protobuf/proto"
- "golang.org/x/net/context"
-
- "google.golang.org/appengine/internal"
- "google.golang.org/appengine/taskqueue"
-)
-
-type CustomType struct {
- N int
-}
-
-type CustomInterface interface {
- N() int
-}
-
-type CustomImpl int
-
-func (c CustomImpl) N() int { return int(c) }
-
-// CustomImpl needs to be registered with gob.
-func init() {
- gob.Register(CustomImpl(0))
-}
-
-var (
- invalidFunc = Func("invalid", func() {})
-
- regFuncRuns = 0
- regFuncMsg = ""
- regFunc = Func("reg", func(c context.Context, arg string) {
- regFuncRuns++
- regFuncMsg = arg
- })
-
- custFuncTally = 0
- custFunc = Func("cust", func(c context.Context, ct *CustomType, ci CustomInterface) {
- a, b := 2, 3
- if ct != nil {
- a = ct.N
- }
- if ci != nil {
- b = ci.N()
- }
- custFuncTally += a + b
- })
-
- anotherCustFunc = Func("cust2", func(c context.Context, n int, ct *CustomType, ci CustomInterface) {
- })
-
- varFuncMsg = ""
- varFunc = Func("variadic", func(c context.Context, format string, args ...int) {
- // convert []int to []interface{} for fmt.Sprintf.
- as := make([]interface{}, len(args))
- for i, a := range args {
- as[i] = a
- }
- varFuncMsg = fmt.Sprintf(format, as...)
- })
-
- errFuncRuns = 0
- errFuncErr = errors.New("error!")
- errFunc = Func("err", func(c context.Context) error {
- errFuncRuns++
- if errFuncRuns == 1 {
- return nil
- }
- return errFuncErr
- })
-
- dupeWhich = 0
- dupe1Func = Func("dupe", func(c context.Context) {
- if dupeWhich == 0 {
- dupeWhich = 1
- }
- })
- dupe2Func = Func("dupe", func(c context.Context) {
- if dupeWhich == 0 {
- dupeWhich = 2
- }
- })
-
- reqFuncRuns = 0
- reqFuncHeaders *taskqueue.RequestHeaders
- reqFuncErr error
- reqFunc = Func("req", func(c context.Context) {
- reqFuncRuns++
- reqFuncHeaders, reqFuncErr = RequestHeaders(c)
- })
-)
-
-type fakeContext struct {
- ctx context.Context
- logging [][]interface{}
-}
-
-func newFakeContext() *fakeContext {
- f := new(fakeContext)
- f.ctx = internal.WithCallOverride(context.Background(), f.call)
- f.ctx = internal.WithLogOverride(f.ctx, f.logf)
- return f
-}
-
-func (f *fakeContext) call(ctx context.Context, service, method string, in, out proto.Message) error {
- panic("should never be called")
-}
-
-var logLevels = map[int64]string{1: "INFO", 3: "ERROR"}
-
-func (f *fakeContext) logf(level int64, format string, args ...interface{}) {
- f.logging = append(f.logging, append([]interface{}{logLevels[level], format}, args...))
-}
-
-func TestInvalidFunction(t *testing.T) {
- c := newFakeContext()
-
- if got, want := invalidFunc.Call(c.ctx), fmt.Errorf("delay: func is invalid: %s", errFirstArg); got.Error() != want.Error() {
- t.Errorf("Incorrect error: got %q, want %q", got, want)
- }
-}
-
-func TestVariadicFunctionArguments(t *testing.T) {
- // Check the argument type validation for variadic functions.
-
- c := newFakeContext()
-
- calls := 0
- taskqueueAdder = func(c context.Context, t *taskqueue.Task, _ string) (*taskqueue.Task, error) {
- calls++
- return t, nil
- }
-
- varFunc.Call(c.ctx, "hi")
- varFunc.Call(c.ctx, "%d", 12)
- varFunc.Call(c.ctx, "%d %d %d", 3, 1, 4)
- if calls != 3 {
- t.Errorf("Got %d calls to taskqueueAdder, want 3", calls)
- }
-
- if got, want := varFunc.Call(c.ctx, "%d %s", 12, "a string is bad"), errors.New("delay: argument 3 has wrong type: string is not assignable to int"); got.Error() != want.Error() {
- t.Errorf("Incorrect error: got %q, want %q", got, want)
- }
-}
-
-func TestBadArguments(t *testing.T) {
- // Try running regFunc with different sets of inappropriate arguments.
-
- c := newFakeContext()
-
- tests := []struct {
- args []interface{} // all except context
- wantErr string
- }{
- {
- args: nil,
- wantErr: "delay: too few arguments to func: 1 < 2",
- },
- {
- args: []interface{}{"lala", 53},
- wantErr: "delay: too many arguments to func: 3 > 2",
- },
- {
- args: []interface{}{53},
- wantErr: "delay: argument 1 has wrong type: int is not assignable to string",
- },
- }
- for i, tc := range tests {
- got := regFunc.Call(c.ctx, tc.args...)
- if got.Error() != tc.wantErr {
- t.Errorf("Call %v: got %q, want %q", i, got, tc.wantErr)
- }
- }
-}
-
-func TestRunningFunction(t *testing.T) {
- c := newFakeContext()
-
- // Fake out the adding of a task.
- var task *taskqueue.Task
- taskqueueAdder = func(_ context.Context, tk *taskqueue.Task, queue string) (*taskqueue.Task, error) {
- if queue != "" {
- t.Errorf(`Got queue %q, expected ""`, queue)
- }
- task = tk
- return tk, nil
- }
-
- regFuncRuns, regFuncMsg = 0, "" // reset state
- const msg = "Why, hello!"
- regFunc.Call(c.ctx, msg)
-
- // Simulate the Task Queue service.
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
-
- if regFuncRuns != 1 {
- t.Errorf("regFuncRuns: got %d, want 1", regFuncRuns)
- }
- if regFuncMsg != msg {
- t.Errorf("regFuncMsg: got %q, want %q", regFuncMsg, msg)
- }
-}
-
-func TestCustomType(t *testing.T) {
- c := newFakeContext()
-
- // Fake out the adding of a task.
- var task *taskqueue.Task
- taskqueueAdder = func(_ context.Context, tk *taskqueue.Task, queue string) (*taskqueue.Task, error) {
- if queue != "" {
- t.Errorf(`Got queue %q, expected ""`, queue)
- }
- task = tk
- return tk, nil
- }
-
- custFuncTally = 0 // reset state
- custFunc.Call(c.ctx, &CustomType{N: 11}, CustomImpl(13))
-
- // Simulate the Task Queue service.
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
-
- if custFuncTally != 24 {
- t.Errorf("custFuncTally = %d, want 24", custFuncTally)
- }
-
- // Try the same, but with nil values; one is a nil pointer (and thus a non-nil interface value),
- // and the other is a nil interface value.
- custFuncTally = 0 // reset state
- custFunc.Call(c.ctx, (*CustomType)(nil), nil)
-
- // Simulate the Task Queue service.
- req, err = http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw = httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
-
- if custFuncTally != 5 {
- t.Errorf("custFuncTally = %d, want 5", custFuncTally)
- }
-}
-
-func TestRunningVariadic(t *testing.T) {
- c := newFakeContext()
-
- // Fake out the adding of a task.
- var task *taskqueue.Task
- taskqueueAdder = func(_ context.Context, tk *taskqueue.Task, queue string) (*taskqueue.Task, error) {
- if queue != "" {
- t.Errorf(`Got queue %q, expected ""`, queue)
- }
- task = tk
- return tk, nil
- }
-
- varFuncMsg = "" // reset state
- varFunc.Call(c.ctx, "Amiga %d has %d KB RAM", 500, 512)
-
- // Simulate the Task Queue service.
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
-
- const expected = "Amiga 500 has 512 KB RAM"
- if varFuncMsg != expected {
- t.Errorf("varFuncMsg = %q, want %q", varFuncMsg, expected)
- }
-}
-
-func TestErrorFunction(t *testing.T) {
- c := newFakeContext()
-
- // Fake out the adding of a task.
- var task *taskqueue.Task
- taskqueueAdder = func(_ context.Context, tk *taskqueue.Task, queue string) (*taskqueue.Task, error) {
- if queue != "" {
- t.Errorf(`Got queue %q, expected ""`, queue)
- }
- task = tk
- return tk, nil
- }
-
- errFunc.Call(c.ctx)
-
- // Simulate the Task Queue service.
- // The first call should succeed; the second call should fail.
- {
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
- }
- {
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
- if rw.Code != http.StatusInternalServerError {
- t.Errorf("Got status code %d, want %d", rw.Code, http.StatusInternalServerError)
- }
-
- wantLogging := [][]interface{}{
- {"ERROR", "delay: func failed (will retry): %v", errFuncErr},
- }
- if !reflect.DeepEqual(c.logging, wantLogging) {
- t.Errorf("Incorrect logging: got %+v, want %+v", c.logging, wantLogging)
- }
- }
-}
-
-func TestDuplicateFunction(t *testing.T) {
- c := newFakeContext()
-
- // Fake out the adding of a task.
- var task *taskqueue.Task
- taskqueueAdder = func(_ context.Context, tk *taskqueue.Task, queue string) (*taskqueue.Task, error) {
- if queue != "" {
- t.Errorf(`Got queue %q, expected ""`, queue)
- }
- task = tk
- return tk, nil
- }
-
- if err := dupe1Func.Call(c.ctx); err == nil {
- t.Error("dupe1Func.Call did not return error")
- }
- if task != nil {
- t.Error("dupe1Func.Call posted a task")
- }
- if err := dupe2Func.Call(c.ctx); err != nil {
- t.Errorf("dupe2Func.Call error: %v", err)
- }
- if task == nil {
- t.Fatalf("dupe2Func.Call did not post a task")
- }
-
- // Simulate the Task Queue service.
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
-
- if dupeWhich == 1 {
- t.Error("dupe2Func.Call used old registered function")
- } else if dupeWhich != 2 {
- t.Errorf("dupeWhich = %d; want 2", dupeWhich)
- }
-}
-
-func TestGetRequestHeadersFromContext(t *testing.T) {
- c := newFakeContext()
-
- // Outside a delay.Func should return an error.
- headers, err := RequestHeaders(c.ctx)
- if headers != nil {
- t.Errorf("RequestHeaders outside Func, got %v, want nil", headers)
- }
- if err != errOutsideDelayFunc {
- t.Errorf("RequestHeaders outside Func err, got %v, want %v", err, errOutsideDelayFunc)
- }
-
- // Fake out the adding of a task.
- var task *taskqueue.Task
- taskqueueAdder = func(_ context.Context, tk *taskqueue.Task, queue string) (*taskqueue.Task, error) {
- if queue != "" {
- t.Errorf(`Got queue %q, expected ""`, queue)
- }
- task = tk
- return tk, nil
- }
-
- reqFunc.Call(c.ctx)
-
- reqFuncRuns, reqFuncHeaders = 0, nil // reset state
- // Simulate the Task Queue service.
- req, err := http.NewRequest("POST", path, bytes.NewBuffer(task.Payload))
- req.Header.Set("x-appengine-taskname", "foobar")
- if err != nil {
- t.Fatalf("Failed making http.Request: %v", err)
- }
- rw := httptest.NewRecorder()
- runFunc(c.ctx, rw, req)
-
- if reqFuncRuns != 1 {
- t.Errorf("reqFuncRuns: got %d, want 1", reqFuncRuns)
- }
- if reqFuncHeaders.TaskName != "foobar" {
- t.Errorf("reqFuncHeaders.TaskName: got %v, want 'foobar'", reqFuncHeaders.TaskName)
- }
- if reqFuncErr != nil {
- t.Errorf("reqFuncErr: got %v, want nil", reqFuncErr)
- }
-}