package envtest import ( "context" "flag" "fmt" "os" "path" "path/filepath" "strconv" "sync" "testing" "time" "github.com/cenkalti/backoff" "github.com/stretchr/testify/require" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cosmosfaucet" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/env" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/errors" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/gocmd" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/httpstatuschecker" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/xurl" ) const ( envDoNotTrack = "DO_NOT_TRACK" ) var ( // IgniteApp hold the location of the ignite binary used in the integration // tests. The binary is compiled the first time the env.New() function is // invoked. IgniteApp = path.Join(os.TempDir(), "ignite-tests", "ignite") IsCI, _ = strconv.ParseBool(os.Getenv("CI")) compileBinaryOnce sync.Once ) // Env provides an isolated testing environment and what's needed to // make it possible. type Env struct { t *testing.T ctx context.Context } // New creates a new testing environment. func New(t *testing.T) Env { t.Helper() ctx, cancel := context.WithCancel(t.Context()) e := Env{ t: t, ctx: ctx, } // To avoid conflicts with the default config folder located in $HOME, we // set an other one thanks to env var. cfgDir := path.Join(t.TempDir(), ".ignite") env.SetConfigDir(cfgDir) enableDoNotTrackEnv(t) t.Cleanup(cancel) compileBinaryOnce.Do(func() { compileBinary(ctx) }) return e } func compileBinary(ctx context.Context) { wd, err := os.Getwd() if err != nil { panic(fmt.Sprintf("unable to get working dir: %v", err)) } pkgs, err := gocmd.List(ctx, wd, []string{"-m", "-f={{.Dir}}", "git.cw.tr/mukan-network/mukan-ignite"}) if err != nil { panic(fmt.Sprintf("unable to list ignite cli package: %v", err)) } if len(pkgs) != 1 { panic(fmt.Sprintf("expected only one package, got %d", len(pkgs))) } appPath := pkgs[0] var ( output, binary = filepath.Split(IgniteApp) path = path.Join(appPath, "ignite", "cmd", "ignite") ) err = gocmd.BuildPath(ctx, output, binary, path, nil) if err != nil { panic(fmt.Sprintf("error while building binary: %v", err)) } } func (e Env) T() *testing.T { return e.t } // SetCleanup registers a function to be called when the test (or subtest) and all its // subtests complete. func (e Env) SetCleanup(f func()) { e.t.Cleanup(f) } // Ctx returns parent context for the test suite to use for cancelations. func (e Env) Ctx() context.Context { return e.ctx } // IsAppServed checks that app is served properly and servers are started to listening before ctx canceled. func (e Env) IsAppServed(ctx context.Context, apiAddr string) error { checkAlive := func() error { addr, err := xurl.HTTP(apiAddr) if err != nil { return err } ok, err := httpstatuschecker.Check(ctx, fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/node_info", addr)) if err == nil && !ok { err = errors.New("waiting for app") } if HasTestVerboseFlag() { fmt.Printf("IsAppServed at %s: %v\n", addr, err) } return err } return backoff.Retry(checkAlive, backoff.WithContext(backoff.NewConstantBackOff(time.Second), ctx)) } // IsFaucetServed checks that faucet of the app is served properly. func (e Env) IsFaucetServed(ctx context.Context, faucetClient cosmosfaucet.HTTPClient) error { checkAlive := func() error { _, err := faucetClient.FaucetInfo(ctx) return err } return backoff.Retry(checkAlive, backoff.WithContext(backoff.NewConstantBackOff(time.Second), ctx)) } // TmpDir creates a new temporary directory. func (e Env) TmpDir() (path string) { return e.t.TempDir() } // Home returns user's home dir. func (e Env) Home() string { home, err := os.UserHomeDir() require.NoError(e.t, err) return home } // AppHome returns app's root home/data dir path. func (e Env) AppHome(name string) string { return filepath.Join(e.Home(), fmt.Sprintf(".%s", name)) } // Must fails the immediately if not ok. // t.Fail() needs to be called for the failing tests before running Must(). func (e Env) Must(ok bool) { if !ok { e.t.FailNow() } } func (e Env) HasFailed() bool { return e.t.Failed() } func (e Env) RequireExpectations() { e.Must(e.HasFailed()) } // enableDoNotTrackEnv set true the DO_NOT_TRACK env var. func enableDoNotTrackEnv(t *testing.T) { t.Helper() t.Setenv(envDoNotTrack, "true") } func HasTestVerboseFlag() bool { return flag.Lookup("test.v").Value.String() == "true" }