From f403d913852aec1b7863a0b7682a170a97ac1927 Mon Sep 17 00:00:00 2001 From: Wasin Watthanasrisong Date: Fri, 6 Dec 2024 18:13:33 +0700 Subject: [PATCH 1/5] feat: add golangci --- .golangci.yml | 24 ++++++++++++++++++++++++ Makefile | 6 ++++++ 2 files changed, 30 insertions(+) create mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..5c0e0b15 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,24 @@ +linters: + disable-all: false + disable: + - thelper + - varnamelen + - tagliatelle + - wrapcheck + - typecheck + errcheck: + exclude-functions: + - fmt:.* + - io/ioutil:^Read.* + - github.com/spf13/cobra:MarkFlagRequired + - github.com/spf13/viper:BindPFlag +linters-settings: + gocyclo: + min-complexity: 11 + golint: + min-confidence: 1.1 +issues: + exclude: + - composite +run: + tests: false diff --git a/Makefile b/Makefile index 965e0da0..1d97ef19 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,12 @@ build: check_version $(BUILDDIR) install: check_version go install -ldflags "$(LDFLAGS)" . +lint: + golangci-lint run --out-format=tab --timeout=15m + +lint-fix: + golangci-lint run --fix --out-format=tab --timeout=15m + test: check_version go clean -testcache go test -v ./... From 195f5441037b2d36782782acaacc94ce7da6aa17 Mon Sep 17 00:00:00 2001 From: Wasin Watthanasrisong Date: Mon, 9 Dec 2024 16:56:22 +0700 Subject: [PATCH 2/5] chore: follow coderabbit's comment + fix lint + introduce golangci in github actions --- .github/workflows/basic-checks.yml | 39 ++- .golangci.yml | 1 + Makefile | 16 +- client/grpc.go | 8 +- cmd/opinit_bots.go | 4 +- cosmosutils/keys.go | 11 +- models/minitia/launch.go | 2 +- models/minitia/tx.go | 6 +- models/relayer/init.go | 4 +- service/launchd.go | 22 +- tests/integration/alias.go | 29 -- tests/integration/gas_station_test.go | 55 ---- tests/integration/initia_test.go | 370 -------------------------- tests/integration/minitia_test.go | 183 ------------- tests/integration/opinit_test.go | 160 ----------- tests/integration/testutil.go | 168 ------------ 16 files changed, 78 insertions(+), 1000 deletions(-) delete mode 100644 tests/integration/alias.go delete mode 100644 tests/integration/gas_station_test.go delete mode 100644 tests/integration/initia_test.go delete mode 100644 tests/integration/minitia_test.go delete mode 100644 tests/integration/opinit_test.go delete mode 100644 tests/integration/testutil.go diff --git a/.github/workflows/basic-checks.yml b/.github/workflows/basic-checks.yml index aba12b09..bbe5f307 100644 --- a/.github/workflows/basic-checks.yml +++ b/.github/workflows/basic-checks.yml @@ -10,16 +10,45 @@ on: jobs: lint: + env: + GOLANGCI_LINT_VERSION: v1.61.0 + name: golangci-lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v4 with: - go-version: "1.22.6" - - - name: Check lint - run: go fmt ./... + go-version: 1.22.6 + check-latest: true + - uses: technote-space/get-diff-action@v6.1.2 + id: git_diff + with: + PATTERNS: | + **/**.go + go.mod + go.sum + - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION} + - name: run go linters (long) + if: env.GIT_DIFF + id: lint_long + run: | + make lint + env: + GIT_DIFF: ${{ env.GIT_DIFF }} + - uses: technote-space/get-diff-action@v6.1.2 + if: steps.lint_long.outcome == 'skipped' + with: + PATTERNS: | + **/**.go + go.mod + go.sum + - name: run go linters (short) + if: steps.lint_long.outcome == 'skipped' && env.GIT_DIFF + run: | + make lint + env: + GIT_DIFF: ${{ env.GIT_DIFF }} + LINT_DIFF: 1 unit-tests: runs-on: ubuntu-latest steps: diff --git a/.golangci.yml b/.golangci.yml index 5c0e0b15..56782cea 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -20,5 +20,6 @@ linters-settings: issues: exclude: - composite + - 'SA1019: "golang.org/x/crypto/ripemd160" is deprecated:' # Exclude deprecated ripemd160 warning run: tests: false diff --git a/Makefile b/Makefile index 1d97ef19..a0abf4d1 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ release_version=$(filter-out $@,$(MAKECMDGOALS)) # Version check check_version: - @if [ "$(GO_SYSTEM_VERSION)" != "$(REQUIRE_GO_VERSION)" ]; then \ + @if [ $(shell echo "$(GO_SYSTEM_VERSION) < $(REQUIRE_GO_VERSION)" | bc -l) -eq 1 ]; then \ echo "ERROR: Go version $(REQUIRE_GO_VERSION) is required for Weave."; \ exit 1; \ fi @@ -35,11 +35,19 @@ build: check_version $(BUILDDIR) install: check_version go install -ldflags "$(LDFLAGS)" . -lint: +.PHONY: lint lint-fix + +# Run golangci-lint to check code quality +lint: check_version + @command -v golangci-lint >/dev/null 2>&1 || { echo "golangci-lint is required but not installed. Install it by following instructions at https://golangci-lint.run/welcome/install/"; exit 1; } golangci-lint run --out-format=tab --timeout=15m -lint-fix: - golangci-lint run --fix --out-format=tab --timeout=15m +# Run golangci-lint and automatically fix issues where possible (use with caution) +lint-fix: check_version + @echo "Warning: This will automatically modify your files to fix linting issues" + @read -p "Are you sure you want to continue? [y/N] " -n 1 -r; echo; if [[ ! $$REPLY =~ ^[Yy]$$ ]]; then exit 1; fi + @command -v golangci-lint >/dev/null 2>&1 || { echo "golangci-lint is required but not installed. Install it by following instructions at https://golangci-lint.run/welcome/install/"; exit 1; } + golangci-lint run --fix --out-format=tab --timeout=15m test: check_version go clean -testcache diff --git a/client/grpc.go b/client/grpc.go index 5046bbca..132f7bb8 100644 --- a/client/grpc.go +++ b/client/grpc.go @@ -16,9 +16,7 @@ const ( ) // GRPCClient defines the logic for making gRPC requests. -type GRPCClient struct { - conn *grpc.ClientConn -} +type GRPCClient struct{} // NewGRPCClient initializes and returns a new GRPCClient instance. func NewGRPCClient() *GRPCClient { @@ -27,9 +25,7 @@ func NewGRPCClient() *GRPCClient { // CheckHealth attempts to connect to the server and uses the reflection service to verify the server is up. func (g *GRPCClient) CheckHealth(serverAddr string) error { - if strings.HasPrefix(serverAddr, "grpc://") { - serverAddr = strings.TrimPrefix(serverAddr, "grpc://") - } + serverAddr = strings.TrimPrefix(serverAddr, "grpc://") conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { diff --git a/cmd/opinit_bots.go b/cmd/opinit_bots.go index 47c0e034..507bd36f 100644 --- a/cmd/opinit_bots.go +++ b/cmd/opinit_bots.go @@ -213,7 +213,7 @@ Valid options are [executor, challenger] eg. weave opinit-bots stop challenger`, if err != nil { return err } - fmt.Println(fmt.Sprintf("Stopped the OPinit %s bot process.", botName)) + fmt.Printf("Stopped the OPinit %s bot process.\n", botName) return nil }, } @@ -298,7 +298,7 @@ Valid options are [executor, challenger] eg. weave opinit-bots reset challenger` if err = execCmd.Run(); err != nil { return fmt.Errorf("failed to reset-db: %v", err) } - fmt.Println(fmt.Sprintf("Reset the OPinit %[1]s bot database successfully.", botName)) + fmt.Printf("Reset the OPinit %s bot database successfully.\n", botName) return nil }, } diff --git a/cosmosutils/keys.go b/cosmosutils/keys.go index 79f1661a..5033f29f 100644 --- a/cosmosutils/keys.go +++ b/cosmosutils/keys.go @@ -331,7 +331,12 @@ func addNewKeyToHermes(appName, chainId, mnemonic string) (*KeyInfo, error) { if err = io.WriteFile(tempMnemonicPath, mnemonic); err != nil { return nil, fmt.Errorf("failed to write raw tx file: %v", err) } - defer io.DeleteFile(tempMnemonicPath) + + defer func() { + if err := io.DeleteFile(tempMnemonicPath); err != nil { + fmt.Printf("failed to delete temp mnemonic file: %v", err) + } + }() cmd := exec.Command(appName, "keys", "add", "--chain", chainId, "--mnemonic-file", tempMnemonicPath) @@ -370,11 +375,11 @@ func RecoverNewHermesKey(appName, chainId, mnemonic string) (*KeyInfo, error) { } func GenerateAndReplaceHermesKey(appName, chainId string) (*KeyInfo, error) { - DeleteWeaveKeyFromHermes(appName, chainId) + _ = DeleteWeaveKeyFromHermes(appName, chainId) return GenerateAndAddNewHermesKey(appName, chainId) } func RecoverAndReplaceHermesKey(appName, chainId, mnemonic string) (*KeyInfo, error) { - DeleteWeaveKeyFromHermes(appName, chainId) + _ = DeleteWeaveKeyFromHermes(appName, chainId) return RecoverNewHermesKey(appName, chainId, mnemonic) } diff --git a/models/minitia/launch.go b/models/minitia/launch.go index 1ed2195a..b6589c45 100644 --- a/models/minitia/launch.go +++ b/models/minitia/launch.go @@ -2170,7 +2170,7 @@ func (m *DownloadCelestiaBinaryLoading) Update(msg tea.Msg) (tea.Model, tea.Cmd) state := weavecontext.PushPageAndGetState[LaunchState](m) if state.downloadedNewCelestiaBinary { - state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.NoSeparator, fmt.Sprintf("Celestia binary has been successfully downloaded."), []string{}, "")) + state.weave.PushPreviousResponse(styles.RenderPreviousResponse(styles.NoSeparator, "Celestia binary has been successfully downloaded.", []string{}, "")) } model := NewGenerateOrRecoverSystemKeysLoading(weavecontext.SetCurrentState(m.Ctx, state)) return model, model.Init() diff --git a/models/minitia/tx.go b/models/minitia/tx.go index 64a0f083..271b928a 100644 --- a/models/minitia/tx.go +++ b/models/minitia/tx.go @@ -115,7 +115,11 @@ func (lsk *L1SystemKeys) FundAccountsWithGasStation(state *LaunchState) (*FundAc if err = io.WriteFile(rawTxPath, rawTxContent); err != nil { return nil, fmt.Errorf("failed to write raw tx file: %v", err) } - defer io.DeleteFile(rawTxPath) + defer func() { + if err := io.DeleteFile(rawTxPath); err != nil { + fmt.Printf("failed to delete raw tx file: %v", err) + } + }() signCmd := exec.Command(state.binaryPath, "tx", "sign", rawTxPath, "--from", common.WeaveGasStationKeyName, "--node", state.l1RPC, "--chain-id", state.l1ChainId, "--keyring-backend", "test", "--output-document", rawTxPath) diff --git a/models/relayer/init.go b/models/relayer/init.go index 592b1274..9ab6a87b 100644 --- a/models/relayer/init.go +++ b/models/relayer/init.go @@ -528,7 +528,7 @@ func (m *KeysMnemonicDisplayInput) View() string { if state.l2KeyMethod == string(L2GenerateKey) { mnemonicText += styles.RenderMnemonic( - styles.RenderPrompt(fmt.Sprintf("Weave Relayer on L2"), []string{"L2"}, styles.Empty), + styles.RenderPrompt("Weave Relayer on L2", []string{"L2"}, styles.Empty), state.l2RelayerAddress, state.l2RelayerMnemonic, ) @@ -780,7 +780,7 @@ func NewFundingAmountSelect(ctx context.Context) *FundingAmountSelect { CannotBack: true, }, BaseModel: weavecontext.BaseModel{Ctx: ctx, CannotBack: true}, - question: fmt.Sprintf("Please select the filling amount option"), + question: "Please select the filling amount option", } } diff --git a/service/launchd.go b/service/launchd.go index d0d2f5f6..746b40b2 100644 --- a/service/launchd.go +++ b/service/launchd.go @@ -65,17 +65,17 @@ func (j *Launchd) Create(binaryVersion, appHome string) error { return j.reloadService() } -func (j *Launchd) unloadService() error { - userHome, err := os.UserHomeDir() - if err != nil { - return fmt.Errorf("failed to get user home directory: %v", err) - } - unloadCmd := exec.Command("launchctl", "unload", filepath.Join(userHome, fmt.Sprintf("Library/LaunchAgents/%s.plist", j.GetServiceName()))) - if err = unloadCmd.Run(); err != nil { - return fmt.Errorf("failed to unload service: %v", err) - } - return nil -} +// func (j *Launchd) unloadService() error { +// userHome, err := os.UserHomeDir() +// if err != nil { +// return fmt.Errorf("failed to get user home directory: %v", err) +// } +// unloadCmd := exec.Command("launchctl", "unload", filepath.Join(userHome, fmt.Sprintf("Library/LaunchAgents/%s.plist", j.GetServiceName()))) +// if err = unloadCmd.Run(); err != nil { +// return fmt.Errorf("failed to unload service: %v", err) +// } +// return nil +// } func (j *Launchd) reloadService() error { userHome, err := os.UserHomeDir() diff --git a/tests/integration/alias.go b/tests/integration/alias.go deleted file mode 100644 index 4c7ff74c..00000000 --- a/tests/integration/alias.go +++ /dev/null @@ -1,29 +0,0 @@ -package integration - -import ( - "time" - - tea "github.com/charmbracelet/bubbletea" -) - -var ( - pressEnter = InputStep{Msg: tea.KeyMsg{Type: tea.KeyEnter}} - pressSpace = InputStep{Msg: tea.KeyMsg{Type: tea.KeySpace}} - pressTab = InputStep{Msg: tea.KeyMsg{Type: tea.KeyTab}} - pressUp = InputStep{Msg: tea.KeyMsg{Type: tea.KeyUp}} - pressDown = InputStep{Msg: tea.KeyMsg{Type: tea.KeyDown}} - - waitFetching = WaitStep{Check: func() bool { - time.Sleep(5 * time.Second) - return true - }} -) - -func typeText(text string) InputStep { - return InputStep{Msg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune(text)}} -} - -// waitFor receives waitCondition as a parameter, which should return true if the wait should be over. -func waitFor(waitCondition func() bool) WaitStep { - return WaitStep{Check: waitCondition} -} diff --git a/tests/integration/gas_station_test.go b/tests/integration/gas_station_test.go deleted file mode 100644 index 646b9898..00000000 --- a/tests/integration/gas_station_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package integration - -import ( - "os" - "path/filepath" - "testing" - - tea "github.com/charmbracelet/bubbletea" - "github.com/stretchr/testify/assert" - - "github.com/initia-labs/weave/common" - "github.com/initia-labs/weave/config" - "github.com/initia-labs/weave/context" - "github.com/initia-labs/weave/models" -) - -const ( - TestMnemonic string = "imitate sick vibrant bonus weather spice pave announce direct impulse strategy math" -) - -func setupGasStation(t *testing.T) tea.Model { - err := config.InitializeConfig() - assert.Nil(t, err) - - ctx := context.NewAppContext(models.NewExistingCheckerState()) - firstModel := models.NewGasStationMnemonicInput(ctx) - - steps := []Step{ - typeText(TestMnemonic), - pressEnter, - } - - return runProgramWithSteps(t, firstModel, steps) -} - -func TestGasStationSetup(t *testing.T) { - finalModel := setupGasStation(t) - - // Check the final state here - assert.IsType(t, &models.WeaveAppSuccessfullyInitialized{}, finalModel) - - if _, ok := finalModel.(*models.WeaveAppSuccessfullyInitialized); ok { - assert.True(t, ok) - } - - // Check if Weave home has been created - userHome, _ := os.UserHomeDir() - weaveDir := filepath.Join(userHome, common.WeaveDirectory) - _, err := os.Stat(weaveDir) - assert.Nil(t, err) - - // Assert values - weaveConfig := filepath.Join(weaveDir, "config.json") - compareJsonValue(t, weaveConfig, "common.gas_station_mnemonic", TestMnemonic) -} diff --git a/tests/integration/initia_test.go b/tests/integration/initia_test.go deleted file mode 100644 index fc53d178..00000000 --- a/tests/integration/initia_test.go +++ /dev/null @@ -1,370 +0,0 @@ -package integration - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/initia-labs/weave/context" - "github.com/initia-labs/weave/models/initia" -) - -const ( - TestInitiaHome = ".initia.weave.test" -) - -func TestInitiaInitTestnetNoSync(t *testing.T) { - ctx := context.NewAppContext(initia.NewRunL1NodeState()) - ctx = context.SetInitiaHome(ctx, TestInitiaHome) - - firstModel := initia.NewRunL1NodeNetworkSelect(ctx) - - // Ensure that there is no previous Initia home - _, err := os.Stat(TestInitiaHome) - assert.NotNil(t, err) - - steps := []Step{ - pressEnter, - typeText("Moniker"), - pressEnter, - pressSpace, - pressEnter, - typeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), - pressEnter, - typeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), - pressEnter, - waitFor(func() bool { - if _, err := os.Stat(TestInitiaHome); os.IsNotExist(err) { - return false - } - return true - }), - pressDown, - pressDown, - pressEnter, - } - - finalModel := runProgramWithSteps(t, firstModel, steps) - defer clearTestDir(TestInitiaHome) - - // Check the final state here - assert.IsType(t, &initia.TerminalState{}, finalModel) - - if _, ok := finalModel.(*initia.TerminalState); ok { - assert.True(t, ok) - } - - // Check if Initia home has been created - _, err = os.Stat(TestInitiaHome) - assert.Nil(t, err) - - configTomlPath := filepath.Join(TestInitiaHome, "config/config.toml") - appTomlPath := filepath.Join(TestInitiaHome, "config/app.toml") - - if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { - t.Fatalf("Config toml file does not exist: %s", configTomlPath) - } - - if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { - t.Fatalf("App toml file does not exist: %s", appTomlPath) - } - - // Assert values - compareTomlValue(t, configTomlPath, "moniker", "Moniker") - compareTomlValue(t, configTomlPath, "p2p.seeds", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656") - compareTomlValue(t, configTomlPath, "p2p.persistent_peers", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656") - compareTomlValue(t, configTomlPath, "statesync.enable", false) - - compareTomlValue(t, appTomlPath, "minimum-gas-prices", "0.15uinit") - compareTomlValue(t, appTomlPath, "api.enable", "true") -} - -func TestInitiaInitTestnetStatesync(t *testing.T) { - ctx := context.NewAppContext(initia.NewRunL1NodeState()) - ctx = context.SetInitiaHome(ctx, TestInitiaHome) - - firstModel := initia.NewRunL1NodeNetworkSelect(ctx) - - // Ensure that there is no previous Initia home - _, err := os.Stat(TestInitiaHome) - assert.NotNil(t, err) - - steps := []Step{ - pressEnter, - typeText("Moniker"), - pressEnter, - pressSpace, - pressEnter, - typeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), - pressEnter, - typeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), - pressEnter, - waitFor(func() bool { - if _, err := os.Stat(TestInitiaHome); os.IsNotExist(err) { - return false - } - return true - }), - pressDown, - pressEnter, - waitFetching, - pressEnter, - typeText("https://initia-testnet-rpc.polkachu.com:443"), - pressEnter, - waitFetching, - typeText("1d9b9512f925cf8808e7f76d71a788d82089fe76@65.108.198.118:25756"), - pressEnter, - waitFetching, - } - - finalModel := runProgramWithSteps(t, firstModel, steps) - defer clearTestDir(TestInitiaHome) - - // Check the final state here - assert.IsType(t, &initia.TerminalState{}, finalModel) - - if _, ok := finalModel.(*initia.TerminalState); ok { - assert.True(t, ok) - } - - // Check if Initia home has been created - _, err = os.Stat(TestInitiaHome) - assert.Nil(t, err) - - configTomlPath := filepath.Join(TestInitiaHome, "config/config.toml") - appTomlPath := filepath.Join(TestInitiaHome, "config/app.toml") - - if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { - t.Fatalf("Config toml file does not exist: %s", configTomlPath) - } - - if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { - t.Fatalf("App toml file does not exist: %s", appTomlPath) - } - - // Assert values - compareTomlValue(t, configTomlPath, "moniker", "Moniker") - compareTomlValue(t, configTomlPath, "p2p.seeds", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656") - compareTomlValue(t, configTomlPath, "p2p.persistent_peers", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656,1d9b9512f925cf8808e7f76d71a788d82089fe76@65.108.198.118:25756") - compareTomlValue(t, configTomlPath, "statesync.enable", "true") - compareTomlValue(t, configTomlPath, "statesync.rpc_servers", "https://initia-testnet-rpc.polkachu.com:443,https://initia-testnet-rpc.polkachu.com:443") - - compareTomlValue(t, appTomlPath, "minimum-gas-prices", "0.15uinit") - compareTomlValue(t, appTomlPath, "api.enable", "true") -} - -func TestInitiaInitLocal(t *testing.T) { - ctx := context.NewAppContext(initia.NewRunL1NodeState()) - ctx = context.SetInitiaHome(ctx, TestInitiaHome) - - firstModel := initia.NewRunL1NodeNetworkSelect(ctx) - - // Ensure that there is no previous Initia home - _, err := os.Stat(TestInitiaHome) - assert.NotNil(t, err) - - steps := []Step{ - pressDown, - pressEnter, - waitFetching, - pressEnter, - typeText("ChainId-1"), - pressEnter, - typeText("Moniker"), - pressEnter, - typeText("0uinit"), - pressEnter, - pressEnter, - pressEnter, - pressEnter, - waitFor(func() bool { - if _, err := os.Stat(TestInitiaHome); os.IsNotExist(err) { - return false - } - return true - }), - } - - finalModel := runProgramWithSteps(t, firstModel, steps) - defer clearTestDir(TestInitiaHome) - - // Check the final state here - assert.IsType(t, &initia.InitializingAppLoading{}, finalModel) - - if _, ok := finalModel.(*initia.InitializingAppLoading); ok { - assert.True(t, ok) - } - - // Check if Initia home has been created - _, err = os.Stat(TestInitiaHome) - assert.Nil(t, err) - - configTomlPath := filepath.Join(TestInitiaHome, "config/config.toml") - appTomlPath := filepath.Join(TestInitiaHome, "config/app.toml") - - if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { - t.Fatalf("Config toml file does not exist: %s", configTomlPath) - } - - if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { - t.Fatalf("App toml file does not exist: %s", appTomlPath) - } - - // Assert values - compareTomlValue(t, configTomlPath, "moniker", "Moniker") - compareTomlValue(t, configTomlPath, "p2p.seeds", "") - compareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") - compareTomlValue(t, configTomlPath, "statesync.enable", false) - compareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") - - compareTomlValue(t, appTomlPath, "minimum-gas-prices", "0uinit") - compareTomlValue(t, appTomlPath, "api.enable", "false") -} - -func TestInitiaInitLocalExisting(t *testing.T) { - ctx := context.NewAppContext(initia.NewRunL1NodeState()) - ctx = context.SetInitiaHome(ctx, TestInitiaHome) - - firstModel := initia.NewRunL1NodeNetworkSelect(ctx) - - // Ensure that there is no previous Initia home - _, err := os.Stat(TestInitiaHome) - assert.NotNil(t, err) - - steps := []Step{ - pressDown, - pressEnter, - waitFetching, - pressEnter, - typeText("ChainId-1"), - pressEnter, - typeText("Moniker"), - pressEnter, - typeText("0uinit"), - pressEnter, - pressEnter, - pressEnter, - pressEnter, - waitFor(func() bool { - if _, err := os.Stat(TestInitiaHome); os.IsNotExist(err) { - return false - } - return true - }), - } - - finalModel := runProgramWithSteps(t, firstModel, steps) - - // Check the final state here - assert.IsType(t, &initia.InitializingAppLoading{}, finalModel) - - if _, ok := finalModel.(*initia.InitializingAppLoading); ok { - assert.True(t, ok) - } - - // Check if Initia home has been created - _, err = os.Stat(TestInitiaHome) - assert.Nil(t, err) - - configTomlPath := filepath.Join(TestInitiaHome, "config/config.toml") - appTomlPath := filepath.Join(TestInitiaHome, "config/app.toml") - - if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { - t.Fatalf("Config toml file does not exist: %s", configTomlPath) - } - - if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { - t.Fatalf("App toml file does not exist: %s", appTomlPath) - } - - // Assert values - compareTomlValue(t, configTomlPath, "moniker", "Moniker") - compareTomlValue(t, configTomlPath, "p2p.seeds", "") - compareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") - compareTomlValue(t, configTomlPath, "statesync.enable", false) - compareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") - - compareTomlValue(t, appTomlPath, "minimum-gas-prices", "0uinit") - compareTomlValue(t, appTomlPath, "api.enable", "false") - - ctx = context.NewAppContext(initia.NewRunL1NodeState()) - ctx = context.SetInitiaHome(ctx, TestInitiaHome) - - firstModel = initia.NewRunL1NodeNetworkSelect(ctx) - - // Ensure that there is an existing Initia home - _, err = os.Stat(TestInitiaHome) - assert.Nil(t, err) - - steps = []Step{ - pressDown, - pressEnter, - waitFetching, - pressEnter, - typeText("ChainId-2"), - pressEnter, - waitFetching, - pressEnter, - waitFetching, - pressEnter, - } - - finalModel = runProgramWithSteps(t, firstModel, steps) - - compareTomlValue(t, configTomlPath, "moniker", "Moniker") - compareTomlValue(t, configTomlPath, "p2p.seeds", "") - compareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") - compareTomlValue(t, configTomlPath, "statesync.enable", false) - compareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") - - compareTomlValue(t, appTomlPath, "minimum-gas-prices", "0uinit") - compareTomlValue(t, appTomlPath, "api.enable", "false") - - ctx = context.NewAppContext(initia.NewRunL1NodeState()) - ctx = context.SetInitiaHome(ctx, TestInitiaHome) - - firstModel = initia.NewRunL1NodeNetworkSelect(ctx) - - // Ensure that there is an existing Initia home - _, err = os.Stat(TestInitiaHome) - assert.Nil(t, err) - - steps = []Step{ - pressDown, - pressEnter, - waitFetching, - pressEnter, - typeText("ChainId-3"), - pressEnter, - waitFetching, - pressUp, - pressEnter, - typeText("NewMoniker"), - pressEnter, - typeText("0.015uinit"), - pressEnter, - pressSpace, - pressDown, - pressSpace, - pressEnter, - pressEnter, - pressEnter, - waitFetching, - pressUp, - pressEnter, - } - - finalModel = runProgramWithSteps(t, firstModel, steps) - defer clearTestDir(TestInitiaHome) - - compareTomlValue(t, configTomlPath, "moniker", "NewMoniker") - compareTomlValue(t, configTomlPath, "p2p.seeds", "") - compareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") - compareTomlValue(t, configTomlPath, "statesync.enable", false) - compareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") - - compareTomlValue(t, appTomlPath, "minimum-gas-prices", "0.015uinit") - compareTomlValue(t, appTomlPath, "api.enable", "true") -} diff --git a/tests/integration/minitia_test.go b/tests/integration/minitia_test.go deleted file mode 100644 index 1f9641f2..00000000 --- a/tests/integration/minitia_test.go +++ /dev/null @@ -1,183 +0,0 @@ -package integration - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/initia-labs/weave/context" - "github.com/initia-labs/weave/models/minitia" -) - -const ( - TestMinitiaHome = ".minitia.weave.test" -) - -func TestMinitiaLaunchWithExisting(t *testing.T) { - _ = setupGasStation(t) - - ctx := context.NewAppContext(*minitia.NewLaunchState()) - ctx = context.SetMinitiaHome(ctx, TestMinitiaHome) - - firstModel := minitia.NewExistingMinitiaChecker(ctx) - - // Ensure that there is no previous Minitia home - _, err := os.Stat(TestMinitiaHome) - assert.NotNil(t, err) - - steps := []Step{ - waitFetching, - pressEnter, - pressEnter, - waitFetching, - pressEnter, - typeText("rollup-1"), - pressEnter, - pressTab, - pressEnter, - pressTab, - pressEnter, - pressTab, - pressEnter, - pressTab, - pressEnter, - pressDown, - pressEnter, - pressEnter, - pressEnter, - waitFetching, - pressDown, - pressEnter, - typeText("1234567"), - pressEnter, - typeText("1000000"), - pressEnter, - typeText("1111111"), - pressEnter, - typeText("234567"), - pressEnter, - typeText("123456789123456789"), - pressEnter, - typeText("123456789123456789"), - pressEnter, - pressDown, - pressEnter, - waitFetching, - waitFetching, - typeText("continue"), - pressEnter, - typeText("y"), - pressEnter, - } - - finalModel := runProgramWithSteps(t, firstModel, steps) - - // Check the final state here - assert.IsType(t, &minitia.TerminalState{}, finalModel) - - if _, ok := finalModel.(*minitia.TerminalState); ok { - assert.True(t, ok) - } - - // Check if Initia home has been created - _, err = os.Stat(TestMinitiaHome) - assert.Nil(t, err) - - configTomlPath := filepath.Join(TestMinitiaHome, "config/config.toml") - appTomlPath := filepath.Join(TestMinitiaHome, "config/app.toml") - - if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { - t.Fatalf("Config toml file does not exist: %s", configTomlPath) - } - - if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { - t.Fatalf("App toml file does not exist: %s", appTomlPath) - } - - // Assert values - compareTomlValue(t, configTomlPath, "p2p.seeds", "") - compareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") - compareTomlValue(t, configTomlPath, "statesync.enable", false) - - compareTomlValue(t, appTomlPath, "minimum-gas-prices", "0umin") - compareTomlValue(t, appTomlPath, "api.enable", true) - - artifactsConfigPath := filepath.Join(TestMinitiaHome, "artifacts/config.json") - - if _, err := os.Stat(artifactsConfigPath); os.IsNotExist(err) { - t.Fatalf("Artifacts config json file does not exist: %s", artifactsConfigPath) - } - - compareJsonValue(t, artifactsConfigPath, "l2_config.chain_id", "rollup-1") - compareJsonValue(t, artifactsConfigPath, "l2_config.denom", "umin") - compareJsonValue(t, artifactsConfigPath, "l2_config.moniker", "operator") - compareJsonValue(t, artifactsConfigPath, "op_bridge.enable_oracle", true) - - // Try again with existing Minitia home - ctx = context.NewAppContext(*minitia.NewLaunchState()) - ctx = context.SetMinitiaHome(ctx, TestMinitiaHome) - - firstModel = minitia.NewExistingMinitiaChecker(ctx) - - // Ensure that there is an existing Minitia home - _, err = os.Stat(TestMinitiaHome) - assert.Nil(t, err) - - steps = []Step{ - waitFetching, - typeText("delete"), - pressEnter, - pressEnter, - pressDown, - pressEnter, - waitFetching, - typeText("rollup-2"), - pressEnter, - typeText("uroll"), - pressEnter, - typeText("computer"), - pressEnter, - pressTab, - pressEnter, - pressTab, - pressEnter, - pressDown, - pressEnter, - pressEnter, - pressDown, - pressEnter, - typeText("lonely fly lend protect mix order legal organ fruit donkey dog state"), - pressEnter, - typeText("boy salmon resist afford dog cereal first myth require enough sunny cargo"), - pressEnter, - typeText("young diagram garment finish barrel output pledge borrow tonight frozen clerk sadness"), - pressEnter, - typeText("patrol search opera diary hidden giggle crisp together toy print lemon very"), - pressEnter, - typeText("door radar exhibit equip mom beach drift harbor tomorrow tree long stereo"), - pressEnter, - waitFetching, - pressEnter, - pressEnter, - typeText("init16pawh0v7w996jrmtzugz3hmhq0wx6ndq5pp0dr"), - pressEnter, - typeText("1234567890"), - pressEnter, - pressDown, - pressEnter, - waitFetching, - waitFetching, - typeText("y"), - pressEnter, - } - - finalModel = runProgramWithSteps(t, firstModel, steps) - defer clearTestDir(TestMinitiaHome) - - // Assert values - compareJsonValue(t, artifactsConfigPath, "l2_config.chain_id", "rollup-2") - compareJsonValue(t, artifactsConfigPath, "l2_config.denom", "uroll") - compareJsonValue(t, artifactsConfigPath, "l2_config.moniker", "computer") -} diff --git a/tests/integration/opinit_test.go b/tests/integration/opinit_test.go deleted file mode 100644 index 5d765deb..00000000 --- a/tests/integration/opinit_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package integration - -const ( - TestOPInitHome = ".opinit.weave.test" -) - -// func setupOPInitBots(t *testing.T) tea.Model { -// ctx := context.NewAppContext(opinit_bots.NewOPInitBotsState()) -// ctx = context.SetOPInitHome(ctx, TestOPInitHome) - -// versions, currentVersion := cosmosutils.GetOPInitVersions() -// firstModel := opinit_bots.NewOPInitBotVersionSelector(ctx, versions, currentVersion) - -// // Ensure that there is no previous OPInit home -// _, err := os.Stat(TestOPInitHome) -// assert.NotNil(t, err) - -// steps := []Step{ -// pressEnter, -// pressEnter, -// pressSpace, -// pressDown, -// pressSpace, -// pressDown, -// pressSpace, -// pressDown, -// pressSpace, -// pressEnter, -// pressEnter, -// pressEnter, -// pressEnter, -// pressEnter, -// pressEnter, -// } - -// return runProgramWithSteps(t, firstModel, steps) -// } - -// func TestOPInitBotsSetup(t *testing.T) { -// finalModel := setupOPInitBots(t) - -// // Check the final state here -// assert.IsType(t, &opinit_bots.TerminalState{}, finalModel) - -// if _, ok := finalModel.(*opinit_bots.TerminalState); ok { -// assert.True(t, ok) -// } - -// // Check if OPInit home has been created -// _, err := os.Stat(TestOPInitHome) -// assert.Nil(t, err) - -// // Check the keys have been created -// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_batch_submitter.info")) -// assert.Nil(t, err) - -// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_bridge_executor.info")) -// assert.Nil(t, err) - -// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_challenger.info")) -// assert.Nil(t, err) - -// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_output_submitter.info")) -// assert.Nil(t, err) - -// ctx := context.NewAppContext(opinit_bots.NewOPInitBotsState()) -// ctx = context.SetOPInitHome(ctx, TestOPInitHome) - -// versions, currentVersion := cosmosutils.GetOPInitVersions() -// firstModel := opinit_bots.NewOPInitBotVersionSelector(ctx, versions, currentVersion) - -// // Ensure that there is an existing OPInit home -// _, err = os.Stat(TestOPInitHome) -// assert.Nil(t, err) - -// steps := []Step{ -// pressEnter, -// pressEnter, -// pressSpace, -// pressDown, -// pressSpace, -// pressDown, -// pressSpace, -// pressDown, -// pressSpace, -// pressEnter, -// pressDown, -// pressEnter, -// typeText("false seek emerge venue park present color knock notice spike use notable"), -// pressEnter, -// pressDown, -// pressEnter, -// typeText("people assist noble flower turtle canoe sand wall useful accuse trash zone"), -// pressEnter, -// pressDown, -// pressEnter, -// typeText("delay brick cradle knock indoor squeeze enlist arrange smooth limit symbol south"), -// pressEnter, -// pressEnter, -// pressDown, -// pressEnter, -// typeText("educate protect return spirit finger region portion dish seven boost measure chase"), -// pressEnter, -// } - -// finalModel = runProgramWithSteps(t, firstModel, steps) -// defer clearTestDir(TestOPInitHome) - -// // Let's test the keys -// userHome, _ := os.UserHomeDir() -// opinitBinary := filepath.Join(userHome, common.WeaveDataDirectory, "opinitd") - -// cmd := exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_batch_submitter", "--home", TestOPInitHome) -// outputBytes, err := cmd.CombinedOutput() -// assert.Nil(t, err) -// assert.Equal(t, "weave_batch_submitter: init1wzccyequn0yqc5mne6yev6u628yvyfwpr7y38d\n", string(outputBytes), "Mismatch for key weave_batch_submitter, expected init1wzccyequn0yqc5mne6yev6u628yvyfwpr7y38d but got %s", string(outputBytes)) - -// cmd = exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_bridge_executor", "--home", TestOPInitHome) -// outputBytes, err = cmd.CombinedOutput() -// assert.Nil(t, err) -// assert.Equal(t, "weave_bridge_executor: init1eul78cxrljfn47l0f7qpgue7l3p9pa9j86w6hq\n", string(outputBytes), "Mismatch for key weave_bridge_executor, expected init1eul78cxrljfn47l0f7qpgue7l3p9pa9j86w6hq but got %s", string(outputBytes)) - -// cmd = exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_challenger", "--home", TestOPInitHome) -// outputBytes, err = cmd.CombinedOutput() -// assert.Nil(t, err) -// assert.Equal(t, "weave_challenger: init1masuevcdvkra3nr7p2dkwa8lq2hga75ym279tr\n", string(outputBytes), "Mismatch for key weave_challenger, expected init1masuevcdvkra3nr7p2dkwa8lq2hga75ym279tr but got %s", string(outputBytes)) - -// cmd = exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_output_submitter", "--home", TestOPInitHome) -// outputBytes, err = cmd.CombinedOutput() -// assert.Nil(t, err) -// assert.Equal(t, "weave_output_submitter: init1kd3fc4407sgaakguj4scvhzdv6r907ncdetd94\n", string(outputBytes), "Mismatch for key weave_output_submitter, expected init1kd3fc4407sgaakguj4scvhzdv6r907ncdetd94 but got %s", string(outputBytes)) -// } - -// -//func TestOPInitBotsInit(t *testing.T) { -// ctx := utils.NewAppContext(opinit_bots.NewOPInitBotsState()) -// ctx = utils.SetOPInitHome(ctx, TestOPInitHome) -// -// firstModel := opinit_bots.NewOPInitBotInitSelector(ctx) -// -// // Ensure that there is no previous OPInit home -// _, err := os.Stat(TestOPInitHome) -// assert.NotNil(t, err) -// -// steps := []Step{ -// pressEnter, -// pressEnter, -// pressTab, -// pressEnter, -// } -// -// finalModel := runProgramWithSteps(t, firstModel, steps) -// -// // Check the final state here -// assert.IsType(t, &opinit_bots.TerminalState{}, finalModel) -// -// if _, ok := finalModel.(*opinit_bots.TerminalState); ok { -// assert.True(t, ok) -// } -//} diff --git a/tests/integration/testutil.go b/tests/integration/testutil.go deleted file mode 100644 index 3bdd3ae2..00000000 --- a/tests/integration/testutil.go +++ /dev/null @@ -1,168 +0,0 @@ -package integration - -import ( - "encoding/json" - "fmt" - "os" - "strings" - "testing" - "time" - - tea "github.com/charmbracelet/bubbletea" - "github.com/pelletier/go-toml/v2" - "github.com/stretchr/testify/assert" -) - -const ( - DefaultMaxWaitRetry = 300 - DefaultPostWaitPeriod = 5 * time.Second -) - -type Step interface { - Execute(prog tea.Program) - Wait() bool -} - -type Steps []Step - -type InputStep struct { - Msg tea.Msg -} - -func (i InputStep) Execute(prog tea.Program) { - prog.Send(i.Msg) -} - -func (i InputStep) Wait() bool { - return true -} - -type WaitStep struct { - Check func() bool -} - -func (w WaitStep) Execute(_ tea.Program) {} - -func (w WaitStep) Wait() bool { - return w.Check() -} - -func runProgramWithSteps(t *testing.T, program tea.Model, steps Steps) tea.Model { - prog := tea.NewProgram(program, tea.WithInput(nil)) - done := make(chan struct{}) - finalModel := tea.Model(nil) - - go func() { - var err error - finalModel, err = prog.Run() - if err != nil { - t.Errorf("Program run failed: %v", err) - return - } - close(done) - }() - - for _, step := range steps { - if waitStep, ok := step.(WaitStep); ok { - retryCount := 0 - for { - if waitStep.Wait() { - break - } - - if retryCount >= DefaultMaxWaitRetry { - t.Errorf("Max retries reached while waiting for condition in WaitStep") - return nil - } - - retryCount++ - time.Sleep(100 * time.Millisecond) - } - time.Sleep(DefaultPostWaitPeriod) - } - - step.Execute(*prog) - time.Sleep(100 * time.Millisecond) - } - - <-done - return finalModel -} - -func clearTestDir(dir string) { - if err := os.RemoveAll(dir); err != nil { - panic(fmt.Sprintf("failed to remove test directory: %v", err)) - } -} - -func getTomlValue(filePath, key string) (interface{}, error) { - data, err := os.ReadFile(filePath) - if err != nil { - return nil, err - } - - var tomlData map[string]interface{} - if err := toml.Unmarshal(data, &tomlData); err != nil { - return nil, err - } - - parts := strings.Split(key, ".") - current := tomlData - - for i, part := range parts { - if i == len(parts)-1 { - return current[part], nil - } - - next, ok := current[part].(map[string]interface{}) - if !ok { - return nil, nil - } - current = next - } - - return nil, nil -} - -func compareTomlValue(t *testing.T, filePath, key string, expectedValue interface{}) { - value, err := getTomlValue(filePath, key) - assert.NoError(t, err, "Error loading TOML file or traversing key") - - assert.Equal(t, expectedValue, value, "Mismatch for key %s", key) -} - -func getJsonValue(filePath, key string) (interface{}, error) { - data, err := os.ReadFile(filePath) - if err != nil { - return nil, err - } - - var jsonData map[string]interface{} - if err := json.Unmarshal(data, &jsonData); err != nil { - return nil, err - } - - parts := strings.Split(key, ".") - current := jsonData - - for i, part := range parts { - if i == len(parts)-1 { - return current[part], nil - } - - next, ok := current[part].(map[string]interface{}) - if !ok { - return nil, nil - } - current = next - } - - return nil, nil -} - -func compareJsonValue(t *testing.T, filePath, key string, expectedValue interface{}) { - value, err := getJsonValue(filePath, key) - assert.NoError(t, err, "Error loading JSON file or traversing key") - - assert.Equal(t, expectedValue, value, "Mismatch for key %s", key) -} From e8c9215a984692d9cb1af8a6fa2bcd1a90e6c017 Mon Sep 17 00:00:00 2001 From: Wasin Watthanasrisong Date: Mon, 9 Dec 2024 18:08:30 +0700 Subject: [PATCH 3/5] fix: parallel integration tests --- .github/workflows/basic-checks.yml | 26 +- tests/integration/alias.go | 29 ++ .../gas_station_test/gas_station_test.go | 34 ++ tests/integration/initia_test/initia_test.go | 401 ++++++++++++++++++ .../integration/minitia_test/minitia_test.go | 185 ++++++++ tests/integration/opinit_test/opinit_test.go | 160 +++++++ tests/integration/testutil.go | 188 ++++++++ 7 files changed, 1000 insertions(+), 23 deletions(-) create mode 100644 tests/integration/alias.go create mode 100644 tests/integration/gas_station_test/gas_station_test.go create mode 100644 tests/integration/initia_test/initia_test.go create mode 100644 tests/integration/minitia_test/minitia_test.go create mode 100644 tests/integration/opinit_test/opinit_test.go create mode 100644 tests/integration/testutil.go diff --git a/.github/workflows/basic-checks.yml b/.github/workflows/basic-checks.yml index bbe5f307..16dc3ad9 100644 --- a/.github/workflows/basic-checks.yml +++ b/.github/workflows/basic-checks.yml @@ -18,8 +18,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: 1.22.6 - check-latest: true + go-version: "1.22.6" - uses: technote-space/get-diff-action@v6.1.2 id: git_diff with: @@ -28,27 +27,8 @@ jobs: go.mod go.sum - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION} - - name: run go linters (long) - if: env.GIT_DIFF - id: lint_long - run: | - make lint - env: - GIT_DIFF: ${{ env.GIT_DIFF }} - - uses: technote-space/get-diff-action@v6.1.2 - if: steps.lint_long.outcome == 'skipped' - with: - PATTERNS: | - **/**.go - go.mod - go.sum - - name: run go linters (short) - if: steps.lint_long.outcome == 'skipped' && env.GIT_DIFF - run: | - make lint - env: - GIT_DIFF: ${{ env.GIT_DIFF }} - LINT_DIFF: 1 + - name: Run golangci-lint + run: make lint unit-tests: runs-on: ubuntu-latest steps: diff --git a/tests/integration/alias.go b/tests/integration/alias.go new file mode 100644 index 00000000..a3ce2c19 --- /dev/null +++ b/tests/integration/alias.go @@ -0,0 +1,29 @@ +package integration + +import ( + "time" + + tea "github.com/charmbracelet/bubbletea" +) + +var ( + PressEnter = InputStep{Msg: tea.KeyMsg{Type: tea.KeyEnter}} + PressSpace = InputStep{Msg: tea.KeyMsg{Type: tea.KeySpace}} + PressTab = InputStep{Msg: tea.KeyMsg{Type: tea.KeyTab}} + PressUp = InputStep{Msg: tea.KeyMsg{Type: tea.KeyUp}} + PressDown = InputStep{Msg: tea.KeyMsg{Type: tea.KeyDown}} + + WaitFetching = WaitStep{Check: func() bool { + time.Sleep(5 * time.Second) + return true + }} +) + +func TypeText(text string) InputStep { + return InputStep{Msg: tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune(text)}} +} + +// waitFor receives waitCondition as a parameter, which should return true if the wait should be over. +func WaitFor(waitCondition func() bool) WaitStep { + return WaitStep{Check: waitCondition} +} diff --git a/tests/integration/gas_station_test/gas_station_test.go b/tests/integration/gas_station_test/gas_station_test.go new file mode 100644 index 00000000..4aaab7dd --- /dev/null +++ b/tests/integration/gas_station_test/gas_station_test.go @@ -0,0 +1,34 @@ +package gas_station_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/initia-labs/weave/common" + "github.com/initia-labs/weave/models" + "github.com/initia-labs/weave/tests/integration" +) + +func TestGasStationSetup(t *testing.T) { + finalModel := integration.SetupGasStation(t) + + // Check the final state here + assert.IsType(t, &models.WeaveAppSuccessfullyInitialized{}, finalModel) + + if _, ok := finalModel.(*models.WeaveAppSuccessfullyInitialized); ok { + assert.True(t, ok) + } + + // Check if Weave home has been created + userHome, _ := os.UserHomeDir() + weaveDir := filepath.Join(userHome, common.WeaveDirectory) + _, err := os.Stat(weaveDir) + assert.Nil(t, err) + + // Assert values + weaveConfig := filepath.Join(weaveDir, "config.json") + integration.CompareJsonValue(t, weaveConfig, "common.gas_station_mnemonic", integration.GasStationMnemonic) +} diff --git a/tests/integration/initia_test/initia_test.go b/tests/integration/initia_test/initia_test.go new file mode 100644 index 00000000..a9085940 --- /dev/null +++ b/tests/integration/initia_test/initia_test.go @@ -0,0 +1,401 @@ +package initia_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/initia-labs/weave/context" + "github.com/initia-labs/weave/models/initia" + "github.com/initia-labs/weave/tests/integration" +) + +const ( + TestInitiaHome = ".initia.weave.test" +) + +func TestInitiaInitTestnetNoSync(t *testing.T) { + t.Parallel() + ctx := context.NewAppContext(initia.NewRunL1NodeState()) + initiaHome := TestInitiaHome + ".nosync" + ctx = context.SetInitiaHome(ctx, initiaHome) + + firstModel := initia.NewRunL1NodeNetworkSelect(ctx) + + // Ensure that there is no previous Initia home + _, err := os.Stat(initiaHome) + assert.NotNil(t, err) + + steps := integration.Steps{ + integration.PressEnter, + integration.TypeText("Moniker"), + integration.PressEnter, + integration.PressSpace, + integration.PressEnter, + integration.TypeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), + integration.PressEnter, + integration.TypeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), + integration.PressEnter, + integration.WaitFor(func() bool { + if _, err := os.Stat(initiaHome); os.IsNotExist(err) { + return false + } + return true + }), + integration.PressDown, + integration.PressDown, + integration.PressEnter, + } + + finalModel := integration.RunProgramWithSteps(t, firstModel, steps) + defer integration.ClearTestDir(initiaHome) + + // Check the final state here + assert.IsType(t, &initia.TerminalState{}, finalModel) + + if _, ok := finalModel.(*initia.TerminalState); ok { + assert.True(t, ok) + } + + // Check if Initia home has been created + _, err = os.Stat(initiaHome) + assert.Nil(t, err) + + configTomlPath := filepath.Join(initiaHome, "config/config.toml") + appTomlPath := filepath.Join(initiaHome, "config/app.toml") + + if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { + t.Fatalf("Config toml file does not exist: %s", configTomlPath) + } + + if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { + t.Fatalf("App toml file does not exist: %s", appTomlPath) + } + + // Assert values + integration.CompareTomlValue(t, configTomlPath, "moniker", "Moniker") + integration.CompareTomlValue(t, configTomlPath, "p2p.seeds", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656") + integration.CompareTomlValue(t, configTomlPath, "p2p.persistent_peers", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656") + integration.CompareTomlValue(t, configTomlPath, "statesync.enable", false) + + integration.CompareTomlValue(t, appTomlPath, "minimum-gas-prices", "0.15uinit") + integration.CompareTomlValue(t, appTomlPath, "api.enable", "true") +} + +func TestInitiaInitTestnetStatesync(t *testing.T) { + t.Parallel() + ctx := context.NewAppContext(initia.NewRunL1NodeState()) + initiaHome := TestInitiaHome + ".statesync" + ctx = context.SetInitiaHome(ctx, initiaHome) + + firstModel := initia.NewRunL1NodeNetworkSelect(ctx) + + // Ensure that there is no previous Initia home + _, err := os.Stat(initiaHome) + assert.NotNil(t, err) + + steps := integration.Steps{ + integration.PressEnter, + integration.TypeText("Moniker"), + integration.PressEnter, + integration.PressSpace, + integration.PressEnter, + integration.TypeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), + integration.PressEnter, + integration.TypeText("3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656"), + integration.PressEnter, + integration.WaitFor(func() bool { + if _, err := os.Stat(initiaHome); os.IsNotExist(err) { + return false + } + return true + }), + integration.PressDown, + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressEnter, + integration.TypeText("https://initia-testnet-rpc.polkachu.com:443"), + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.TypeText("1d9b9512f925cf8808e7f76d71a788d82089fe76@65.108.198.118:25756"), + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + } + + finalModel := integration.RunProgramWithSteps(t, firstModel, steps) + defer integration.ClearTestDir(initiaHome) + + // Check the final state here + assert.IsType(t, &initia.TerminalState{}, finalModel) + + if _, ok := finalModel.(*initia.TerminalState); ok { + assert.True(t, ok) + } + + // Check if Initia home has been created + _, err = os.Stat(initiaHome) + assert.Nil(t, err) + + configTomlPath := filepath.Join(initiaHome, "config/config.toml") + appTomlPath := filepath.Join(initiaHome, "config/app.toml") + + if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { + t.Fatalf("Config toml file does not exist: %s", configTomlPath) + } + + if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { + t.Fatalf("App toml file does not exist: %s", appTomlPath) + } + + // Assert values + integration.CompareTomlValue(t, configTomlPath, "moniker", "Moniker") + integration.CompareTomlValue(t, configTomlPath, "p2p.seeds", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656") + integration.CompareTomlValue(t, configTomlPath, "p2p.persistent_peers", "3715cdb41efb45714eb534c3943c5947f4894787@34.143.179.242:26656,1d9b9512f925cf8808e7f76d71a788d82089fe76@65.108.198.118:25756") + integration.CompareTomlValue(t, configTomlPath, "statesync.enable", "true") + integration.CompareTomlValue(t, configTomlPath, "statesync.rpc_servers", "https://initia-testnet-rpc.polkachu.com:443,https://initia-testnet-rpc.polkachu.com:443") + + integration.CompareTomlValue(t, appTomlPath, "minimum-gas-prices", "0.15uinit") + integration.CompareTomlValue(t, appTomlPath, "api.enable", "true") +} + +func TestInitiaInitLocal(t *testing.T) { + t.Parallel() + ctx := context.NewAppContext(initia.NewRunL1NodeState()) + initiaHome := TestInitiaHome + ".local" + ctx = context.SetInitiaHome(ctx, initiaHome) + + firstModel := initia.NewRunL1NodeNetworkSelect(ctx) + + // Ensure that there is no previous Initia home + _, err := os.Stat(initiaHome) + assert.NotNil(t, err) + + steps := []integration.Step{ + integration.PressDown, + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressEnter, + integration.TypeText("ChainId-1"), + integration.PressEnter, + integration.TypeText("Moniker"), + integration.PressEnter, + integration.TypeText("0uinit"), + integration.PressEnter, + integration.PressEnter, + integration.PressEnter, + integration.PressEnter, + integration.WaitFor(func() bool { + if _, err := os.Stat(initiaHome); os.IsNotExist(err) { + return false + } + return true + }), + } + + finalModel := integration.RunProgramWithSteps(t, firstModel, steps) + defer integration.ClearTestDir(initiaHome) + + // Check the final state here + assert.IsType(t, &initia.InitializingAppLoading{}, finalModel) + + if _, ok := finalModel.(*initia.InitializingAppLoading); ok { + assert.True(t, ok) + } + + // Check if Initia home has been created + _, err = os.Stat(initiaHome) + assert.Nil(t, err) + + configTomlPath := filepath.Join(initiaHome, "config/config.toml") + appTomlPath := filepath.Join(initiaHome, "config/app.toml") + + if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { + t.Fatalf("Config toml file does not exist: %s", configTomlPath) + } + + if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { + t.Fatalf("App toml file does not exist: %s", appTomlPath) + } + + // Assert values + integration.CompareTomlValue(t, configTomlPath, "moniker", "Moniker") + integration.CompareTomlValue(t, configTomlPath, "p2p.seeds", "") + integration.CompareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") + integration.CompareTomlValue(t, configTomlPath, "statesync.enable", false) + integration.CompareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") + + integration.CompareTomlValue(t, appTomlPath, "minimum-gas-prices", "0uinit") + integration.CompareTomlValue(t, appTomlPath, "api.enable", "false") +} + +func TestInitiaInitLocalExisting(t *testing.T) { + t.Parallel() + ctx := context.NewAppContext(initia.NewRunL1NodeState()) + initiaHome := TestInitiaHome + ".local.existing" + ctx = context.SetInitiaHome(ctx, initiaHome) + + firstModel := initia.NewRunL1NodeNetworkSelect(ctx) + + // Ensure that there is no previous Initia home + _, err := os.Stat(initiaHome) + assert.NotNil(t, err) + + steps := []integration.Step{ + integration.PressDown, + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressEnter, + integration.TypeText("ChainId-1"), + integration.PressEnter, + integration.TypeText("Moniker"), + integration.PressEnter, + integration.TypeText("0uinit"), + integration.PressEnter, + integration.PressEnter, + integration.PressEnter, + integration.PressEnter, + integration.WaitFor(func() bool { + if _, err := os.Stat(initiaHome); os.IsNotExist(err) { + return false + } + return true + }), + } + + finalModel := integration.RunProgramWithSteps(t, firstModel, steps) + + // Check the final state here + assert.IsType(t, &initia.InitializingAppLoading{}, finalModel) + + if _, ok := finalModel.(*initia.InitializingAppLoading); ok { + assert.True(t, ok) + } + + // Check if Initia home has been created + _, err = os.Stat(initiaHome) + assert.Nil(t, err) + + configTomlPath := filepath.Join(initiaHome, "config/config.toml") + appTomlPath := filepath.Join(initiaHome, "config/app.toml") + + if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { + t.Fatalf("Config toml file does not exist: %s", configTomlPath) + } + + if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { + t.Fatalf("App toml file does not exist: %s", appTomlPath) + } + + // Assert values + integration.CompareTomlValue(t, configTomlPath, "moniker", "Moniker") + integration.CompareTomlValue(t, configTomlPath, "p2p.seeds", "") + integration.CompareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") + integration.CompareTomlValue(t, configTomlPath, "statesync.enable", false) + integration.CompareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") + + integration.CompareTomlValue(t, appTomlPath, "minimum-gas-prices", "0uinit") + integration.CompareTomlValue(t, appTomlPath, "api.enable", "false") + + ctx = context.NewAppContext(initia.NewRunL1NodeState()) + ctx = context.SetInitiaHome(ctx, initiaHome) + + firstModel = initia.NewRunL1NodeNetworkSelect(ctx) + + // Ensure that there is an existing Initia home + _, err = os.Stat(initiaHome) + assert.Nil(t, err) + + steps = []integration.Step{ + integration.PressDown, + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressEnter, + integration.TypeText("ChainId-2"), + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressEnter, + } + + finalModel = integration.RunProgramWithSteps(t, firstModel, steps) + + integration.CompareTomlValue(t, configTomlPath, "moniker", "Moniker") + integration.CompareTomlValue(t, configTomlPath, "p2p.seeds", "") + integration.CompareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") + integration.CompareTomlValue(t, configTomlPath, "statesync.enable", false) + integration.CompareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") + + integration.CompareTomlValue(t, appTomlPath, "minimum-gas-prices", "0uinit") + integration.CompareTomlValue(t, appTomlPath, "api.enable", "false") + + ctx = context.NewAppContext(initia.NewRunL1NodeState()) + ctx = context.SetInitiaHome(ctx, initiaHome) + + firstModel = initia.NewRunL1NodeNetworkSelect(ctx) + + // Ensure that there is an existing Initia home + _, err = os.Stat(initiaHome) + assert.Nil(t, err) + + steps = integration.Steps{ + integration.PressDown, + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressEnter, + integration.TypeText("ChainId-3"), + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressUp, + integration.PressEnter, + integration.TypeText("NewMoniker"), + integration.PressEnter, + integration.TypeText("0.015uinit"), + integration.PressEnter, + integration.PressSpace, + integration.PressDown, + integration.PressSpace, + integration.PressEnter, + integration.PressEnter, + integration.PressEnter, + integration.WaitFor(func() bool { + return true + }), + integration.PressUp, + integration.PressEnter, + } + + finalModel = integration.RunProgramWithSteps(t, firstModel, steps) + defer integration.ClearTestDir(initiaHome) + + integration.CompareTomlValue(t, configTomlPath, "moniker", "NewMoniker") + integration.CompareTomlValue(t, configTomlPath, "p2p.seeds", "") + integration.CompareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") + integration.CompareTomlValue(t, configTomlPath, "statesync.enable", false) + integration.CompareTomlValue(t, configTomlPath, "statesync.rpc_servers", "") + + integration.CompareTomlValue(t, appTomlPath, "minimum-gas-prices", "0.015uinit") + integration.CompareTomlValue(t, appTomlPath, "api.enable", "true") +} diff --git a/tests/integration/minitia_test/minitia_test.go b/tests/integration/minitia_test/minitia_test.go new file mode 100644 index 00000000..c81fe8cb --- /dev/null +++ b/tests/integration/minitia_test/minitia_test.go @@ -0,0 +1,185 @@ +package minitia_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/initia-labs/weave/context" + "github.com/initia-labs/weave/models/minitia" + "github.com/initia-labs/weave/tests/integration" +) + +const ( + TestMinitiaHome = ".minitia.weave.test" +) + +func TestMinitiaLaunchWithExisting(t *testing.T) { + t.Skip("Skipping minitia launch with existing test") + _ = integration.SetupGasStation(t) + + ctx := context.NewAppContext(*minitia.NewLaunchState()) + ctx = context.SetMinitiaHome(ctx, TestMinitiaHome) + + firstModel := minitia.NewExistingMinitiaChecker(ctx) + + // Ensure that there is no previous Minitia home + _, err := os.Stat(TestMinitiaHome) + assert.NotNil(t, err) + + steps := integration.Steps{ + integration.WaitFetching, + integration.PressEnter, + integration.PressEnter, + integration.WaitFetching, + integration.PressEnter, + integration.TypeText("rollup-1"), + integration.PressEnter, + integration.PressTab, + integration.PressEnter, + integration.PressTab, + integration.PressEnter, + integration.PressTab, + integration.PressEnter, + integration.PressTab, + integration.PressEnter, + integration.PressDown, + integration.PressEnter, + integration.PressEnter, + integration.PressEnter, + integration.WaitFetching, + integration.PressDown, + integration.PressEnter, + integration.TypeText("1234567"), + integration.PressEnter, + integration.TypeText("1000000"), + integration.PressEnter, + integration.TypeText("1111111"), + integration.PressEnter, + integration.TypeText("234567"), + integration.PressEnter, + integration.TypeText("123456789123456789"), + integration.PressEnter, + integration.TypeText("123456789123456789"), + integration.PressEnter, + integration.PressDown, + integration.PressEnter, + integration.WaitFetching, + integration.WaitFetching, + integration.TypeText("continue"), + integration.PressEnter, + integration.TypeText("y"), + integration.PressEnter, + } + + finalModel := integration.RunProgramWithSteps(t, firstModel, steps) + + // Check the final state here + assert.IsType(t, &minitia.TerminalState{}, finalModel) + + if _, ok := finalModel.(*minitia.TerminalState); ok { + assert.True(t, ok) + } + + // Check if Initia home has been created + _, err = os.Stat(TestMinitiaHome) + assert.Nil(t, err) + + configTomlPath := filepath.Join(TestMinitiaHome, "config/config.toml") + appTomlPath := filepath.Join(TestMinitiaHome, "config/app.toml") + + if _, err := os.Stat(configTomlPath); os.IsNotExist(err) { + t.Fatalf("Config toml file does not exist: %s", configTomlPath) + } + + if _, err := os.Stat(appTomlPath); os.IsNotExist(err) { + t.Fatalf("App toml file does not exist: %s", appTomlPath) + } + + // Assert values + integration.CompareTomlValue(t, configTomlPath, "p2p.seeds", "") + integration.CompareTomlValue(t, configTomlPath, "p2p.persistent_peers", "") + integration.CompareTomlValue(t, configTomlPath, "statesync.enable", false) + + integration.CompareTomlValue(t, appTomlPath, "minimum-gas-prices", "0umin") + integration.CompareTomlValue(t, appTomlPath, "api.enable", true) + + artifactsConfigPath := filepath.Join(TestMinitiaHome, "artifacts/config.json") + + if _, err := os.Stat(artifactsConfigPath); os.IsNotExist(err) { + t.Fatalf("Artifacts config json file does not exist: %s", artifactsConfigPath) + } + + integration.CompareJsonValue(t, artifactsConfigPath, "l2_config.chain_id", "rollup-1") + integration.CompareJsonValue(t, artifactsConfigPath, "l2_config.denom", "umin") + integration.CompareJsonValue(t, artifactsConfigPath, "l2_config.moniker", "operator") + integration.CompareJsonValue(t, artifactsConfigPath, "op_bridge.enable_oracle", true) + + // Try again with existing Minitia home + ctx = context.NewAppContext(*minitia.NewLaunchState()) + ctx = context.SetMinitiaHome(ctx, TestMinitiaHome) + + firstModel = minitia.NewExistingMinitiaChecker(ctx) + + // Ensure that there is an existing Minitia home + _, err = os.Stat(TestMinitiaHome) + assert.Nil(t, err) + + steps = integration.Steps{ + integration.WaitFetching, + integration.TypeText("delete"), + integration.PressEnter, + integration.PressEnter, + integration.PressDown, + integration.PressEnter, + integration.WaitFetching, + integration.TypeText("rollup-2"), + integration.PressEnter, + integration.TypeText("uroll"), + integration.PressEnter, + integration.TypeText("computer"), + integration.PressEnter, + integration.PressTab, + integration.PressEnter, + integration.PressTab, + integration.PressEnter, + integration.PressDown, + integration.PressEnter, + integration.PressEnter, + integration.PressDown, + integration.PressEnter, + integration.TypeText("lonely fly lend protect mix order legal organ fruit donkey dog state"), + integration.PressEnter, + integration.TypeText("boy salmon resist afford dog cereal first myth require enough sunny cargo"), + integration.PressEnter, + integration.TypeText("young diagram garment finish barrel output pledge borrow tonight frozen clerk sadness"), + integration.PressEnter, + integration.TypeText("patrol search opera diary hidden giggle crisp together toy print lemon very"), + integration.PressEnter, + integration.TypeText("door radar exhibit equip mom beach drift harbor tomorrow tree long stereo"), + integration.PressEnter, + integration.WaitFetching, + integration.PressEnter, + integration.PressEnter, + integration.TypeText("init16pawh0v7w996jrmtzugz3hmhq0wx6ndq5pp0dr"), + integration.PressEnter, + integration.TypeText("1234567890"), + integration.PressEnter, + integration.PressDown, + integration.PressEnter, + integration.WaitFetching, + integration.WaitFetching, + integration.TypeText("y"), + integration.PressEnter, + } + + finalModel = integration.RunProgramWithSteps(t, firstModel, steps) + defer integration.ClearTestDir(TestMinitiaHome) + + // Assert values + integration.CompareJsonValue(t, artifactsConfigPath, "l2_config.chain_id", "rollup-2") + integration.CompareJsonValue(t, artifactsConfigPath, "l2_config.denom", "uroll") + integration.CompareJsonValue(t, artifactsConfigPath, "l2_config.moniker", "computer") +} diff --git a/tests/integration/opinit_test/opinit_test.go b/tests/integration/opinit_test/opinit_test.go new file mode 100644 index 00000000..86c5eab1 --- /dev/null +++ b/tests/integration/opinit_test/opinit_test.go @@ -0,0 +1,160 @@ +package opinit_test + +const ( + TestOPInitHome = ".opinit.weave.test" +) + +// func setupOPInitBots(t *testing.T) tea.Model { +// ctx := context.NewAppContext(opinit_bots.NewOPInitBotsState()) +// ctx = context.SetOPInitHome(ctx, TestOPInitHome) + +// versions, currentVersion := cosmosutils.GetOPInitVersions() +// firstModel := opinit_bots.NewOPInitBotVersionSelector(ctx, versions, currentVersion) + +// // Ensure that there is no previous OPInit home +// _, err := os.Stat(TestOPInitHome) +// assert.NotNil(t, err) + +// steps := []Step{ +// pressEnter, +// pressEnter, +// pressSpace, +// pressDown, +// pressSpace, +// pressDown, +// pressSpace, +// pressDown, +// pressSpace, +// pressEnter, +// pressEnter, +// pressEnter, +// pressEnter, +// pressEnter, +// pressEnter, +// } + +// return runProgramWithSteps(t, firstModel, steps) +// } + +// func TestOPInitBotsSetup(t *testing.T) { +// finalModel := setupOPInitBots(t) + +// // Check the final state here +// assert.IsType(t, &opinit_bots.TerminalState{}, finalModel) + +// if _, ok := finalModel.(*opinit_bots.TerminalState); ok { +// assert.True(t, ok) +// } + +// // Check if OPInit home has been created +// _, err := os.Stat(TestOPInitHome) +// assert.Nil(t, err) + +// // Check the keys have been created +// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_batch_submitter.info")) +// assert.Nil(t, err) + +// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_bridge_executor.info")) +// assert.Nil(t, err) + +// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_challenger.info")) +// assert.Nil(t, err) + +// _, err = os.Stat(filepath.Join(TestOPInitHome, "weave-dummy/keyring-test/weave_output_submitter.info")) +// assert.Nil(t, err) + +// ctx := context.NewAppContext(opinit_bots.NewOPInitBotsState()) +// ctx = context.SetOPInitHome(ctx, TestOPInitHome) + +// versions, currentVersion := cosmosutils.GetOPInitVersions() +// firstModel := opinit_bots.NewOPInitBotVersionSelector(ctx, versions, currentVersion) + +// // Ensure that there is an existing OPInit home +// _, err = os.Stat(TestOPInitHome) +// assert.Nil(t, err) + +// steps := []Step{ +// pressEnter, +// pressEnter, +// pressSpace, +// pressDown, +// pressSpace, +// pressDown, +// pressSpace, +// pressDown, +// pressSpace, +// pressEnter, +// pressDown, +// pressEnter, +// typeText("false seek emerge venue park present color knock notice spike use notable"), +// pressEnter, +// pressDown, +// pressEnter, +// typeText("people assist noble flower turtle canoe sand wall useful accuse trash zone"), +// pressEnter, +// pressDown, +// pressEnter, +// typeText("delay brick cradle knock indoor squeeze enlist arrange smooth limit symbol south"), +// pressEnter, +// pressEnter, +// pressDown, +// pressEnter, +// typeText("educate protect return spirit finger region portion dish seven boost measure chase"), +// pressEnter, +// } + +// finalModel = runProgramWithSteps(t, firstModel, steps) +// defer clearTestDir(TestOPInitHome) + +// // Let's test the keys +// userHome, _ := os.UserHomeDir() +// opinitBinary := filepath.Join(userHome, common.WeaveDataDirectory, "opinitd") + +// cmd := exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_batch_submitter", "--home", TestOPInitHome) +// outputBytes, err := cmd.CombinedOutput() +// assert.Nil(t, err) +// assert.Equal(t, "weave_batch_submitter: init1wzccyequn0yqc5mne6yev6u628yvyfwpr7y38d\n", string(outputBytes), "Mismatch for key weave_batch_submitter, expected init1wzccyequn0yqc5mne6yev6u628yvyfwpr7y38d but got %s", string(outputBytes)) + +// cmd = exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_bridge_executor", "--home", TestOPInitHome) +// outputBytes, err = cmd.CombinedOutput() +// assert.Nil(t, err) +// assert.Equal(t, "weave_bridge_executor: init1eul78cxrljfn47l0f7qpgue7l3p9pa9j86w6hq\n", string(outputBytes), "Mismatch for key weave_bridge_executor, expected init1eul78cxrljfn47l0f7qpgue7l3p9pa9j86w6hq but got %s", string(outputBytes)) + +// cmd = exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_challenger", "--home", TestOPInitHome) +// outputBytes, err = cmd.CombinedOutput() +// assert.Nil(t, err) +// assert.Equal(t, "weave_challenger: init1masuevcdvkra3nr7p2dkwa8lq2hga75ym279tr\n", string(outputBytes), "Mismatch for key weave_challenger, expected init1masuevcdvkra3nr7p2dkwa8lq2hga75ym279tr but got %s", string(outputBytes)) + +// cmd = exec.Command(opinitBinary, "keys", "show", "weave-dummy", "weave_output_submitter", "--home", TestOPInitHome) +// outputBytes, err = cmd.CombinedOutput() +// assert.Nil(t, err) +// assert.Equal(t, "weave_output_submitter: init1kd3fc4407sgaakguj4scvhzdv6r907ncdetd94\n", string(outputBytes), "Mismatch for key weave_output_submitter, expected init1kd3fc4407sgaakguj4scvhzdv6r907ncdetd94 but got %s", string(outputBytes)) +// } + +// +//func TestOPInitBotsInit(t *testing.T) { +// ctx := utils.NewAppContext(opinit_bots.NewOPInitBotsState()) +// ctx = utils.SetOPInitHome(ctx, TestOPInitHome) +// +// firstModel := opinit_bots.NewOPInitBotInitSelector(ctx) +// +// // Ensure that there is no previous OPInit home +// _, err := os.Stat(TestOPInitHome) +// assert.NotNil(t, err) +// +// steps := []Step{ +// pressEnter, +// pressEnter, +// pressTab, +// pressEnter, +// } +// +// finalModel := runProgramWithSteps(t, firstModel, steps) +// +// // Check the final state here +// assert.IsType(t, &opinit_bots.TerminalState{}, finalModel) +// +// if _, ok := finalModel.(*opinit_bots.TerminalState); ok { +// assert.True(t, ok) +// } +//} diff --git a/tests/integration/testutil.go b/tests/integration/testutil.go new file mode 100644 index 00000000..027ad173 --- /dev/null +++ b/tests/integration/testutil.go @@ -0,0 +1,188 @@ +package integration + +import ( + "encoding/json" + "fmt" + "os" + "strings" + "testing" + "time" + + "github.com/initia-labs/weave/config" + "github.com/initia-labs/weave/context" + "github.com/initia-labs/weave/models" + + tea "github.com/charmbracelet/bubbletea" + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/assert" +) + +const ( + DefaultMaxWaitRetry = 300 + DefaultPostWaitPeriod = 5 * time.Second + GasStationMnemonic = "imitate sick vibrant bonus weather spice pave announce direct impulse strategy math" +) + +type Step interface { + Execute(prog tea.Program) + Wait() bool +} + +type Steps []Step + +type InputStep struct { + Msg tea.Msg +} + +func (i InputStep) Execute(prog tea.Program) { + prog.Send(i.Msg) +} + +func (i InputStep) Wait() bool { + return true +} + +type WaitStep struct { + Check func() bool +} + +func (w WaitStep) Execute(_ tea.Program) {} + +func (w WaitStep) Wait() bool { + return w.Check() +} + +func RunProgramWithSteps(t *testing.T, program tea.Model, steps Steps) tea.Model { + prog := tea.NewProgram(program, tea.WithInput(nil)) + done := make(chan struct{}) + finalModel := tea.Model(nil) + + go func() { + var err error + finalModel, err = prog.Run() + if err != nil { + t.Errorf("Program run failed: %v", err) + return + } + close(done) + }() + + for _, step := range steps { + if waitStep, ok := step.(WaitStep); ok { + retryCount := 0 + for { + if waitStep.Wait() { + break + } + + if retryCount >= DefaultMaxWaitRetry { + t.Errorf("Max retries reached while waiting for condition in WaitStep") + return nil + } + + retryCount++ + time.Sleep(100 * time.Millisecond) + } + time.Sleep(DefaultPostWaitPeriod) + } + + step.Execute(*prog) + time.Sleep(100 * time.Millisecond) + } + + <-done + return finalModel +} + +func ClearTestDir(dir string) { + if err := os.RemoveAll(dir); err != nil { + panic(fmt.Sprintf("failed to remove test directory: %v", err)) + } +} + +func GetTomlValue(filePath, key string) (interface{}, error) { + data, err := os.ReadFile(filePath) + if err != nil { + return nil, err + } + + var tomlData map[string]interface{} + if err := toml.Unmarshal(data, &tomlData); err != nil { + return nil, err + } + + parts := strings.Split(key, ".") + current := tomlData + + for i, part := range parts { + if i == len(parts)-1 { + return current[part], nil + } + + next, ok := current[part].(map[string]interface{}) + if !ok { + return nil, nil + } + current = next + } + + return nil, nil +} + +func CompareTomlValue(t *testing.T, filePath, key string, expectedValue interface{}) { + value, err := GetTomlValue(filePath, key) + assert.NoError(t, err, "Error loading TOML file or traversing key") + + assert.Equal(t, expectedValue, value, "Mismatch for key %s", key) +} + +func GetJsonValue(filePath, key string) (interface{}, error) { + data, err := os.ReadFile(filePath) + if err != nil { + return nil, err + } + + var jsonData map[string]interface{} + if err := json.Unmarshal(data, &jsonData); err != nil { + return nil, err + } + + parts := strings.Split(key, ".") + current := jsonData + + for i, part := range parts { + if i == len(parts)-1 { + return current[part], nil + } + + next, ok := current[part].(map[string]interface{}) + if !ok { + return nil, nil + } + current = next + } + + return nil, nil +} + +func CompareJsonValue(t *testing.T, filePath, key string, expectedValue interface{}) { + value, err := GetJsonValue(filePath, key) + assert.NoError(t, err, "Error loading JSON file or traversing key") + + assert.Equal(t, expectedValue, value, "Mismatch for key %s", key) +} + +func SetupGasStation(t *testing.T) tea.Model { + err := config.InitializeConfig() + assert.Nil(t, err) + + ctx := context.NewAppContext(models.NewExistingCheckerState()) + firstModel := models.NewGasStationMnemonicInput(ctx) + + steps := Steps{ + TypeText(GasStationMnemonic), + PressEnter, + } + + return RunProgramWithSteps(t, firstModel, steps) +} From 00be74c63ee9ba96a653f42634c68e7d978b3c9a Mon Sep 17 00:00:00 2001 From: Wasin Watthanasrisong Date: Mon, 9 Dec 2024 18:12:12 +0700 Subject: [PATCH 4/5] fix: extra space on Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a0abf4d1..463d719f 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ lint-fix: check_version @echo "Warning: This will automatically modify your files to fix linting issues" @read -p "Are you sure you want to continue? [y/N] " -n 1 -r; echo; if [[ ! $$REPLY =~ ^[Yy]$$ ]]; then exit 1; fi @command -v golangci-lint >/dev/null 2>&1 || { echo "golangci-lint is required but not installed. Install it by following instructions at https://golangci-lint.run/welcome/install/"; exit 1; } - golangci-lint run --fix --out-format=tab --timeout=15m + golangci-lint run --fix --out-format=tab --timeout=15m test: check_version go clean -testcache From e79bb8bc8f7b866c1a328e7662c0efb2fcd383d7 Mon Sep 17 00:00:00 2001 From: Wasin Watthanasrisong Date: Mon, 9 Dec 2024 18:26:15 +0700 Subject: [PATCH 5/5] fix: based on coderabbit --- .github/workflows/basic-checks.yml | 13 ++++++------- .github/workflows/build-release.yml | 18 +++++++++--------- .github/workflows/integration-tests.yml | 6 +++--- .github/workflows/on-workflow-end.yaml | 2 +- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.github/workflows/basic-checks.yml b/.github/workflows/basic-checks.yml index 16dc3ad9..8546fd8e 100644 --- a/.github/workflows/basic-checks.yml +++ b/.github/workflows/basic-checks.yml @@ -15,10 +15,10 @@ jobs: name: golangci-lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.22.6" + go-version: ^1.22 - uses: technote-space/get-diff-action@v6.1.2 id: git_diff with: @@ -32,11 +32,10 @@ jobs: unit-tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-go@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.22.6" + go-version: ^1.22 - name: Run unit tests run: go test -v ./... diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index cb107e9b..b20d47fa 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -11,11 +11,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.22.6" + go-version: ^1.22 - name: Check lint run: go fmt ./... @@ -29,11 +29,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.22.6" + go-version: ^1.22 - name: Run Integration Tests run: cd tests && go test -v ./... @@ -49,11 +49,11 @@ jobs: goarch: [amd64, arm64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.22.6" + go-version: ^1.22 - name: Read enabled flags run: | diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index a6297215..2da4ad8e 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -18,11 +18,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.22.6" + go-version: ^1.22 - name: Run Integration Tests run: cd tests && go test -v ./... diff --git a/.github/workflows/on-workflow-end.yaml b/.github/workflows/on-workflow-end.yaml index 8e33b778..698a5fc7 100644 --- a/.github/workflows/on-workflow-end.yaml +++ b/.github/workflows/on-workflow-end.yaml @@ -10,7 +10,7 @@ jobs: notify-slack: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Get Slack member IDs id: get-slack-id