From c0cab57c57b6922f87507da39479fa5a95abbb5c Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 6 Jan 2026 14:12:03 -0800 Subject: [PATCH 1/6] Fix `flow.json` fork field usage in `flow test --fork ` --- internal/test/test.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/internal/test/test.go b/internal/test/test.go index 71ef29b4e..83ba87ded 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -194,24 +194,35 @@ func testCode( // Resolve network labels using flow.json state resolveNetworkFromState := func(label string) (string, bool) { - network, err := state.Networks().ByName(strings.ToLower(strings.TrimSpace(label))) + normalizedLabel := strings.ToLower(strings.TrimSpace(label)) + network, err := state.Networks().ByName(normalizedLabel) if err != nil || network == nil { return "", false } - if strings.TrimSpace(network.Host) == "" { + + // If network has a fork, resolve the fork network's host + host := strings.TrimSpace(network.Host) + if network.Fork != "" { + forkName := strings.ToLower(strings.TrimSpace(network.Fork)) + forkNetwork, err := state.Networks().ByName(forkName) + if err == nil && forkNetwork != nil { + host = strings.TrimSpace(forkNetwork.Host) + } + } + + if host == "" { return "", false } // Track network resolution for current test file (indicates pragma-based fork usage) // Only track if it's not the default "testing" network - normalizedLabel := strings.ToLower(strings.TrimSpace(label)) if currentTestFile != "" && normalizedLabel != "testing" { if _, exists := fileNetworkResolutions[currentTestFile]; !exists { fileNetworkResolutions[currentTestFile] = normalizedLabel } } - return network.Host, true + return host, true } // Configure fork mode if requested From 21769f5f593ccdcd3d3e0873b2e32f98a45ffb8b Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 6 Jan 2026 14:17:20 -0800 Subject: [PATCH 2/6] prevent silent failure --- internal/test/test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/test/test.go b/internal/test/test.go index 83ba87ded..382879556 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -205,9 +205,10 @@ func testCode( if network.Fork != "" { forkName := strings.ToLower(strings.TrimSpace(network.Fork)) forkNetwork, err := state.Networks().ByName(forkName) - if err == nil && forkNetwork != nil { - host = strings.TrimSpace(forkNetwork.Host) + if err != nil { + return "", false } + host = strings.TrimSpace(forkNetwork.Host) } if host == "" { From e531939d6bb11303ce3e5a526b312dc3118a2835 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 6 Jan 2026 19:25:21 -0800 Subject: [PATCH 3/6] Add tests --- internal/test/test_test.go | 149 +++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/internal/test/test_test.go b/internal/test/test_test.go index af85a1d37..cfdabb6e5 100644 --- a/internal/test/test_test.go +++ b/internal/test/test_test.go @@ -900,3 +900,152 @@ func TestForkMode_AutodetectFailureRequiresExplicitNetwork(t *testing.T) { require.Error(t, err) assert.ErrorContains(t, err, "failed to get chain ID from fork host") } + +func TestNetworkForkResolution_Success(t *testing.T) { + t.Parallel() + + _, state, _ := util.TestMocks(t) + + // Add mainnet network with a host + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet", + Host: "access.mainnet.nodes.onflow.org:9000", + }) + + // Add mainnet-fork that references mainnet via Fork field (no host) + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet-fork", + Fork: "mainnet", + }) + + // Create a simple test that uses the test_fork pragma + testScript := []byte(` +#test_fork(network: "mainnet-fork", height: nil) + +import Test + +access(all) fun testSimple() { + Test.assert(true) +} +`) + + testFiles := map[string][]byte{ + "test_fork_resolution.cdc": testScript, + } + + result, err := testCode(testFiles, state, flagsTests{}) + + require.NoError(t, err) + require.Len(t, result.Results, 1) + assert.NoError(t, result.Results["test_fork_resolution.cdc"][0].Error) +} + +func TestNetworkForkResolution_ForkNetworkNotFound(t *testing.T) { + t.Parallel() + + _, state, _ := util.TestMocks(t) + + // Add mainnet-fork that references non-existent network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet-fork", + Fork: "nonexistent", + }) + + // Create a simple test that uses the fork network + testScript := []byte(` +#test_fork(network: "mainnet-fork", height: nil) + +import Test + +access(all) fun testSimple() { + Test.assert(true) +} +`) + + testFiles := map[string][]byte{ + "test_fork_missing.cdc": testScript, + } + + _, err := testCode(testFiles, state, flagsTests{}) + + require.Error(t, err) + assert.ErrorContains(t, err, "could not resolve network") +} + +func TestNetworkForkResolution_ForkNetworkHasNoHost(t *testing.T) { + t.Parallel() + + _, state, _ := util.TestMocks(t) + + // Add mainnet network with no host + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet", + }) + + // Add mainnet-fork that references mainnet with no host + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet-fork", + Fork: "mainnet", + }) + + // Create a simple test that uses the fork network + testScript := []byte(` +#test_fork(network: "mainnet-fork", height: nil) + +import Test + +access(all) fun testSimple() { + Test.assert(true) +} +`) + + testFiles := map[string][]byte{ + "test_fork_no_host.cdc": testScript, + } + + _, err := testCode(testFiles, state, flagsTests{}) + + require.Error(t, err) + assert.ErrorContains(t, err, "could not resolve network") +} + +func TestNetworkForkResolution_WithOwnHost(t *testing.T) { + t.Parallel() + + _, state, _ := util.TestMocks(t) + + // Add mainnet network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet", + Host: "access.mainnet.nodes.onflow.org:9000", + }) + + // Add mainnet-fork with its own host AND fork field + // Should use mainnet's host (from Fork) not its own + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet-fork", + Host: "127.0.0.1:3569", + Fork: "mainnet", + }) + + // Create a simple test that uses the fork network + testScript := []byte(` +#test_fork(network: "mainnet-fork", height: nil) + +import Test + +access(all) fun testSimple() { + Test.assert(true) +} +`) + + testFiles := map[string][]byte{ + "test_fork_with_host.cdc": testScript, + } + + result, err := testCode(testFiles, state, flagsTests{}) + + require.NoError(t, err) + require.Len(t, result.Results, 1) + assert.NoError(t, result.Results["test_fork_with_host.cdc"][0].Error) +} From e3f877bf1fb0910c3ee4e58afb06b0c61257d397 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 6 Jan 2026 19:42:30 -0800 Subject: [PATCH 4/6] Add alias resolution tests --- internal/test/test_test.go | 190 +++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/internal/test/test_test.go b/internal/test/test_test.go index cfdabb6e5..b21ea210e 100644 --- a/internal/test/test_test.go +++ b/internal/test/test_test.go @@ -1049,3 +1049,193 @@ access(all) fun testSimple() { require.Len(t, result.Results, 1) assert.NoError(t, result.Results["test_fork_with_host.cdc"][0].Error) } + +func TestContractAddressForkResolution_UsesMainnetForkFirst(t *testing.T) { + t.Parallel() + + _, state, _ := util.TestMocks(t) + + // Add mainnet network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet", + Host: "access.mainnet.nodes.onflow.org:9000", + }) + + // Add mainnet-fork network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet-fork", + Fork: "mainnet", + }) + + // Contract with mainnet-fork specific alias (using proper mainnet-style address) + mainnetForkAddr := flowsdk.HexToAddress("0x1654653399040a61") + contractSource := []byte(` +access(all) contract TestContract { + access(all) var value: Int + init() { self.value = 42 } +} +`) + _ = state.ReaderWriter().WriteFile("TestContract.cdc", contractSource, 0644) + + c := config.Contract{ + Name: "TestContract", + Location: "TestContract.cdc", + Aliases: config.Aliases{ + { + Network: "mainnet-fork", + Address: mainnetForkAddr, + }, + }, + } + state.Contracts().AddOrUpdate(c) + + testScript := []byte(` +#test_fork(network: "mainnet-fork", height: nil) + +import Test +import "TestContract" + +access(all) fun testUsesMainnetForkAddress() { + Test.assert(true) +} +`) + + testFiles := map[string][]byte{ + "test_mainnet_fork_addr.cdc": testScript, + } + + result, err := testCode(testFiles, state, flagsTests{}) + + require.NoError(t, err) + require.Len(t, result.Results, 1) + assert.NoError(t, result.Results["test_mainnet_fork_addr.cdc"][0].Error) +} + +func TestContractAddressForkResolution_FallbackToMainnet(t *testing.T) { + t.Parallel() + + _, state, _ := util.TestMocks(t) + + // Add mainnet network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet", + Host: "access.mainnet.nodes.onflow.org:9000", + }) + + // Add mainnet-fork network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet-fork", + Fork: "mainnet", + }) + + // Contract with ONLY mainnet alias (no mainnet-fork alias) + mainnetAddr := flowsdk.HexToAddress("0xf233dcee88fe0abe") + contractSource := []byte(` +access(all) contract TestContract { + access(all) var value: Int + init() { self.value = 99 } +} +`) + _ = state.ReaderWriter().WriteFile("TestContract.cdc", contractSource, 0644) + + c := config.Contract{ + Name: "TestContract", + Location: "TestContract.cdc", + Aliases: config.Aliases{ + { + Network: "mainnet", + Address: mainnetAddr, + }, + }, + } + state.Contracts().AddOrUpdate(c) + + testScript := []byte(` +#test_fork(network: "mainnet-fork", height: nil) + +import Test +import "TestContract" + +access(all) fun testFallbackToMainnetAddress() { + Test.assert(true) +} +`) + + testFiles := map[string][]byte{ + "test_fallback_mainnet.cdc": testScript, + } + + result, err := testCode(testFiles, state, flagsTests{}) + + require.NoError(t, err) + require.Len(t, result.Results, 1) + assert.NoError(t, result.Results["test_fallback_mainnet.cdc"][0].Error) +} + +func TestContractAddressForkResolution_PrioritizesForkOverParent(t *testing.T) { + t.Parallel() + + _, state, _ := util.TestMocks(t) + + // Add mainnet network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet", + Host: "access.mainnet.nodes.onflow.org:9000", + }) + + // Add mainnet-fork network + state.Networks().AddOrUpdate(config.Network{ + Name: "mainnet-fork", + Fork: "mainnet", + }) + + // Contract with BOTH mainnet and mainnet-fork aliases - should use mainnet-fork first + mainnetAddr := flowsdk.HexToAddress("0x1654653399040a61") + mainnetForkAddr := flowsdk.HexToAddress("0xf233dcee88fe0abe") + + contractSource := []byte(` +access(all) contract TestContract { + access(all) var value: Int + init() { self.value = 123 } +} +`) + _ = state.ReaderWriter().WriteFile("TestContract.cdc", contractSource, 0644) + + c := config.Contract{ + Name: "TestContract", + Location: "TestContract.cdc", + Aliases: config.Aliases{ + { + Network: "mainnet", + Address: mainnetAddr, + }, + { + Network: "mainnet-fork", + Address: mainnetForkAddr, + }, + }, + } + state.Contracts().AddOrUpdate(c) + + // Should use the mainnet-fork address (0xf233dcee88fe0abe), not mainnet (0x1654653399040a61) + testScript := []byte(` +#test_fork(network: "mainnet-fork", height: nil) + +import Test +import "TestContract" + +access(all) fun testPrioritizesFork() { + Test.assert(true) +} +`) + + testFiles := map[string][]byte{ + "test_priority.cdc": testScript, + } + + result, err := testCode(testFiles, state, flagsTests{}) + + require.NoError(t, err) + require.Len(t, result.Results, 1) + assert.NoError(t, result.Results["test_priority.cdc"][0].Error) +} From f2e590edab04254221e726c7eb12b51701bdd349 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 6 Jan 2026 22:17:05 -0800 Subject: [PATCH 5/6] Add more test assertions --- internal/test/test_test.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/internal/test/test_test.go b/internal/test/test_test.go index b21ea210e..a205ab6de 100644 --- a/internal/test/test_test.go +++ b/internal/test/test_test.go @@ -1005,8 +1005,9 @@ access(all) fun testSimple() { _, err := testCode(testFiles, state, flagsTests{}) + // Should fail with network resolution error require.Error(t, err) - assert.ErrorContains(t, err, "could not resolve network") + assert.ErrorContains(t, err, "network resolver could not resolve network") } func TestNetworkForkResolution_WithOwnHost(t *testing.T) { @@ -1096,7 +1097,9 @@ import Test import "TestContract" access(all) fun testUsesMainnetForkAddress() { - Test.assert(true) + // Verify TestContract resolves to the mainnet-fork address + let addr = Type().address! + Test.assertEqual(0x1654653399040a61 as Address, addr) } `) @@ -1157,7 +1160,9 @@ import Test import "TestContract" access(all) fun testFallbackToMainnetAddress() { - Test.assert(true) + // Verify TestContract falls back to mainnet address since mainnet-fork has no alias + let addr = Type().address! + Test.assertEqual(0xf233dcee88fe0abe as Address, addr) } `) @@ -1225,7 +1230,9 @@ import Test import "TestContract" access(all) fun testPrioritizesFork() { - Test.assert(true) + // Verify TestContract uses mainnet-fork address (0xf233dcee88fe0abe), NOT mainnet (0x1654653399040a61) + let addr = Type().address! + Test.assertEqual(0xf233dcee88fe0abe as Address, addr) } `) From 579d98f797080d29c5ac41caa923754de6ce3da0 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 6 Jan 2026 22:36:20 -0800 Subject: [PATCH 6/6] Fix windows test --- internal/test/test_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/test/test_test.go b/internal/test/test_test.go index a205ab6de..86ba69e70 100644 --- a/internal/test/test_test.go +++ b/internal/test/test_test.go @@ -1065,6 +1065,7 @@ func TestContractAddressForkResolution_UsesMainnetForkFirst(t *testing.T) { // Add mainnet-fork network state.Networks().AddOrUpdate(config.Network{ Name: "mainnet-fork", + Host: "127.0.0.1:3569", Fork: "mainnet", }) @@ -1128,6 +1129,7 @@ func TestContractAddressForkResolution_FallbackToMainnet(t *testing.T) { // Add mainnet-fork network state.Networks().AddOrUpdate(config.Network{ Name: "mainnet-fork", + Host: "127.0.0.1:3569", Fork: "mainnet", }) @@ -1191,6 +1193,7 @@ func TestContractAddressForkResolution_PrioritizesForkOverParent(t *testing.T) { // Add mainnet-fork network state.Networks().AddOrUpdate(config.Network{ Name: "mainnet-fork", + Host: "127.0.0.1:3569", Fork: "mainnet", })