Skip to content

Commit c0bbc71

Browse files
committed
Add tests
1 parent 3521470 commit c0bbc71

File tree

5 files changed

+518
-6
lines changed

5 files changed

+518
-6
lines changed

lib/config/testconfig_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package config
22

33
import (
44
"errors"
5+
"fmt"
56
"os"
67
"reflect"
78
"testing"
89

910
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr"
11+
"github.com/stretchr/testify/require"
1012
)
1113

1214
func TestReadConfigValuesFromEnvVars(t *testing.T) {
@@ -123,3 +125,106 @@ func TestReadConfigValuesFromEnvVars(t *testing.T) {
123125
func newString(s string) *string {
124126
return &s
125127
}
128+
129+
func TestValidateNetworkConfig(t *testing.T) {
130+
testCases := []struct {
131+
name string
132+
networkConfig NetworkConfig
133+
expectedError error
134+
}{
135+
{
136+
name: "Valid configuration with HTTP and WS URLs",
137+
networkConfig: NetworkConfig{
138+
SelectedNetworks: []string{"MAINNET"},
139+
RpcHttpUrls: map[string][]string{
140+
"MAINNET": {"http://localhost:8545"},
141+
},
142+
RpcWsUrls: map[string][]string{
143+
"MAINNET": {"ws://localhost:8546"},
144+
},
145+
WalletKeys: map[string][]string{
146+
"MAINNET": {"0xPrivateKey"},
147+
},
148+
},
149+
expectedError: nil,
150+
},
151+
{
152+
name: "Valid configuration with only HTTP URL",
153+
networkConfig: NetworkConfig{
154+
SelectedNetworks: []string{"MAINNET"},
155+
RpcHttpUrls: map[string][]string{
156+
"MAINNET": {"http://localhost:8545"},
157+
},
158+
WalletKeys: map[string][]string{
159+
"MAINNET": {"0xPrivateKey"},
160+
},
161+
},
162+
expectedError: nil,
163+
},
164+
{
165+
name: "Invalid configuration with only WS URL",
166+
networkConfig: NetworkConfig{
167+
SelectedNetworks: []string{"MAINNET"},
168+
RpcWsUrls: map[string][]string{
169+
"MAINNET": {"ws://localhost:8546"},
170+
},
171+
WalletKeys: map[string][]string{
172+
"MAINNET": {"0xPrivateKey"},
173+
},
174+
},
175+
expectedError: fmt.Errorf("WS RPC endpoint for MAINNET network is set without an HTTP endpoint; only HTTP or both HTTP and WS are allowed"),
176+
},
177+
{
178+
name: "Invalid configuration without HTTP or WS URLs",
179+
networkConfig: NetworkConfig{
180+
SelectedNetworks: []string{"MAINNET"},
181+
WalletKeys: map[string][]string{
182+
"MAINNET": {"0xPrivateKey"},
183+
},
184+
},
185+
expectedError: fmt.Errorf("at least one HTTP RPC endpoint for MAINNET network must be set"),
186+
},
187+
{
188+
name: "Valid simulated network without RPC URLs",
189+
networkConfig: NetworkConfig{
190+
SelectedNetworks: []string{"SIMULATED"},
191+
},
192+
expectedError: nil,
193+
},
194+
{
195+
name: "Valid forked network (Anvil) without RPC URLs",
196+
networkConfig: NetworkConfig{
197+
SelectedNetworks: []string{"MAINNET"},
198+
AnvilConfigs: map[string]*AnvilConfig{
199+
"MAINNET": {URL: ptr.Ptr("http://forked-node-url")},
200+
},
201+
},
202+
expectedError: nil,
203+
},
204+
{
205+
name: "Missing private key",
206+
networkConfig: NetworkConfig{
207+
SelectedNetworks: []string{"MAINNET"},
208+
RpcHttpUrls: map[string][]string{
209+
"MAINNET": {"http://localhost:8545"},
210+
},
211+
RpcWsUrls: map[string][]string{
212+
"MAINNET": {"ws://localhost:8546"},
213+
},
214+
},
215+
expectedError: fmt.Errorf("at least one private key of funding wallet for MAINNET network must be set"),
216+
},
217+
}
218+
219+
for _, tc := range testCases {
220+
tc := tc // capture range variable
221+
t.Run(tc.name, func(t *testing.T) {
222+
err := tc.networkConfig.Validate()
223+
if tc.expectedError != nil {
224+
require.EqualError(t, err, tc.expectedError.Error())
225+
} else {
226+
require.NoError(t, err)
227+
}
228+
})
229+
}
230+
}

lib/networks/known_networks.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ func SetNetworks(networkCfg config.NetworkConfig) ([]blockchain.EVMNetwork, erro
11011101
if networkCfg.AnvilConfigs != nil {
11021102
_, forked = networkCfg.AnvilConfigs[networkName]
11031103
}
1104+
11041105
// if network is not simulated or forked, use the rpc urls and wallet keys from config
11051106
if !strings.Contains(networkName, "SIMULATED") && !forked {
11061107
var ok, wsOk, httpOk bool
@@ -1109,9 +1110,14 @@ func SetNetworks(networkCfg config.NetworkConfig) ([]blockchain.EVMNetwork, erro
11091110
// Check for HTTP URLs
11101111
httpUrls, httpOk = networkCfg.RpcHttpUrls[selectedNetworks[i]]
11111112

1112-
// Ensure at least one of WS or HTTP URLs is available
1113-
if !wsOk && !httpOk {
1114-
return nil, fmt.Errorf("no RPC URLs found for '%s' network; at least one HTTP or WS RPC URL must be set", selectedNetworks[i])
1113+
// WS can be present but only if HTTP is also available, the CL node cannot funtion only on WS
1114+
if wsOk && !httpOk {
1115+
return nil, fmt.Errorf("WS RPC endpoint for %s network is set without an HTTP endpoint; only HTTP or both HTTP and WS are allowed", selectedNetworks[i])
1116+
}
1117+
1118+
// Validate that there is at least one HTTP endpoint
1119+
if !httpOk {
1120+
return nil, fmt.Errorf("at least one HTTP RPC endpoint for %s network must be set", selectedNetworks[i])
11151121
}
11161122

11171123
walletKeys, ok = networkCfg.WalletKeys[selectedNetworks[i]]

lib/networks/known_networks_test.go

Lines changed: 182 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain"
1212
"github.com/smartcontractkit/chainlink-testing-framework/lib/config"
1313
"github.com/smartcontractkit/chainlink-testing-framework/lib/logging"
14+
"github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr"
1415
)
1516

1617
func TestMain(m *testing.M) {
@@ -79,6 +80,8 @@ func TestVariousNetworkConfig(t *testing.T) {
7980
"ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
8081
},
8182
}
83+
httpOnlyNetwork := newNetwork
84+
httpOnlyNetwork.URLs = nil
8285
forkedNetwork := newNetwork
8386
forkedNetwork.HTTPURLs = nil
8487
forkedNetwork.URLs = nil
@@ -445,7 +448,7 @@ evm_default_gas_limit = 6000000
445448
os.Unsetenv("E2E_TEST_NEW_NETWORK_WALLET_KEY")
446449
os.Unsetenv("E2E_TEST_NEW_NETWORK_RPC_HTTP_URL")
447450
},
448-
isNetworkConfigError: true,
451+
expNetworks: []blockchain.EVMNetwork{httpOnlyNetwork},
449452
},
450453
}
451454
for _, tc := range testcases {
@@ -490,3 +493,181 @@ evm_default_gas_limit = 6000000
490493
})
491494
}
492495
}
496+
497+
func TestSetNetworks(t *testing.T) {
498+
// Helper to create a simple NetworkConfig for testing
499+
createNetworkConfig := func(selectedNetworks []string, evmNetworks map[string]*blockchain.EVMNetwork,
500+
rpcHttpUrls map[string][]string, rpcWsUrls map[string][]string, walletKeys map[string][]string,
501+
anvilConfigs map[string]*config.AnvilConfig) config.NetworkConfig {
502+
503+
return config.NetworkConfig{
504+
SelectedNetworks: selectedNetworks,
505+
EVMNetworks: evmNetworks,
506+
RpcHttpUrls: rpcHttpUrls,
507+
RpcWsUrls: rpcWsUrls,
508+
WalletKeys: walletKeys,
509+
AnvilConfigs: anvilConfigs,
510+
}
511+
}
512+
513+
// Define test cases
514+
testCases := []struct {
515+
name string
516+
networkCfg config.NetworkConfig
517+
expectedError bool
518+
expectedErrorMsg string
519+
expectedCount int // Expected number of valid networks returned
520+
}{
521+
{
522+
name: "Basic network setup with both HTTP and WS URLs",
523+
networkCfg: createNetworkConfig(
524+
[]string{"ETHEREUM_MAINNET"},
525+
map[string]*blockchain.EVMNetwork{
526+
"ETHEREUM_MAINNET": {Name: "ETHEREUM_MAINNET", ChainID: 1},
527+
},
528+
map[string][]string{"ETHEREUM_MAINNET": {"http://localhost:8545"}},
529+
map[string][]string{"ETHEREUM_MAINNET": {"ws://localhost:8546"}},
530+
map[string][]string{"ETHEREUM_MAINNET": {"ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"}},
531+
nil,
532+
),
533+
expectedError: false,
534+
expectedCount: 1,
535+
},
536+
{
537+
name: "Simulated network bypasses validations",
538+
networkCfg: createNetworkConfig(
539+
[]string{"SIMULATED"},
540+
map[string]*blockchain.EVMNetwork{
541+
"SIMULATED": {Name: "Simulated", Simulated: true, ChainID: 1337},
542+
},
543+
nil, nil, nil, nil,
544+
),
545+
expectedError: false,
546+
expectedCount: 1,
547+
},
548+
{
549+
name: "Forked network skips RPC and wallet validation",
550+
networkCfg: createNetworkConfig(
551+
[]string{"ETHEREUM_MAINNET"},
552+
nil,
553+
nil,
554+
nil,
555+
nil,
556+
map[string]*config.AnvilConfig{
557+
"ETHEREUM_MAINNET": {URL: ptr.Ptr("http://localhost:8545")},
558+
},
559+
),
560+
expectedError: false,
561+
expectedCount: 1,
562+
},
563+
{
564+
name: "Only HTTP URLs, valid setup",
565+
networkCfg: createNetworkConfig(
566+
[]string{"ETHEREUM_MAINNET"},
567+
nil,
568+
map[string][]string{"ETHEREUM_MAINNET": {"http://localhost:8545"}},
569+
nil,
570+
map[string][]string{"ETHEREUM_MAINNET": {"ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"}},
571+
nil,
572+
),
573+
expectedError: false,
574+
expectedCount: 1,
575+
},
576+
{
577+
name: "Only WS URLs without HTTP, invalid setup",
578+
networkCfg: createNetworkConfig(
579+
[]string{"MAINNET"},
580+
nil,
581+
nil,
582+
map[string][]string{"MAINNET": {"ws://localhost:8546"}},
583+
map[string][]string{"MAINNET": {"ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"}},
584+
nil,
585+
),
586+
expectedError: true,
587+
expectedErrorMsg: "WS RPC endpoint for MAINNET network is set without an HTTP endpoint",
588+
},
589+
{
590+
name: "Multiple networks with valid configurations",
591+
networkCfg: createNetworkConfig(
592+
[]string{"ETHEREUM_MAINNET", "OPTIMISM_MAINNET"},
593+
map[string]*blockchain.EVMNetwork{
594+
"ETHEREUM_MAINNET": {Name: "ETHEREUM_MAINNET", ChainID: 1},
595+
"OPTIMISM_MAINNET": {Name: "OPTIMISM_MAINNET", ChainID: 10},
596+
},
597+
map[string][]string{
598+
"ETHEREUM_MAINNET": {"http://localhost:8545"},
599+
"OPTIMISM_MAINNET": {"http://localhost:8547"},
600+
},
601+
map[string][]string{
602+
"ETHEREUM_MAINNET": {"ws://localhost:8546"},
603+
"OPTIMISM_MAINNET": {"ws://localhost:8548"},
604+
},
605+
map[string][]string{
606+
"ETHEREUM_MAINNET": {"ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"},
607+
"OPTIMISM_MAINNET": {"59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"},
608+
},
609+
nil,
610+
),
611+
expectedError: false,
612+
expectedCount: 2,
613+
},
614+
{
615+
name: "Missing wallet keys, invalid setup",
616+
networkCfg: createNetworkConfig(
617+
[]string{"ETHEREUM_MAINNET"},
618+
nil,
619+
map[string][]string{"ETHEREUM_MAINNET": {"http://localhost:8545"}},
620+
nil,
621+
nil,
622+
nil,
623+
),
624+
expectedError: true,
625+
expectedErrorMsg: "no wallet keys found in config for 'ETHEREUM_MAINNET' network",
626+
},
627+
{
628+
name: "Unknown network, invalid setup skips validation",
629+
networkCfg: createNetworkConfig(
630+
[]string{"UNKNOWN_NETWORK"},
631+
nil,
632+
nil,
633+
nil,
634+
nil,
635+
nil,
636+
),
637+
expectedError: true,
638+
expectedErrorMsg: "at least one HTTP RPC endpoint for UNKNOWN_NETWORK network must be set",
639+
},
640+
{
641+
name: "Valid known network from MappedNetworks",
642+
networkCfg: createNetworkConfig(
643+
[]string{"SIMULATED_1"},
644+
nil,
645+
nil,
646+
nil,
647+
nil,
648+
nil,
649+
),
650+
expectedError: false,
651+
expectedCount: 1,
652+
},
653+
}
654+
655+
// Run test cases
656+
for _, tc := range testCases {
657+
tc := tc // capture range variable
658+
t.Run(tc.name, func(t *testing.T) {
659+
nets, err := SetNetworks(tc.networkCfg)
660+
661+
// Check for expected error
662+
if tc.expectedError {
663+
require.Error(t, err)
664+
require.Contains(t, err.Error(), tc.expectedErrorMsg)
665+
return
666+
}
667+
require.NoError(t, err)
668+
669+
// Check the expected count of networks returned
670+
require.Equal(t, tc.expectedCount, len(nets))
671+
})
672+
}
673+
}

lib/utils/seth/seth.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,11 @@ func MergeSethAndEvmNetworkConfigs(evmNetwork blockchain.EVMNetwork, sethConfig
197197
if conf.Name == fmt.Sprint(pkg_seth.DefaultNetworkName) {
198198
conf.Name = evmNetwork.Name
199199
conf.PrivateKeys = evmNetwork.PrivateKeys
200-
conf.URLs = evmNetwork.URLs
201-
200+
if len(evmNetwork.URLs) > 0 {
201+
conf.URLs = evmNetwork.URLs
202+
} else {
203+
conf.URLs = evmNetwork.HTTPURLs
204+
}
202205
sethNetwork = conf
203206
break
204207
}

0 commit comments

Comments
 (0)