Skip to content

Commit a0e1065

Browse files
committed
test(di): add coverage for container wiring and adapters
Signed-off-by: kangeunchan <kangeunchan080310@gmail.com>
1 parent 11fa876 commit a0e1065

2 files changed

Lines changed: 360 additions & 0 deletions

File tree

internal/di/container_test.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package di
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/altuslabsxyz/devnet-builder/internal/output"
8+
)
9+
10+
func TestNewContainerDefaults(t *testing.T) {
11+
c := New()
12+
if c == nil {
13+
t.Fatal("expected container")
14+
}
15+
if c.Logger() == nil {
16+
t.Fatal("expected default logger")
17+
}
18+
if c.Config() == nil {
19+
t.Fatal("expected default config")
20+
}
21+
if c.NetworkRegistry() == nil {
22+
t.Fatal("expected network registry wrapper")
23+
}
24+
}
25+
26+
func TestWithConfigInitializesPluginManager(t *testing.T) {
27+
c := New(WithConfig(&Config{PluginDir: t.TempDir()}))
28+
if c.PluginManager() == nil {
29+
t.Fatal("expected plugin manager to be initialized when PluginDir is set")
30+
}
31+
}
32+
33+
func TestWireContainerBuildsCoreDependencies(t *testing.T) {
34+
factory := NewInfrastructureFactory(t.TempDir(), output.NewLogger()).WithNetworkModule(&testNetworkModule{})
35+
container, err := factory.WireContainer()
36+
if err != nil {
37+
t.Fatalf("WireContainer failed: %v", err)
38+
}
39+
40+
if container.DevnetRepository() == nil {
41+
t.Fatal("expected devnet repository")
42+
}
43+
if container.NodeRepository() == nil {
44+
t.Fatal("expected node repository")
45+
}
46+
if container.ProvisionUseCase() == nil {
47+
t.Fatal("expected provision use case")
48+
}
49+
if container.ExecuteUpgradeUseCase() == nil {
50+
t.Fatal("expected execute upgrade use case")
51+
}
52+
}
53+
54+
func TestContainerLazyAccessors(t *testing.T) {
55+
factory := NewInfrastructureFactory(t.TempDir(), output.NewLogger()).WithNetworkModule(&testNetworkModule{})
56+
container, err := factory.WireContainer()
57+
if err != nil {
58+
t.Fatalf("WireContainer failed: %v", err)
59+
}
60+
61+
container.SetNetworkModule(nil)
62+
container.SetBinaryResolver(nil)
63+
64+
_ = container.Logger()
65+
_ = container.LoggerPort()
66+
_ = container.NetworkRegistry()
67+
_ = container.PluginManager()
68+
_ = container.Config()
69+
_ = container.DevnetRepository()
70+
_ = container.NodeRepository()
71+
_ = container.ExportRepository()
72+
_ = container.Executor()
73+
_ = container.HealthChecker()
74+
_ = container.NetworkModule()
75+
_ = container.GitHubClient()
76+
_ = container.InteractiveSelector()
77+
_ = container.BinaryCache()
78+
_ = container.Builder()
79+
_ = container.ValidatorKeyLoader()
80+
_ = container.EVMClient()
81+
_ = container.RPCClient()
82+
_ = container.NodeInitializer()
83+
_ = container.ProvisionUseCase()
84+
_ = container.RunUseCase()
85+
_ = container.StopUseCase()
86+
_ = container.HealthUseCase()
87+
_ = container.ResetUseCase()
88+
_ = container.DestroyUseCase()
89+
_ = container.ProposeUseCase()
90+
_ = container.VoteUseCase()
91+
_ = container.SwitchBinaryUseCase()
92+
_ = container.ExecuteUpgradeUseCase()
93+
_ = container.MonitorUseCase()
94+
_ = container.StateManager()
95+
_ = container.StateTransitioner()
96+
_ = container.StateDetector()
97+
_ = container.ResumableExecuteUpgradeUseCase()
98+
_ = container.ResumeUseCase()
99+
_ = container.BuildUseCase()
100+
_ = container.CacheListUseCase()
101+
_ = container.CacheCleanUseCase()
102+
_ = container.PassthroughUseCase()
103+
_ = container.ImportCustomBinaryUseCase()
104+
_ = container.NodeLifecycleManager()
105+
_ = container.ExportUseCase(context.Background())
106+
}

