fake.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // Copyright 2011 Google Inc. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. // Package aetesting provides utilities for testing App Engine packages.
  5. // This is not for testing user applications.
  6. package aetesting
  7. import (
  8. "fmt"
  9. "reflect"
  10. "testing"
  11. "github.com/golang/protobuf/proto"
  12. "golang.org/x/net/context"
  13. "google.golang.org/appengine/internal"
  14. )
  15. // FakeSingleContext returns a context whose Call invocations will be serviced
  16. // by f, which should be a function that has two arguments of the input and output
  17. // protocol buffer type, and one error return.
  18. func FakeSingleContext(t *testing.T, service, method string, f interface{}) context.Context {
  19. fv := reflect.ValueOf(f)
  20. if fv.Kind() != reflect.Func {
  21. t.Fatal("not a function")
  22. }
  23. ft := fv.Type()
  24. if ft.NumIn() != 2 || ft.NumOut() != 1 {
  25. t.Fatalf("f has %d in and %d out, want 2 in and 1 out", ft.NumIn(), ft.NumOut())
  26. }
  27. for i := 0; i < 2; i++ {
  28. at := ft.In(i)
  29. if !at.Implements(protoMessageType) {
  30. t.Fatalf("arg %d does not implement proto.Message", i)
  31. }
  32. }
  33. if ft.Out(0) != errorType {
  34. t.Fatalf("f's return is %v, want error", ft.Out(0))
  35. }
  36. s := &single{
  37. t: t,
  38. service: service,
  39. method: method,
  40. f: fv,
  41. }
  42. return internal.WithCallOverride(context.Background(), s.call)
  43. }
  44. var (
  45. protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
  46. errorType = reflect.TypeOf((*error)(nil)).Elem()
  47. )
  48. type single struct {
  49. t *testing.T
  50. service, method string
  51. f reflect.Value
  52. }
  53. func (s *single) call(ctx context.Context, service, method string, in, out proto.Message) error {
  54. if service == "__go__" {
  55. if method == "GetNamespace" {
  56. return nil // always yield an empty namespace
  57. }
  58. return fmt.Errorf("Unknown API call /%s.%s", service, method)
  59. }
  60. if service != s.service || method != s.method {
  61. s.t.Fatalf("Unexpected call to /%s.%s", service, method)
  62. }
  63. ins := []reflect.Value{
  64. reflect.ValueOf(in),
  65. reflect.ValueOf(out),
  66. }
  67. outs := s.f.Call(ins)
  68. if outs[0].IsNil() {
  69. return nil
  70. }
  71. return outs[0].Interface().(error)
  72. }