@@ -4,13 +4,16 @@ import (
4
4
"context"
5
5
"errors"
6
6
"fmt"
7
+ "sync"
7
8
"testing"
8
9
"time"
9
10
10
11
"github.com/graph-gophers/graphql-go"
11
12
gqlerrors "github.com/graph-gophers/graphql-go/errors"
12
13
"github.com/graph-gophers/graphql-go/example/starwars"
13
14
"github.com/graph-gophers/graphql-go/gqltesting"
15
+ "github.com/graph-gophers/graphql-go/introspection"
16
+ "github.com/graph-gophers/graphql-go/trace"
14
17
)
15
18
16
19
type helloWorldResolver1 struct {}
@@ -3999,3 +4002,153 @@ func TestNullable(t *testing.T) {
3999
4002
},
4000
4003
})
4001
4004
}
4005
+
4006
+ type testTracer struct {
4007
+ mu * sync.Mutex
4008
+ fields []fieldTrace
4009
+ queries []queryTrace
4010
+ }
4011
+
4012
+ type fieldTrace struct {
4013
+ label string
4014
+ typeName string
4015
+ fieldName string
4016
+ isTrivial bool
4017
+ args map [string ]interface {}
4018
+ err * gqlerrors.QueryError
4019
+ }
4020
+
4021
+ type queryTrace struct {
4022
+ document string
4023
+ opName string
4024
+ variables map [string ]interface {}
4025
+ varTypes map [string ]* introspection.Type
4026
+ errors []* gqlerrors.QueryError
4027
+ }
4028
+
4029
+ func (t * testTracer ) TraceField (ctx context.Context , label , typeName , fieldName string , trivial bool , args map [string ]interface {}) (context.Context , trace.TraceFieldFinishFunc ) {
4030
+ return ctx , func (qe * gqlerrors.QueryError ) {
4031
+ t .mu .Lock ()
4032
+ defer t .mu .Unlock ()
4033
+
4034
+ ft := fieldTrace {
4035
+ label : label ,
4036
+ typeName : typeName ,
4037
+ fieldName : fieldName ,
4038
+ isTrivial : trivial ,
4039
+ args : args ,
4040
+ err : qe ,
4041
+ }
4042
+
4043
+ t .fields = append (t .fields , ft )
4044
+ }
4045
+ }
4046
+
4047
+ func (t * testTracer ) TraceQuery (ctx context.Context , document string , opName string , vars map [string ]interface {}, varTypes map [string ]* introspection.Type ) (context.Context , trace.TraceQueryFinishFunc ) {
4048
+ return ctx , func (qe []* gqlerrors.QueryError ) {
4049
+ t .mu .Lock ()
4050
+ defer t .mu .Unlock ()
4051
+
4052
+ qt := queryTrace {
4053
+ document : document ,
4054
+ opName : opName ,
4055
+ variables : vars ,
4056
+ varTypes : varTypes ,
4057
+ errors : qe ,
4058
+ }
4059
+
4060
+ t .queries = append (t .queries , qt )
4061
+ }
4062
+ }
4063
+
4064
+ var _ trace.Tracer = (* testTracer )(nil )
4065
+
4066
+ func TestTracer (t * testing.T ) {
4067
+ t .Parallel ()
4068
+
4069
+ tracer := & testTracer {mu : & sync.Mutex {}}
4070
+
4071
+ schema , err := graphql .ParseSchema (starwars .Schema , & starwars.Resolver {}, graphql .Tracer (tracer ))
4072
+ if err != nil {
4073
+ t .Fatalf ("graphql.ParseSchema: %s" , err )
4074
+ }
4075
+
4076
+ ctx := context .Background ()
4077
+ doc := `
4078
+ query TestTracer($id: ID!) {
4079
+ HanSolo: human(id: $id) {
4080
+ __typename
4081
+ name
4082
+ }
4083
+ }
4084
+ `
4085
+ opName := "TestTracer"
4086
+ variables := map [string ]interface {}{
4087
+ "id" : "1002" ,
4088
+ }
4089
+
4090
+ _ = schema .Exec (ctx , doc , opName , variables )
4091
+
4092
+ tracer .mu .Lock ()
4093
+ defer tracer .mu .Unlock ()
4094
+
4095
+ if len (tracer .queries ) != 1 {
4096
+ t .Fatalf ("expected one query trace, but got %d: %#v" , len (tracer .queries ), tracer .queries )
4097
+ }
4098
+
4099
+ qt := tracer .queries [0 ]
4100
+ if qt .document != doc {
4101
+ t .Errorf ("mismatched query trace document:\n want: %q\n got : %q" , doc , qt .document )
4102
+ }
4103
+ if qt .opName != opName {
4104
+ t .Errorf ("mismated query trace operationName:\n want: %q\n got : %q" , opName , qt .opName )
4105
+ }
4106
+
4107
+ expectedFieldTraces := []fieldTrace {
4108
+ {fieldName : "human" , typeName : "Query" },
4109
+ {fieldName : "__typename" , typeName : "Human" },
4110
+ {fieldName : "name" , typeName : "Human" },
4111
+ }
4112
+
4113
+ checkFieldTraces (t , expectedFieldTraces , tracer .fields )
4114
+ }
4115
+
4116
+ func checkFieldTraces (t * testing.T , want , have []fieldTrace ) {
4117
+ if len (want ) != len (have ) {
4118
+ t .Errorf ("mismatched field traces: expected %d but got %d: %#v" , len (want ), len (have ), have )
4119
+ }
4120
+
4121
+ type comparsion struct {
4122
+ want fieldTrace
4123
+ have fieldTrace
4124
+ }
4125
+
4126
+ m := map [string ]comparsion {}
4127
+
4128
+ for _ , ft := range want {
4129
+ m [ft .fieldName ] = comparsion {want : ft }
4130
+ }
4131
+
4132
+ for _ , ft := range have {
4133
+ c := m [ft .fieldName ]
4134
+ c .have = ft
4135
+ m [ft .fieldName ] = c
4136
+ }
4137
+
4138
+ for _ , c := range m {
4139
+ if err := stringsEqual (c .want .fieldName , c .have .fieldName ); err != "" {
4140
+ t .Error ("mismatched field name:" , err )
4141
+ }
4142
+ if err := stringsEqual (c .want .typeName , c .have .typeName ); err != "" {
4143
+ t .Error ("mismatched field parent type:" , err )
4144
+ }
4145
+ }
4146
+ }
4147
+
4148
+ func stringsEqual (want , have string ) string {
4149
+ if want != have {
4150
+ return fmt .Sprintf ("mismatched values:\n want: %q\n have: %q" , want , have )
4151
+ }
4152
+
4153
+ return ""
4154
+ }
0 commit comments