internal/di/factory_test.go

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
package di
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
cosmoslog "cosmossdk.io/log"
8+
"github.com/altuslabsxyz/devnet-builder/internal/application/ports"
9+
"github.com/altuslabsxyz/devnet-builder/internal/infrastructure/network"
10+
"github.com/altuslabsxyz/devnet-builder/internal/infrastructure/plugin"
11+
"github.com/altuslabsxyz/devnet-builder/internal/output"
12+
pkgnetwork "github.com/altuslabsxyz/devnet-builder/pkg/network"
13+
)
14+
15+
type testNetworkModule struct{}
16+
17+
func (m *testNetworkModule) Name() string { return "testnet" }
18+
func (m *testNetworkModule) DisplayName() string { return "Testnet" }
19+
func (m *testNetworkModule) Version() string { return "1.0.0" }
20+
func (m *testNetworkModule) BinaryName() string { return "testd" }
21+
func (m *testNetworkModule) BinarySource() network.BinarySource {
22+
return network.BinarySource{Type: network.BinarySourceGitHub, Owner: "owner", Repo: "repo"}
23+
}
24+
func (m *testNetworkModule) DefaultBinaryVersion() string { return "v1.0.0" }
25+
func (m *testNetworkModule) GetBuildConfig(networkType string) (*pkgnetwork.BuildConfig, error) {
26+
return &pkgnetwork.BuildConfig{Tags: []string{"netgo"}}, nil
27+
}
28+
func (m *testNetworkModule) Bech32Prefix() string { return "test" }
29+
func (m *testNetworkModule) BaseDenom() string { return "utest" }
30+
func (m *testNetworkModule) GenesisConfig() network.GenesisConfig { return network.GenesisConfig{} }
31+
func (m *testNetworkModule) DefaultChainID() string { return "testnet-1" }
32+
func (m *testNetworkModule) DockerImage() string { return "ghcr.io/example/testd" }
33+
func (m *testNetworkModule) DockerImageTag(version string) string { return version }
34+
func (m *testNetworkModule) DockerHomeDir() string { return "/home/testd" }
35+
func (m *testNetworkModule) InitCommand(homeDir, chainID, moniker string) []string {
36+
return []string{"init", moniker, "--chain-id", chainID}
37+
}
38+
func (m *testNetworkModule) StartCommand(homeDir string, networkMode string) []string {
39+
return []string{"start"}
40+
}
41+
func (m *testNetworkModule) ExportCommand(homeDir string) []string { return []string{"export"} }
42+
func (m *testNetworkModule) DefaultMoniker(index int) string { return "node0" }
43+
func (m *testNetworkModule) DefaultNodeHome() string { return ".testd" }
44+
func (m *testNetworkModule) PIDFileName() string { return "testd.pid" }
45+
func (m *testNetworkModule) LogFileName() string { return "testd.log" }
46+
func (m *testNetworkModule) ProcessPattern() string { return "testd" }
47+
func (m *testNetworkModule) DefaultPorts() network.PortConfig { return network.DefaultPortConfig() }
48+
func (m *testNetworkModule) ConfigDir(homeDir string) string { return homeDir + "/config" }
49+
func (m *testNetworkModule) DataDir(homeDir string) string { return homeDir + "/data" }
50+
func (m *testNetworkModule) KeyringDir(homeDir string, backend string) string {
51+
return homeDir + "/keyring-" + backend
52+
}
53+
func (m *testNetworkModule) ModifyGenesis(genesis []byte, opts network.GenesisOptions) ([]byte, error) {
54+
return genesis, nil
55+
}
56+
func (m *testNetworkModule) NewGenerator(config *network.GeneratorConfig, logger cosmoslog.Logger) (network.Generator, error) {
57+
return nil, nil
58+
}
59+
func (m *testNetworkModule) DefaultGeneratorConfig() *network.GeneratorConfig {
60+
return &network.GeneratorConfig{}
61+
}
62+
func (m *testNetworkModule) Validate() error { return nil }
63+
func (m *testNetworkModule) SnapshotURL(networkType string) string { return "https://snapshot.example" }
64+
func (m *testNetworkModule) RPCEndpoint(networkType string) string { return "https://rpc.example" }
65+
func (m *testNetworkModule) AvailableNetworks() []string { return []string{"mainnet", "testnet"} }
66+
func (m *testNetworkModule) GetConfigOverrides(nodeIndex int, opts network.NodeConfigOptions) ([]byte, []byte, error) {
67+
return []byte("config"), []byte("app"), nil
68+
}
69+
70+
type fileCapableModule struct {
71+
*testNetworkModule
72+
}
73+
74+
func (m *fileCapableModule) ModifyGenesisFile(inputPath, outputPath string, opts network.GenesisOptions) (int64, error) {
75+
return 42, nil
76+
}
77+
78+
func TestOptionFunctionsApplyWithoutPanics(t *testing.T) {
79+
c := New()
80+
logger := output.NewLogger()
81+
pm := plugin.NewPluginManager(t.TempDir())
82+
83+
opts := []Option{
84+
WithLogger(logger),
85+
WithConfig(&Config{HomeDir: t.TempDir(), PluginDir: t.TempDir()}),
86+
WithPluginManager(pm),
87+
WithDevnetRepository((ports.DevnetRepository)(nil)),
88+
WithNodeRepository((ports.NodeRepository)(nil)),
89+
WithBinaryCache((ports.BinaryCache)(nil)),
90+
WithExecutor((ports.ProcessExecutor)(nil)),
91+
WithRPCClient((ports.RPCClient)(nil)),
92+
WithEVMClient((ports.EVMClient)(nil)),
93+
WithSnapshotFetcher((ports.SnapshotFetcher)(nil)),
94+
WithGenesisFetcher((ports.GenesisFetcher)(nil)),
95+
WithStateExportService((ports.StateExportService)(nil)),
96+
WithNodeInitializer((ports.NodeInitializer)(nil)),
97+
WithKeyManager((ports.KeyManager)(nil)),
98+
WithHealthChecker((ports.HealthChecker)(nil)),
99+
WithValidatorKeyLoader((ports.ValidatorKeyLoader)(nil)),
100+
WithBuilder((ports.Builder)(nil)),
101+
WithNetworkModule((ports.NetworkModule)(nil)),
102+
WithGitHubClient((ports.GitHubClient)(nil)),
103+
WithInteractiveSelector((ports.InteractiveSelector)(nil)),
104+
WithBinaryResolver((ports.BinaryResolver)(nil)),
105+
WithBinaryExecutor((ports.BinaryExecutor)(nil)),
106+
WithExportRepository((ports.ExportRepository)(nil)),
107+
WithBinaryVersionDetector((ports.BinaryVersionDetector)(nil)),
108+
}
109+
110+
for _, opt := range opts {
111+
opt(c)
112+
}
113+
114+
if c.Logger() != logger {
115+
t.Fatal("expected logger option to be applied")
116+
}
117+
if c.PluginManager() != pm {
118+
t.Fatal("expected plugin manager option to be applied")
119+
}
120+
}
121+
122+
func TestNetworkModuleAdapterMethods(t *testing.T) {
123+
base := &testNetworkModule{}
124+
adapter := &networkModuleAdapter{module: base}
125+
126+
if adapter.Name() != "testnet" {
127+
t.Fatalf("unexpected adapter name: %s", adapter.Name())
128+
}
129+
if adapter.BinaryName() != "testd" {
130+
t.Fatalf("unexpected binary name: %s", adapter.BinaryName())
131+
}
132+
if adapter.DockerImageTag("v1") != "v1" {
133+
t.Fatal("expected docker image tag passthrough")
134+
}
135+
if _, err := adapter.ModifyGenesis([]byte(`{}`), ports.GenesisModifyOptions{}); err != nil {
136+
t.Fatalf("unexpected ModifyGenesis error: %v", err)
137+
}
138+
139+
portsCfg := adapter.DefaultPorts()
140+
if portsCfg.PProf != 6060 || portsCfg.Rosetta != 8080 {
141+
t.Fatalf("unexpected default extra ports: %+v", portsCfg)
142+
}
143+
144+
if _, err := adapter.ModifyGenesisFile("in", "out", ports.GenesisModifyOptions{}); err == nil {
145+
t.Fatal("expected ModifyGenesisFile to fail when module does not support file modifier")
146+
}
147+
148+
fileAdapter := &networkModuleAdapter{module: &fileCapableModule{testNetworkModule: base}}
149+
size, err := fileAdapter.ModifyGenesisFile("in", "out", ports.GenesisModifyOptions{})
150+
if err != nil {
151+
t.Fatalf("unexpected file ModifyGenesisFile error: %v", err)
152+
}
153+
if size != 42 {
154+
t.Fatalf("unexpected output size: %d", size)
155+
}
156+
}
157+
158+
func TestInfrastructureFactoryCreateMethods(t *testing.T) {
159+
logger := output.NewLogger()
160+
module := &testNetworkModule{}
161+
f := NewInfrastructureFactory(t.TempDir(), logger).
162+
WithNetworkModule(module).
163+
WithGitHubConfig("token", "owner", "repo")
164+
165+
if f.CreateDevnetRepository() == nil {
166+
t.Fatal("expected devnet repository")
167+
}
168+
if f.CreateNodeRepository() == nil {
169+
t.Fatal("expected node repository")
170+
}
171+
if f.CreateExportRepository() == nil {
172+
t.Fatal("expected export repository")
173+
}
174+
if f.CreateDockerExecutor() == nil {
175+
t.Fatal("expected docker executor")
176+
}
177+
if f.CreateRPCClient("localhost", 26657) == nil {
178+
t.Fatal("expected rpc client")
179+
}
180+
if _, err := f.CreateBinaryCache(); err != nil {
181+
t.Fatalf("expected binary cache, got error: %v", err)
182+
}
183+
if f.CreateBinaryVersionDetector() == nil {
184+
t.Fatal("expected version detector")
185+
}
186+
if f.CreateBuilder() == nil {
187+
t.Fatal("expected builder")
188+
}
189+
if f.CreateSnapshotFetcher() == nil {
190+
t.Fatal("expected snapshot fetcher")
191+
}
192+
if f.CreateGenesisFetcher() == nil {
193+
t.Fatal("expected genesis fetcher")
194+
}
195+
if f.CreateStateExportService() == nil {
196+
t.Fatal("expected state export service")
197+
}
198+
if f.CreateNodeInitializer() == nil {
199+
t.Fatal("expected node initializer")
200+
}
201+
if f.CreateNodeManagerFactory() == nil {
202+
t.Fatal("expected node manager factory")
203+
}
204+
if f.CreateGitHubClient() == nil {
205+
t.Fatal("expected github client")
206+
}
207+
if f.CreateInteractiveSelector() == nil {
208+
t.Fatal("expected interactive selector")
209+
}
210+
if f.CreateEVMClient("http://localhost:8545") == nil {
211+
t.Fatal("expected evm client")
212+
}
213+
if f.CreateValidatorKeyLoader() == nil {
214+
t.Fatal("expected validator key loader")
215+
}
216+
if f.CreateVersionRepository() == nil {
217+
t.Fatal("expected version repository")
218+
}
219+
if f.CreateMigrationService() == nil {
220+
t.Fatal("expected migration service")
221+
}
222+
if f.CreateBinaryExecutor() == nil {
223+
t.Fatal("expected binary executor")
224+
}
225+
if f.CreateBinaryResolver(nil, nil) == nil {
226+
t.Fatal("expected binary resolver")
227+
}
228+
229+
f.WithDockerMode(false)
230+
if f.CreateProcessExecutor() == nil {
231+
t.Fatal("expected local process executor")
232+
}
233+
f.WithDockerMode(true)
234+
if f.CreateProcessExecutor() == nil {
235+
t.Fatal("expected docker process executor")
236+
}
237+
238+
health := f.CreateHealthChecker(26657)
239+
results, err := health.CheckAllNodes(context.Background(), []*ports.NodeMetadata{})
240+
if err != nil {
241+
t.Fatalf("unexpected CheckAllNodes error: %v", err)
242+
}
243+
if len(results) != 0 {
244+
t.Fatalf("expected 0 health results, got %d", len(results))
245+
}
246+
247+
container, err := f.WireContainer()
248+
if err != nil {
249+
t.Fatalf("WireContainer failed: %v", err)
250+
}
251+
if container == nil {
252+
t.Fatal("expected wired container")
253+
}
254+
}

0 commit comments

Comments
 (0)