From c723bab43825cbd7d8480bdc15f46c1ec4fa38c5 Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Tue, 12 Aug 2025 17:16:22 +0530 Subject: [PATCH 1/8] updating workflow to handle panics in pipeline --- .github/workflows/go.yml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 36a794cce..3f8300169 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -146,16 +146,25 @@ jobs: with: timeout_minutes: 5 max_attempts: 2 + retry_on: error # Only retry on errors, not panics command: | export APP_ENV=test - # Run tests with coverage for root gofr package only - go test -v -short -covermode=atomic -coverpkg=./pkg/gofr -coverprofile=gofr_only.cov ./pkg/gofr - # Run tests for all sub-packages under gofr - go test -v -covermode=atomic -coverpkg=./pkg/gofr -coverprofile=submodules.cov ./pkg/gofr/... - # Combine coverage profiles - echo "mode: atomic" > profile.cov - grep -h -v "mode:" gofr_only.cov submodules.cov | grep -v '/mock_' >> profile.cov - go tool cover -func profile.cov + + # Custom test runner that distinguishes panics + run_test() { + go test -failfast -v -short -coverprofile packageWithpbgo.cov -coverpkg=gofr.dev/examples/... + local exit_code=$? + + if [ $exit_code -eq 2 ]; then + echo "PANIC detected - not retrying" + echo "::error::Test panic detected (exit code 2)" + return 2 + fi + + return $exit_code + } + + run_test # Upload coverage report for the 1.24 Go version only - name: Upload Test Coverage From 83a3d8d9f8082d3c414acfd22b0d804f6ad1bc8c Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Wed, 13 Aug 2025 12:28:34 +0530 Subject: [PATCH 2/8] to-be-reverted --- pkg/gofr/context.go | 4 ++++ pkg/gofr/context_test.go | 41 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/pkg/gofr/context.go b/pkg/gofr/context.go index 1c1295fd4..a396acde6 100644 --- a/pkg/gofr/context.go +++ b/pkg/gofr/context.go @@ -177,3 +177,7 @@ func newCMDContext(w Responder, r Request, c *container.Container, out terminal. ContextLogger: *logging.NewContextLogger(r.Context(), c.Logger), } } + +func (c *Context) GetCorrelationID() string { + return trace.SpanFromContext(c).SpanContext().TraceID().String() +} diff --git a/pkg/gofr/context_test.go b/pkg/gofr/context_test.go index d14a4d301..07ccbd192 100644 --- a/pkg/gofr/context_test.go +++ b/pkg/gofr/context_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "gofr.dev/pkg/gofr" "net/http" "net/http/httptest" "testing" @@ -234,3 +235,43 @@ func TestGetAuthInfo_JWTClaims(t *testing.T) { assert.Equal(t, claims, res) } + +func TestGetCorrelationID_WithSpan(t *testing.T) { + // Create a known TraceID for testing + traceID := trace.Trace{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + spanID := trace.SpanID{1, 2, 3, 4, 5, 6, 7, 8} + + spanCtx := trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: traceID, + SpanID: spanID, + TraceFlags: trace.FlagsSampled, + Remote: false, + }) + + // Put the SpanContext in a context + ctx := trace.ContextWithSpanContext(context.Background(), spanCtx) + + // Wrap in GoFr Context + gc := &gofr.Context{Context: ctx} + + // Call method + got := gc.GetCorrelationID() + + // Assert + want := traceID.String() + if got != want { + t.Errorf("GetCorrelationID() = %q, want %q", got, want) + } +} + +func TestGetCorrelationID_NoSpan(t *testing.T) { + // No span in context + gc := &gofr.Context{Context: context.Background()} + + got := gc.GetCorrelationID() + want := trace.TraceID().String() // zero TraceID string + + if got != want { + t.Errorf("GetCorrelationID() without span = %q, want %q", got, want) + } +} From 0c39f9415ebf25cf1edfd47c0077257b09488632 Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Wed, 13 Aug 2025 12:34:15 +0530 Subject: [PATCH 3/8] added tests --- pkg/gofr/context_test.go | 59 +++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/pkg/gofr/context_test.go b/pkg/gofr/context_test.go index 07ccbd192..b6b3ba517 100644 --- a/pkg/gofr/context_test.go +++ b/pkg/gofr/context_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "fmt" - "gofr.dev/pkg/gofr" + "go.opentelemetry.io/otel/sdk/trace/tracetest" "net/http" "net/http/httptest" "testing" @@ -236,42 +236,45 @@ func TestGetAuthInfo_JWTClaims(t *testing.T) { assert.Equal(t, claims, res) } -func TestGetCorrelationID_WithSpan(t *testing.T) { - // Create a known TraceID for testing - traceID := trace.Trace{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} - spanID := trace.SpanID{1, 2, 3, 4, 5, 6, 7, 8} +func TestContext_GetCorrelationID(t *testing.T) { + // Setup OpenTelemetry tracer + exporter := tracetest.NewInMemoryExporter() + tp := trace.NewTracerProvider(trace.WithSyncer(exporter)) + otel.SetTracerProvider(tp) - spanCtx := trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: traceID, - SpanID: spanID, - TraceFlags: trace.FlagsSampled, - Remote: false, - }) + tracer := tp.Tracer("test") + ctx, span := tracer.Start(context.Background(), "test-span") + defer span.End() - // Put the SpanContext in a context - ctx := trace.ContextWithSpanContext(context.Background(), spanCtx) + // Create Context instance + gofCtx := &Context{ + Context: ctx, + } - // Wrap in GoFr Context - gc := &gofr.Context{Context: ctx} + // Test GetCorrelationID + correlationID := gofCtx.GetCorrelationID() - // Call method - got := gc.GetCorrelationID() + // Verify result + if len(correlationID) != 32 { + t.Errorf("Expected correlation ID length 32, got %d", len(correlationID)) + } - // Assert - want := traceID.String() - if got != want { - t.Errorf("GetCorrelationID() = %q, want %q", got, want) + if correlationID == "00000000000000000000000000000000" { + t.Error("Expected non-empty correlation ID") } } -func TestGetCorrelationID_NoSpan(t *testing.T) { - // No span in context - gc := &gofr.Context{Context: context.Background()} +func TestContext_GetCorrelationID_NoSpan(t *testing.T) { + // Test with no span in context + gofCtx := &Context{ + Context: context.Background(), + } - got := gc.GetCorrelationID() - want := trace.TraceID().String() // zero TraceID string + correlationID := gofCtx.GetCorrelationID() - if got != want { - t.Errorf("GetCorrelationID() without span = %q, want %q", got, want) + // Should return empty TraceID + expected := "00000000000000000000000000000000" + if correlationID != expected { + t.Errorf("Expected %s, got %s", expected, correlationID) } } From 92675670106d3eb4532e4b3c5ce6686f137ad601 Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Wed, 13 Aug 2025 12:36:32 +0530 Subject: [PATCH 4/8] fixed linters --- pkg/gofr/context_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/gofr/context_test.go b/pkg/gofr/context_test.go index b6b3ba517..226695419 100644 --- a/pkg/gofr/context_test.go +++ b/pkg/gofr/context_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "go.opentelemetry.io/otel/sdk/trace/tracetest" "net/http" "net/http/httptest" "testing" @@ -16,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" "gofr.dev/pkg/gofr/config" "gofr.dev/pkg/gofr/container" @@ -243,7 +243,8 @@ func TestContext_GetCorrelationID(t *testing.T) { otel.SetTracerProvider(tp) tracer := tp.Tracer("test") - ctx, span := tracer.Start(context.Background(), "test-span") + ctx, span := tracer.Start(t.Context(), "test-span") + defer span.End() // Create Context instance @@ -267,7 +268,7 @@ func TestContext_GetCorrelationID(t *testing.T) { func TestContext_GetCorrelationID_NoSpan(t *testing.T) { // Test with no span in context gofCtx := &Context{ - Context: context.Background(), + Context: t.Context(), } correlationID := gofCtx.GetCorrelationID() From 570762860573cffa07ba437007cdfe8a266fc39c Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Thu, 14 Aug 2025 11:15:09 +0530 Subject: [PATCH 5/8] reverting workflow changes --- .github/workflows/go.yml | 43 ++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index abede9769..cd8901079 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -72,7 +72,7 @@ jobs: # Steps to execute for this job steps: - name: Checkout code into go module directory - uses: actions/checkout@v5 + uses: actions/checkout@v4 with: fetch-depth: 0 # Full git history for accurate testing @@ -125,7 +125,7 @@ jobs: steps: - name: Checkout code into go module directory - uses: actions/checkout@v5 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -146,25 +146,16 @@ jobs: with: timeout_minutes: 5 max_attempts: 2 - retry_on: error # Only retry on errors, not panics command: | export APP_ENV=test - - # Custom test runner that distinguishes panics - run_test() { - go test -failfast -v -short -coverprofile packageWithpbgo.cov -coverpkg=gofr.dev/examples/... - local exit_code=$? - - if [ $exit_code -eq 2 ]; then - echo "PANIC detected - not retrying" - echo "::error::Test panic detected (exit code 2)" - return 2 - fi - - return $exit_code - } - - run_test + # Run tests with coverage for root gofr package only + go test -v -short -covermode=atomic -coverpkg=./pkg/gofr -coverprofile=gofr_only.cov ./pkg/gofr + # Run tests for all sub-packages under gofr + go test -v -covermode=atomic -coverpkg=./pkg/gofr -coverprofile=submodules.cov ./pkg/gofr/... + # Combine coverage profiles + echo "mode: atomic" > profile.cov + grep -h -v "mode:" gofr_only.cov submodules.cov | grep -v '/mock_' >> profile.cov + go tool cover -func profile.cov # Upload coverage report for the 1.24 Go version only - name: Upload Test Coverage @@ -182,11 +173,11 @@ jobs: needs: [ Example-Unit-Testing,PKG-Unit-Testing ] steps: - name: Check out code into the Go module directory - uses: actions/checkout@v5 + uses: actions/checkout@v4 # Download coverage reports from previous jobs - name: Download Coverage Report - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v4 with: path: artifacts @@ -222,7 +213,7 @@ jobs: steps: - name: Checkout code into go module directory - uses: actions/checkout@v5 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -294,11 +285,11 @@ jobs: # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development'}} # steps: # - name: Check out code into the Go module directory -# uses: actions/checkout@v5 +# uses: actions/checkout@v4 # # # Download coverage artifacts # - name: Download Coverage Report -# uses: actions/download-artifact@v5 +# uses: actions/download-artifact@v4 # with: # path: artifacts # @@ -330,7 +321,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v5 + uses: actions/checkout@v4 - name: Set up Go environment uses: actions/setup-go@v5 @@ -377,7 +368,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v5 + uses: actions/checkout@v4 - name: Set up Go environment uses: actions/setup-go@v5 From 2d27112098ae7c0c76065871578e48b62446416a Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Thu, 14 Aug 2025 11:20:49 +0530 Subject: [PATCH 6/8] revert extra changes --- .github/workflows/go.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index cd8901079..4a6677eb7 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -72,7 +72,7 @@ jobs: # Steps to execute for this job steps: - name: Checkout code into go module directory - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 # Full git history for accurate testing @@ -125,7 +125,7 @@ jobs: steps: - name: Checkout code into go module directory - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 @@ -173,11 +173,11 @@ jobs: needs: [ Example-Unit-Testing,PKG-Unit-Testing ] steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@v5 # Download coverage reports from previous jobs - name: Download Coverage Report - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: path: artifacts @@ -213,7 +213,7 @@ jobs: steps: - name: Checkout code into go module directory - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 @@ -285,11 +285,11 @@ jobs: # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development'}} # steps: # - name: Check out code into the Go module directory -# uses: actions/checkout@v4 +# uses: actions/checkout@v5 # # # Download coverage artifacts # - name: Download Coverage Report -# uses: actions/download-artifact@v4 +# uses: actions/download-artifact@v5 # with: # path: artifacts # @@ -321,7 +321,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Go environment uses: actions/setup-go@v5 @@ -368,7 +368,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Go environment uses: actions/setup-go@v5 From f4a9ae7951818e5f3e1ae20a5b074febbae6d843 Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Tue, 19 Aug 2025 14:52:58 +0530 Subject: [PATCH 7/8] fixed tests --- pkg/gofr/context_test.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pkg/gofr/context_test.go b/pkg/gofr/context_test.go index 226695419..1851a5522 100644 --- a/pkg/gofr/context_test.go +++ b/pkg/gofr/context_test.go @@ -255,14 +255,9 @@ func TestContext_GetCorrelationID(t *testing.T) { // Test GetCorrelationID correlationID := gofCtx.GetCorrelationID() - // Verify result - if len(correlationID) != 32 { - t.Errorf("Expected correlation ID length 32, got %d", len(correlationID)) - } + assert.Len(t, gofCtx.GetCorrelationID(), 32, "Expected correlation ID length 32, got %d", len(correlationID)) - if correlationID == "00000000000000000000000000000000" { - t.Error("Expected non-empty correlation ID") - } + assert.NotEqual(t, "00000000000000000000000000000000", correlationID, "Expected non-empty correlation ID") } func TestContext_GetCorrelationID_NoSpan(t *testing.T) { From c0d09409178bc958b3ce53c48c1cae70970092a3 Mon Sep 17 00:00:00 2001 From: coolwednesday Date: Thu, 21 Aug 2025 15:19:07 +0530 Subject: [PATCH 8/8] refactored tests --- pkg/gofr/context_test.go | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/pkg/gofr/context_test.go b/pkg/gofr/context_test.go index 1851a5522..6b4bb63a8 100644 --- a/pkg/gofr/context_test.go +++ b/pkg/gofr/context_test.go @@ -241,36 +241,24 @@ func TestContext_GetCorrelationID(t *testing.T) { exporter := tracetest.NewInMemoryExporter() tp := trace.NewTracerProvider(trace.WithSyncer(exporter)) otel.SetTracerProvider(tp) - tracer := tp.Tracer("test") - ctx, span := tracer.Start(t.Context(), "test-span") - - defer span.End() - - // Create Context instance - gofCtx := &Context{ - Context: ctx, - } - - // Test GetCorrelationID - correlationID := gofCtx.GetCorrelationID() - assert.Len(t, gofCtx.GetCorrelationID(), 32, "Expected correlation ID length 32, got %d", len(correlationID)) + t.Run("with span", func(t *testing.T) { + ctx, span := tracer.Start(t.Context(), "test-span") + defer span.End() - assert.NotEqual(t, "00000000000000000000000000000000", correlationID, "Expected non-empty correlation ID") -} + gofCtx := &Context{Context: ctx} + correlationID := gofCtx.GetCorrelationID() -func TestContext_GetCorrelationID_NoSpan(t *testing.T) { - // Test with no span in context - gofCtx := &Context{ - Context: t.Context(), - } + assert.Len(t, correlationID, 32, "Expected correlation ID length 32, got %d", len(correlationID)) + assert.NotEqual(t, "00000000000000000000000000000000", correlationID, "Expected non-empty correlation ID") + }) - correlationID := gofCtx.GetCorrelationID() + t.Run("without span", func(t *testing.T) { + gofCtx := &Context{Context: t.Context()} + correlationID := gofCtx.GetCorrelationID() - // Should return empty TraceID - expected := "00000000000000000000000000000000" - if correlationID != expected { - t.Errorf("Expected %s, got %s", expected, correlationID) - } + expected := "00000000000000000000000000000000" + assert.Equal(t, expected, correlationID, "Expected empty TraceID when no span present") + }) }