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  }