github.com/geneva/gqlgen@v0.17.7-0.20230801155730-7b9317164836/graphql/handler/apollotracing/tracer_test.go (about) 1 package apollotracing_test 2 3 import ( 4 "encoding/json" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/geneva/gqlgen/graphql" 13 "github.com/geneva/gqlgen/graphql/handler/apollotracing" 14 "github.com/geneva/gqlgen/graphql/handler/extension" 15 "github.com/geneva/gqlgen/graphql/handler/lru" 16 "github.com/geneva/gqlgen/graphql/handler/testserver" 17 "github.com/geneva/gqlgen/graphql/handler/transport" 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 "github.com/vektah/gqlparser/v2/ast" 21 "github.com/vektah/gqlparser/v2/gqlerror" 22 ) 23 24 type alwaysError struct{} 25 26 func (a *alwaysError) Read(p []byte) (int, error) { 27 return 0, io.ErrUnexpectedEOF 28 } 29 30 func TestApolloTracing(t *testing.T) { 31 now := time.Unix(0, 0) 32 33 graphql.Now = func() time.Time { 34 defer func() { 35 now = now.Add(100 * time.Nanosecond) 36 }() 37 return now 38 } 39 40 h := testserver.New() 41 h.AddTransport(transport.POST{}) 42 h.Use(apollotracing.Tracer{}) 43 44 resp := doRequest(h, http.MethodPost, "/graphql", `{"query":"{ name }"}`) 45 assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) 46 var respData struct { 47 Extensions struct { 48 Tracing apollotracing.TracingExtension `json:"tracing"` 49 } `json:"extensions"` 50 } 51 require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &respData)) 52 53 tracing := &respData.Extensions.Tracing 54 55 require.EqualValues(t, 1, tracing.Version) 56 57 require.Zero(t, tracing.StartTime.UnixNano()) 58 require.EqualValues(t, 900, tracing.EndTime.UnixNano()) 59 require.EqualValues(t, 900, tracing.Duration) 60 61 require.EqualValues(t, 300, tracing.Parsing.StartOffset) 62 require.EqualValues(t, 100, tracing.Parsing.Duration) 63 64 require.EqualValues(t, 500, tracing.Validation.StartOffset) 65 require.EqualValues(t, 100, tracing.Validation.Duration) 66 67 require.EqualValues(t, 700, tracing.Execution.Resolvers[0].StartOffset) 68 require.EqualValues(t, 100, tracing.Execution.Resolvers[0].Duration) 69 require.EqualValues(t, ast.Path{ast.PathName("name")}, tracing.Execution.Resolvers[0].Path) 70 require.Equal(t, "Query", tracing.Execution.Resolvers[0].ParentType) 71 require.Equal(t, "name", tracing.Execution.Resolvers[0].FieldName) 72 require.Equal(t, "String!", tracing.Execution.Resolvers[0].ReturnType) 73 } 74 75 func TestApolloTracing_withFail(t *testing.T) { 76 now := time.Unix(0, 0) 77 78 graphql.Now = func() time.Time { 79 defer func() { 80 now = now.Add(100 * time.Nanosecond) 81 }() 82 return now 83 } 84 85 h := testserver.New() 86 h.AddTransport(transport.POST{}) 87 h.Use(extension.AutomaticPersistedQuery{Cache: lru.New(100)}) 88 h.Use(apollotracing.Tracer{}) 89 90 resp := doRequest(h, http.MethodPost, "/graphql", `{"operationName":"A","extensions":{"persistedQuery":{"version":1,"sha256Hash":"338bbc16ac780daf81845339fbf0342061c1e9d2b702c96d3958a13a557083a6"}}}`) 91 assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String()) 92 b := resp.Body.Bytes() 93 t.Log(string(b)) 94 var respData struct { 95 Errors gqlerror.List 96 } 97 require.NoError(t, json.Unmarshal(b, &respData)) 98 require.Len(t, respData.Errors, 1) 99 require.Equal(t, "PersistedQueryNotFound", respData.Errors[0].Message) 100 } 101 102 func TestApolloTracing_withUnexpectedEOF(t *testing.T) { 103 h := testserver.New() 104 h.AddTransport(transport.POST{}) 105 h.Use(apollotracing.Tracer{}) 106 107 resp := doRequestWithReader(h, http.MethodPost, "/graphql", &alwaysError{}) 108 assert.Equal(t, http.StatusOK, resp.Code) 109 } 110 111 func doRequest(handler http.Handler, method, target, body string) *httptest.ResponseRecorder { 112 return doRequestWithReader(handler, method, target, strings.NewReader(body)) 113 } 114 115 func doRequestWithReader(handler http.Handler, method string, target string, 116 reader io.Reader) *httptest.ResponseRecorder { 117 r := httptest.NewRequest(method, target, reader) 118 r.Header.Set("Content-Type", "application/json") 119 w := httptest.NewRecorder() 120 121 handler.ServeHTTP(w, r) 122 return w 123 }