Skip to content

Commit db0959a

Browse files
committed
test: detect and fix goroutine leaks with goleak
Add goleak.VerifyTestMain to every test package as a regression fence against goroutine leaks. Where leaks were detected, fix them at the source rather than ignoring globally: - pkg/attestation: refactor AttestationVerifier to track owned http.Transport and JWK cache; add idempotent Close() that drains the worker pool and closes idle connections. - internal/tests/anvil.go: drain readiness-probe response body before returning to the idle pool; centralize transport-clone via CloneDefaultTransport helper. - pkg/transportSigner/web3TransportSigner: track http.Transport in test helpers via newTrackedWeb3SignerClient for goleak cleanup. - pkg/blockHandler: ensure ListenToChannel goroutines exit cleanly before tests return. Permanent third-party leaks (glog flushDaemon, hashicorp LRU eviction) are scoped via goleak.IgnoreAnyFunction in the affected packages rather than file-level globals.
1 parent 04f8e78 commit db0959a

34 files changed

Lines changed: 488 additions & 29 deletions

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ require (
2222
github.com/stretchr/testify v1.11.1
2323
github.com/urfave/cli/v2 v2.27.7
2424
github.com/wealdtech/go-merkletree/v2 v2.6.1
25+
go.uber.org/goleak v1.3.0
2526
go.uber.org/zap v1.27.1
2627
golang.org/x/crypto v0.48.0
2728
golang.org/x/time v0.9.0
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package localKeyGenerator
2+
3+
import (
4+
"testing"
5+
6+
"go.uber.org/goleak"
7+
)
8+
9+
func TestMain(m *testing.M) {
10+
goleak.VerifyTestMain(m)
11+
}

internal/tests/anvil.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tests
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"net/http"
78
"os"
89
"os/exec"
@@ -14,6 +15,19 @@ import (
1415
"github.com/Layr-Labs/chain-indexer/pkg/clients/ethereum"
1516
)
1617

18+
// CloneDefaultTransport returns a clone of http.DefaultTransport when it is
19+
// the standard *http.Transport, or a fresh *http.Transport otherwise. Tests
20+
// use this to install an owned transport whose idle connections can be torn
21+
// down deterministically (for goleak), without panicking if an application
22+
// has installed a non-standard DefaultTransport (e.g. an instrumented or
23+
// wrapping transport).
24+
func CloneDefaultTransport() *http.Transport {
25+
if dt, ok := http.DefaultTransport.(*http.Transport); ok {
26+
return dt.Clone()
27+
}
28+
return &http.Transport{}
29+
}
30+
1731
type AnvilConfig struct {
1832
ForkUrl string `json:"forkUrl"`
1933
ForkBlockNumber string `json:"forkBlockNumber"`
@@ -50,11 +64,24 @@ func StartAnvil(projectRoot string, ctx context.Context, cfg *AnvilConfig) (*exe
5064

5165
rpcUrl := fmt.Sprintf("http://localhost:%s", cfg.PortNumber)
5266

67+
// Use a dedicated transport whose idle connections we tear down before
68+
// returning — http.DefaultClient would leak persistConn goroutines past
69+
// the caller's lifetime (goleak would report them).
70+
readinessTransport := CloneDefaultTransport()
71+
readinessClient := &http.Client{Transport: readinessTransport, Timeout: 5 * time.Second}
72+
defer readinessTransport.CloseIdleConnections()
73+
5374
for i := 1; i < 10; i++ {
54-
res, err := http.Post(rpcUrl, "application/json", nil)
55-
if err == nil && res.StatusCode == 200 {
56-
fmt.Println("Anvil is up and running")
57-
return cmd, nil
75+
res, err := readinessClient.Post(rpcUrl, "application/json", nil)
76+
if err == nil {
77+
// Drain the response body before closing so the TCP connection can
78+
// be returned to the idle pool cleanly instead of being RST-torn.
79+
_, _ = io.Copy(io.Discard, res.Body)
80+
_ = res.Body.Close()
81+
if res.StatusCode == 200 {
82+
fmt.Println("Anvil is up and running")
83+
return cmd, nil
84+
}
5885
}
5986
fmt.Printf("Anvil not ready yet, retrying... %d\n", i)
6087
time.Sleep(time.Second * time.Duration(i))
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package integration
2+
3+
import (
4+
"testing"
5+
6+
"go.uber.org/goleak"
7+
)
8+
9+
func TestMain(m *testing.M) {
10+
goleak.VerifyTestMain(m)
11+
}

internal/tests/integration/onchain_integration_test.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package integration
22

33
import (
44
"context"
5+
"net/http"
56
"sync"
67
"testing"
78
"time"
@@ -84,6 +85,13 @@ func Test_OnChainIntegration(t *testing.T) {
8485
BlockType: ethereum.BlockType_Latest,
8586
}, l)
8687

88+
// Install an owned HTTP transport so CloseIdleConnections can tear down
89+
// the persistConn read/write loop goroutines that the RPC polling loop
90+
// creates (otherwise goleak flags them when the test exits).
91+
l1RpcTransport := tests.CloneDefaultTransport()
92+
l1Client.SetHttpClient(&http.Client{Transport: l1RpcTransport, Timeout: 10 * time.Second})
93+
t.Cleanup(l1RpcTransport.CloseIdleConnections)
94+
8795
anvilWg := &sync.WaitGroup{}
8896
anvilWg.Add(1)
8997
startErrorsChan := make(chan error, 1)
@@ -125,6 +133,10 @@ func Test_OnChainIntegration(t *testing.T) {
125133
BlockType: ethereum.BlockType_Latest,
126134
}, l)
127135

136+
l2RpcTransport := tests.CloneDefaultTransport()
137+
l2Client.SetHttpClient(&http.Client{Transport: l2RpcTransport, Timeout: 10 * time.Second})
138+
t.Cleanup(l2RpcTransport.CloseIdleConnections)
139+
128140
anvilWg2 := &sync.WaitGroup{}
129141
anvilWg2.Add(1)
130142
startErrorsChan2 := make(chan error, 1)
@@ -149,6 +161,7 @@ func Test_OnChainIntegration(t *testing.T) {
149161
// ------------------------------------------------------------------------
150162
l1EthClient, err := l1Client.GetEthereumContractCaller()
151163
require.NoError(t, err)
164+
t.Cleanup(l1EthClient.Close)
152165

153166
l1ContractCaller, err := caller.NewContractCaller(l1EthClient, nil, l)
154167
require.NoError(t, err)
@@ -182,8 +195,14 @@ func Test_OnChainIntegration(t *testing.T) {
182195
BaseUrl: L2RpcUrl,
183196
BlockType: ethereum.BlockType_Latest,
184197
}, l)
198+
199+
nodeL2RpcTransport := tests.CloneDefaultTransport()
200+
nodeL2Client.SetHttpClient(&http.Client{Transport: nodeL2RpcTransport, Timeout: 10 * time.Second})
201+
t.Cleanup(nodeL2RpcTransport.CloseIdleConnections)
202+
185203
nodeL2EthClient, err := nodeL2Client.GetEthereumContractCaller()
186204
require.NoError(t, err)
205+
t.Cleanup(nodeL2EthClient.Close)
187206

188207
// Create block handler and chain poller for each node
189208
bh := blockHandler.NewBlockHandler(l)
@@ -222,6 +241,10 @@ func Test_OnChainIntegration(t *testing.T) {
222241
l.Sugar().Fatalw("Failed to create Web3Signer client", "error", err)
223242
}
224243

244+
w3sTransport := tests.CloneDefaultTransport()
245+
web3SignerClient.SetHttpClient(&http.Client{Transport: w3sTransport, Timeout: 10 * time.Second})
246+
t.Cleanup(w3sTransport.CloseIdleConnections)
247+
225248
txSigner, err = transactionSigner.NewWeb3TransactionSigner(web3SignerClient, common.HexToAddress(operatorConfigs[i].address), nodeL2EthClient, l)
226249
require.NoError(t, err)
227250

@@ -330,12 +353,19 @@ func Test_OnChainIntegration(t *testing.T) {
330353
// ------------------------------------------------------------------------
331354
t.Log("Using KMSClient to get master public key...")
332355

333-
// Create KMS client with contract caller for fetching operators on-demand
356+
// Create KMS client with contract caller for fetching operators on-demand.
357+
// Provide an owned HTTP transport so idle persistConn goroutines created
358+
// for the node-facing /pubkey and /app/sign calls can be torn down at
359+
// test end (goleak would otherwise flag them).
360+
kmsHttpTransport := tests.CloneDefaultTransport()
361+
t.Cleanup(kmsHttpTransport.CloseIdleConnections)
362+
334363
client, err := kmsClient.NewClient(&kmsClient.ClientConfig{
335364
AVSAddress: chainConfig.AVSAccountAddress,
336365
OperatorSetID: 0,
337366
Logger: l,
338367
ContractCaller: l1ContractCaller,
368+
HTTPClient: &http.Client{Transport: kmsHttpTransport, Timeout: 30 * time.Second},
339369
})
340370
require.NoError(t, err)
341371

internal/tests/integration/real_node_ibe_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package integration
22

33
import (
44
"fmt"
5+
"net/http"
56
"testing"
7+
"time"
68

79
"github.com/ethereum/go-ethereum/common"
810
"github.com/stretchr/testify/require"
911

12+
"github.com/Layr-Labs/eigenx-kms-go/internal/tests"
1013
"github.com/Layr-Labs/eigenx-kms-go/pkg/clients/kmsClient"
1114
"github.com/Layr-Labs/eigenx-kms-go/pkg/logger"
1215
"github.com/Layr-Labs/eigenx-kms-go/pkg/peering"
@@ -31,12 +34,18 @@ func Test_IBEIntegration(t *testing.T) {
3134
operatorAddresses: operatorAddresses,
3235
}
3336

34-
// Create KMS client with mock contract caller for testing
37+
// Create KMS client with mock contract caller for testing.
38+
// Provide an owned HTTP transport so idle persistConn goroutines created
39+
// for calls to the test cluster can be torn down at test end.
40+
kmsHttpTransport := tests.CloneDefaultTransport()
41+
t.Cleanup(kmsHttpTransport.CloseIdleConnections)
42+
3543
client, err := kmsClient.NewClient(&kmsClient.ClientConfig{
3644
AVSAddress: "0x0000000000000000000000000000000000000000", // Mock address for test
3745
OperatorSetID: 0,
3846
Logger: clientLogger,
3947
ContractCaller: mockContractCaller,
48+
HTTPClient: &http.Client{Transport: kmsHttpTransport, Timeout: 30 * time.Second},
4049
})
4150
require.NoError(t, err)
4251

pkg/attestation/attestation.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
"encoding/json"
66
"fmt"
77
"log/slog"
8+
"net/http"
89
"slices"
910
"strings"
11+
"sync"
1012
"time"
1113

1214
"github.com/Layr-Labs/eigenx-kms-go/pkg/types"
@@ -90,21 +92,46 @@ type AttestationVerifier struct {
9092
intelJwksCache jwk.Set
9193
projectID string
9294
debugMode bool
95+
cancel context.CancelFunc
96+
httpTransport *http.Transport
97+
closeOnce sync.Once
9398
}
9499

95100
func NewAttestationVerifier(ctx context.Context, logger *slog.Logger, projectID string, refreshInterval time.Duration, debugMode bool) (*AttestationVerifier, error) {
96101
avLogger := logger.With("component", "attestation_verifier")
97102
avLogger.Debug("Initializing attestation verifier", "project_id", projectID, "refresh_interval", refreshInterval)
98103

104+
// Derive a cancellable context owned by the verifier so JWK cache workers
105+
// (httprc/v3) can be shut down via Close() in addition to parent cancellation.
106+
cacheCtx, cancel := context.WithCancel(ctx)
107+
108+
// Own the HTTP transport so Close() can tear down idle connections and the
109+
// associated read/write loop goroutines. Using DefaultClient (httprc's default)
110+
// leaks persistent HTTP/2 read loops past context cancellation.
111+
// Guard the type assertion: an application can install a custom
112+
// http.DefaultTransport (e.g. an instrumented transport) that is not a
113+
// *http.Transport, and blind assertion would panic.
114+
var transport *http.Transport
115+
if dt, ok := http.DefaultTransport.(*http.Transport); ok {
116+
transport = dt.Clone()
117+
} else {
118+
transport = &http.Transport{}
119+
}
120+
httpClient := &http.Client{Transport: transport}
121+
99122
avLogger.Debug("Creating Google Confidential Space JWK cache", "jwk_url", confidentialSpaceJWKURL)
100-
googleJwksCache, err := NewJWKCache(ctx, confidentialSpaceJWKURL, refreshInterval)
123+
googleJwksCache, err := newJWKCacheWithClient(cacheCtx, confidentialSpaceJWKURL, refreshInterval, httpClient)
101124
if err != nil {
125+
cancel()
126+
transport.CloseIdleConnections()
102127
return nil, fmt.Errorf("failed to create Google JWK cache: %w", err)
103128
}
104129

105130
avLogger.Debug("Creating Intel Trust Authority JWK cache", "jwk_url", intelTrustAuthorityJWKURL)
106-
intelJwksCache, err := NewJWKCache(ctx, intelTrustAuthorityJWKURL, refreshInterval)
131+
intelJwksCache, err := newJWKCacheWithClient(cacheCtx, intelTrustAuthorityJWKURL, refreshInterval, httpClient)
107132
if err != nil {
133+
cancel()
134+
transport.CloseIdleConnections()
108135
return nil, fmt.Errorf("failed to create Intel JWK cache: %w", err)
109136
}
110137

@@ -116,9 +143,25 @@ func NewAttestationVerifier(ctx context.Context, logger *slog.Logger, projectID
116143
googleJwksCache: googleJwksCache,
117144
intelJwksCache: intelJwksCache,
118145
debugMode: debugMode,
146+
cancel: cancel,
147+
httpTransport: transport,
119148
}, nil
120149
}
121150

151+
// Close stops the background JWK cache workers spawned by the verifier and
152+
// releases pooled HTTP connections. Safe to call multiple times and safe to
153+
// call concurrently from multiple goroutines.
154+
func (av *AttestationVerifier) Close() {
155+
av.closeOnce.Do(func() {
156+
if av.cancel != nil {
157+
av.cancel()
158+
}
159+
if av.httpTransport != nil {
160+
av.httpTransport.CloseIdleConnections()
161+
}
162+
})
163+
}
164+
122165
func (av *AttestationVerifier) VerifyAttestation(ctx context.Context, tokenString string, provider AttestationProvider) (*types.AttestationClaims, error) {
123166
av.logger.Debug("Starting attestation verification", "token_length", len(tokenString), "provider", provider)
124167

@@ -364,14 +407,34 @@ func extractAppIDFromInstanceName(instanceName string) (string, error) {
364407
return instanceNameParts[len(instanceNameParts)-1], nil
365408
}
366409

410+
// NewJWKCache creates a JWK set backed by a periodic refresh worker.
411+
//
412+
// The background worker goroutines and their HTTP idle connections are tied
413+
// to ctx — cancel it to stop them. Callers that need deterministic teardown
414+
// of pooled HTTP connections (e.g. short-lived tests or a short-lived verifier
415+
// lifecycle separate from process shutdown) should not use this function
416+
// directly; instead they should manage the HTTP transport themselves and use
417+
// AttestationVerifier, which closes idle connections on Close().
367418
func NewJWKCache(ctx context.Context, jwkUrl string, refreshInterval time.Duration) (jwk.Set, error) {
419+
return newJWKCacheWithClient(ctx, jwkUrl, refreshInterval, nil)
420+
}
421+
422+
// newJWKCacheWithClient is like NewJWKCache but lets the caller supply the HTTP
423+
// client used to fetch the JWK set. Passing a non-nil client lets the caller
424+
// own its transport and close idle connections when the cache is no longer
425+
// needed, preventing leaked HTTP read/write loop goroutines.
426+
func newJWKCacheWithClient(ctx context.Context, jwkUrl string, refreshInterval time.Duration, httpClient *http.Client) (jwk.Set, error) {
368427
cache, err := jwk.NewCache(ctx, httprc.NewClient())
369428
if err != nil {
370429
return nil, fmt.Errorf("failed to create jwk cache: %w", err)
371430
}
372431

373432
// register a constant refresh interval for this URL.
374-
err = cache.Register(ctx, jwkUrl, jwk.WithConstantInterval(refreshInterval))
433+
registerOpts := []jwk.RegisterOption{jwk.WithConstantInterval(refreshInterval)}
434+
if httpClient != nil {
435+
registerOpts = append(registerOpts, jwk.WithHTTPClient(httpClient))
436+
}
437+
err = cache.Register(ctx, jwkUrl, registerOpts...)
375438
if err != nil {
376439
return nil, fmt.Errorf("failed to register jwk location: %w", err)
377440
}

pkg/attestation/attestation_test.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import (
66
"crypto/rsa"
77
"encoding/json"
88
"log/slog"
9+
"net/http"
910
"os"
1011
"testing"
1112
"time"
1213

14+
"github.com/Layr-Labs/eigenx-kms-go/internal/tests"
1315
"github.com/lestrrat-go/jwx/v3/jwa"
1416
"github.com/lestrrat-go/jwx/v3/jwk"
1517
"github.com/lestrrat-go/jwx/v3/jwt"
@@ -244,6 +246,7 @@ func TestNewAttestationVerifier(t *testing.T) {
244246
verifier, err := NewAttestationVerifier(ctx, logger, "test-project", time.Minute, false)
245247
require.NoError(t, err)
246248
require.NotNil(t, verifier)
249+
t.Cleanup(verifier.Close)
247250
require.Equal(t, "test-project", verifier.projectID)
248251
require.False(t, verifier.debugMode)
249252
})
@@ -253,6 +256,7 @@ func TestNewAttestationVerifier(t *testing.T) {
253256
verifier, err := NewAttestationVerifier(ctx, logger, "test-project", time.Minute, true)
254257
require.NoError(t, err)
255258
require.NotNil(t, verifier)
259+
t.Cleanup(verifier.Close)
256260
require.Equal(t, "test-project", verifier.projectID)
257261
require.True(t, verifier.debugMode)
258262
})
@@ -578,15 +582,22 @@ func TestInstanceNameParsing(t *testing.T) {
578582
}
579583

580584
func TestFilterIntelJWKS(t *testing.T) {
581-
ctx := context.Background()
585+
ctx, cancel := context.WithCancel(context.Background())
586+
t.Cleanup(cancel)
582587
logger := setupLogger()
583588

589+
// Own the HTTP transport so goroutines started by the JWK fetch can be
590+
// fully torn down via CloseIdleConnections after the test.
591+
transport := tests.CloneDefaultTransport()
592+
httpClient := &http.Client{Transport: transport}
593+
t.Cleanup(transport.CloseIdleConnections)
594+
584595
// Real Intel token with RS256 algorithm
585596
realToken := "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vcG9ydGFsLnRydXN0YXV0aG9yaXR5LmludGVsLmNvbS9jZXJ0cyIsImtpZCI6ImQxNTU0ZTBhYTJlOWViODZlNzdmNDFlMjQ3NTllNzcxMmVkNDI0YjM2NWZmMjBhMjJhZDFjMmUzYzdjNjA0NTVhYzY3YWU2YzJlN2IyNTZmN2I3NjgwMDlhYjg4MDgxYiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJFaWdlblggS01TIiwiZGJnc3RhdCI6ImRpc2FibGVkLXNpbmNlLWJvb3QiLCJlYXRfbm9uY2UiOlsiOWNjYjY1MmIzOTYzOWVkODE2Yzg4NjBiMzNlNDVmMmFiZjc4ODBlZWUyNWRiN2ZkMGUzYjZiZTc4ZGU1M2NiMyJdLCJlYXRfcHJvZmlsZSI6Imh0dHBzOi8vcG9ydGFsLnRydXN0YXV0aG9yaXR5LmludGVsLmNvbS9lYXRfcHJvZmlsZS5odG1sIiwiZ29vZ2xlX3NlcnZpY2VfYWNjb3VudHMiOlsidGVlLWluc3RhbmNlLXYyLXNlcG9saWEtZGV2QHRlZS1jb21wdXRlLXNlcG9saWEtZGV2LmlhbS5nc2VydmljZWFjY291bnQuY29tIl0sImh3bW9kZWwiOiJJTlRFTF9URFgiLCJvZW1pZCI6MTExMjksInNlY2Jvb3QiOnRydWUsInN1YiI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2NvbXB1dGUvdjEvcHJvamVjdHMvdGVlLWNvbXB1dGUtc2Vwb2xpYS1kZXYvem9uZXMvdXMtZWFzdDEtYy9pbnN0YW5jZXMvdGVlLTB4ZTU3NzBiNmRlMmVjZTYxMDBmYzcxZTk0YmMzMzExMjY0NWY5MmVjYSIsInN1Ym1vZHMiOnsiY29uZmlkZW50aWFsX3NwYWNlIjp7Im1vbml0b3JpbmdfZW5hYmxlZCI6eyJtZW1vcnkiOmZhbHNlfSwic3VwcG9ydF9hdHRyaWJ1dGVzIjpbIkVYUEVSSU1FTlRBTCJdfSwiY29udGFpbmVyIjp7ImFyZ3MiOlsiL3Vzci9sb2NhbC9iaW4vY29tcHV0ZS1zb3VyY2UtZW52LnNoIiwibnBtIiwic3RhcnQiXSwiZW52Ijp7IkhPU1ROQU1FIjoidGVlLTB4ZTU3NzBiNmRlMmVjZTYxMDBmYzcxZTk0YmMzMzExMjY0NWY5MmVjYSIsIk5PREVfVkVSU0lPTiI6IjE4LjIwLjgiLCJQQVRIIjoiL3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIiwiWUFSTl9WRVJTSU9OIjoiMS4yMi4yMiJ9LCJpbWFnZV9kaWdlc3QiOiJzaGEyNTY6MTg5MzBkMDU5YzI2YjRmNDkyOTBiYzA2ZjVjMzExZmQzMjNhMTExMzA0MjUxNDk2ZTE4MTcyYjMyOTA3ZjYyYSIsImltYWdlX2lkIjoic2hhMjU2OjJmYThmZWI1ODAxMGVlMmE4ZWIxN2RlNjBjZjhhMGE4Zjg0MjY0YzNiZmU0ZTQ1YjI4ZDNkNzlmZGNhZWY2NTgiLCJpbWFnZV9yZWZlcmVuY2UiOiJpbmRleC5kb2NrZXIuaW8vc2F1Y2Vsb3JkL215LXRzLWFwcEBzaGEyNTY6MTg5MzBkMDU5YzI2YjRmNDkyOTBiYzA2ZjVjMzExZmQzMjNhMTExMzA0MjUxNDk2ZTE4MTcyYjMyOTA3ZjYyYSIsInJlc3RhcnRfcG9saWN5IjoiTmV2ZXIifSwiZ2NlIjp7Imluc3RhbmNlX2lkIjoiNzAxNTIzMTk4MTgzNjcxNzIwNiIsImluc3RhbmNlX25hbWUiOiJ0ZWUtMHhlNTc3MGI2ZGUyZWNlNjEwMGZjNzFlOTRiYzMzMTEyNjQ1ZjkyZWNhIiwicHJvamVjdF9pZCI6InRlZS1jb21wdXRlLXNlcG9saWEtZGV2IiwicHJvamVjdF9udW1iZXIiOiI2MTcyMjc5MDM2NjgiLCJ6b25lIjoidXMtZWFzdDEtYyJ9fSwic3duYW1lIjoiQ09ORklERU5USUFMX1NQQUNFIiwic3d2ZXJzaW9uIjpbIjI1MDUwMSJdLCJ0ZHgiOnsiYXR0ZXN0ZXJfdGNiX2RhdGUiOiIyMDI1LTA1LTE0VDAwOjAwOjAwWiIsImF0dGVzdGVyX3RjYl9zdGF0dXMiOiJPdXRPZkRhdGUiLCJnY3BfYXR0ZXN0ZXJfdGNiX2RhdGUiOiIyMDI0LTAzLTEzVDAwOjAwOjAwWiIsImdjcF9hdHRlc3Rlcl90Y2Jfc3RhdHVzIjoiVXBUb0RhdGUifSwidmVyaWZpZXJfaW5zdGFuY2VfaWRzIjpbIjM2Nzc5ZjAyLWY4MDYtNDY2MS04ZmU5LTI2MDU4NjA4NWI3NiIsIjVjM2I5OTYzLTIzYmYtNGI1NS05YjEwLTJjMjNhZWU2OWVmMyIsIjAzNzY3ZWNkLTliNTMtNDEyNC05MGQ3LTkyMzg0MGRkOWNhNyIsIjE1OTVmNzhiLTBiYTgtNDc1Yi1iMWZlLTg1ZmNiOGYyZjkyZSIsIjRhZWMyNmVkLTQ0M2ItNDAyYS04YWY4LWFlYjlmYzYwYmE3ZiIsImMzY2I5MzM4LThkZTQtNDUwNS1iM2M4LWNjMTNkNGQyZDAwYSIsIjE2MmMxNzE0LTY3Y2YtNDU3Yi05M2RmLWJiNWY4NTcxNjBlMCJdLCJleHAiOjE3NjEzNDI0MzAsImp0aSI6IjY0YWVhYmQ3LTlmOTctNGFjZS05MGZmLTBmMTU1OWI4OGNjZCIsImlhdCI6MTc2MTM0MjEzMCwiaXNzIjoiaHR0cHM6Ly9wb3J0YWwudHJ1c3RhdXRob3JpdHkuaW50ZWwuY29tIiwibmJmIjoxNzYxMzQyMTMwfQ.WwPSo7PkiKCNB5QeeQVP3c09b6054JLnXKCB4OpNKWqd-MJ_hwFHMQDRQcnD8urY6rlpNx9lAPjEJL66qGQY7GiSmPUWQ-xYKeX8wQYPVzhTxbC-2ckHeHaYOBPneI3ct1ryWvd_GTRJenM1CeDDAfhDz9xFNfqJYQZ2bY55Nf853TUjXFATKONutRRTVvxgx0b75wDz-PQcMSFAy73-AxnHJVEFqxqh1v3no5jsvAES7nxaFguHdxwB9Kuprs9UMklMsM8xXE3Gww_lYoPxjDYwG5aAmui9bOROGnUmPDPIazMWX5L2HDdXOyvt9iS9DXKk-R1DlsytG_SmpwpU3A6Abfjj7-fyOnYeXeDRebO9iNKzcBZN_w084XxtdFKyoPXynvJMCWMh0pcgByVHtyOXBd1BQ0yMRJ91cqmNLYcvlt-Qr9NzXxVzA3qHtDBTswbbwelnx6vETyzSTOhjfXuf7oCJqgfRVKdRYfTS9pFbaQo2Tjg_1Xdi15tDFbOf"
586597

587598
// Fetch the real Intel JWKS
588599
t.Logf("Fetching Intel JWKS from: %s", intelTrustAuthorityJWKURL)
589-
intelKeySet, err := NewJWKCache(ctx, intelTrustAuthorityJWKURL, time.Minute)
600+
intelKeySet, err := newJWKCacheWithClient(ctx, intelTrustAuthorityJWKURL, time.Minute, httpClient)
590601
require.NoError(t, err, "Failed to create Intel JWKS cache")
591602

592603
originalCount := intelKeySet.Len()

pkg/attestation/benchmark_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ func BenchmarkGCPMethodStub(b *testing.B) {
103103
if err != nil {
104104
b.Fatalf("Failed to create verifier: %v", err)
105105
}
106+
b.Cleanup(verifier.Close)
106107

107108
gcpMethod := NewGCPAttestationMethod(verifier, GoogleConfidentialSpace)
108109

0 commit comments

Comments
 (0)