From fca783c799750e4818fdfa3bf1b60b825462e23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Garc=C3=ADa=20Hierro?= Date: Mon, 18 Dec 2023 09:33:19 +0000 Subject: [PATCH] fix: crash when requesting trace info without initializing it (#704) If the trace info was not initialized (e.g. we want to always print it if it's available, but it is not always available), we might get into this scenario. --- v2/pkg/engine/resolve/context.go | 4 +++- v2/pkg/engine/resolve/resolvable_test.go | 27 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/v2/pkg/engine/resolve/context.go b/v2/pkg/engine/resolve/context.go index e6cb0591c7..c6b75d6980 100644 --- a/v2/pkg/engine/resolve/context.go +++ b/v2/pkg/engine/resolve/context.go @@ -138,5 +138,7 @@ func SetPlannerStats(ctx context.Context, stats PlannerStats) { } func GetTraceInfo(ctx context.Context) *TraceInfo { - return ctx.Value(traceStartKey{}).(*TraceInfo) + // The context might not have trace info, in that case we return nil + info, _ := ctx.Value(traceStartKey{}).(*TraceInfo) + return info } diff --git a/v2/pkg/engine/resolve/resolvable_test.go b/v2/pkg/engine/resolve/resolvable_test.go index ea52ad373d..a4dfc29613 100644 --- a/v2/pkg/engine/resolve/resolvable_test.go +++ b/v2/pkg/engine/resolve/resolvable_test.go @@ -469,6 +469,33 @@ func BenchmarkResolvable_ResolveWithErrorBubbleUp(b *testing.B) { } } +func TestResolvable_WithTracingNotStarted(t *testing.T) { + res := NewResolvable() + // Do not start a trace with SetTraceStart(), but request it to be output + ctx := NewContext(context.Background()) + ctx.RequestTracingOptions.IncludeTraceOutputInResponseExtensions = true + err := res.Init(ctx, []byte(`{"hello": "world"}`), ast.OperationTypeQuery) + assert.NoError(t, err) + object := &Object{ + Fields: []*Field{ + { + Name: []byte("hello"), + Value: &String{ + Path: []string{"hello"}, + }, + }, + }, + } + out := &bytes.Buffer{} + err = res.Resolve(ctx.ctx, object, out) + + assert.NoError(t, err) + assert.JSONEq(t, `{ + "data": {"hello":"world"}, + "extensions":{"trace":{"node_type":"object","nullable":true,"fields":[{"name":"hello","value":{"node_type":"string","path":["hello"]}}]}} + }`, out.String()) +} + func TestResolvable_WithTracing(t *testing.T) { topProducts := `{"topProducts":[{"name":"Table","__typename":"Product","upc":"1","reviews":[{"body":"Love Table!","author":{"__typename":"User","id":"1","name":"user-1"}},{"body":"Prefer other Table.","author":{"__typename":"User","id":"2","name":"user-2"}}],"stock":8},{"name":"Couch","__typename":"Product","upc":"2","reviews":[{"body":"Couch Too expensive.","author":{"__typename":"User","id":"1","name":"user-1"}}],"stock":2},{"name":"Chair","__typename":"Product","upc":"3","reviews":[{"body":"Chair Could be better.","author":{"__typename":"User","id":"2","name":"user-2"}}],"stock":5}]}` res := NewResolvable()