Skip to content

Commit

Permalink
delay: permit Context from either stdlib or golang.org/x/net (#95)
Browse files Browse the repository at this point in the history
Go 1.7 introduced the Context type into the standard library, but it is
assignable to the golang.org/x/net variant.  The appengine libraries are
written in terms of golang.org/x/net, which can interoperate with the
standard library type most of time, but because delay uses reflection,
it depends directly on the exact type.

The test in this change only failed on Go 1.7 and Go 1.8 but not Go
1.9, since after Go 1.9 the golang.org/x/net type became a type alias
for the standard library type.
  • Loading branch information
zombiezen committed Oct 10, 2017
1 parent 24e4144 commit 07f0757
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 3 deletions.
5 changes: 2 additions & 3 deletions delay/delay.go
Expand Up @@ -81,8 +81,7 @@ var (
funcs = make(map[string]*Function)

// precomputed types
contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
errorType = reflect.TypeOf((*error)(nil)).Elem()
errorType = reflect.TypeOf((*error)(nil)).Elem()

// errors
errFirstArg = errors.New("first argument must be context.Context")
Expand Down Expand Up @@ -112,7 +111,7 @@ func Func(key string, i interface{}) *Function {
f.err = errors.New("not a function")
return f
}
if t.NumIn() == 0 || t.In(0) != contextType {
if t.NumIn() == 0 || !isContext(t.In(0)) {
f.err = errFirstArg
return f
}
Expand Down
23 changes: 23 additions & 0 deletions delay/delay_go17.go
@@ -0,0 +1,23 @@
// 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
}
55 changes: 55 additions & 0 deletions delay/delay_go17_test.go
@@ -0,0 +1,55 @@
// 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)
}
}
19 changes: 19 additions & 0 deletions delay/delay_pre17.go
@@ -0,0 +1,19 @@
// 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
}

0 comments on commit 07f0757

Please sign in to comment.