-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Expand e2e tests to cover the true end-to-end flow (#267)
- Loading branch information
Showing
19 changed files
with
3,016 additions
and
915 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package e2e | ||
|
||
import ( | ||
"context" | ||
"crypto/ecdsa" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"syscall" | ||
|
||
bftclient "github.com/cometbft/cometbft/rpc/client/http" | ||
opbindings "github.com/ethereum-optimism/optimism/op-bindings/bindings" | ||
opgenesis "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" | ||
"github.com/ethereum-optimism/optimism/op-node/bindings" | ||
"github.com/ethereum-optimism/optimism/op-node/rollup" | ||
"github.com/polymerdao/monomer/environment" | ||
) | ||
|
||
type StackConfig struct { | ||
Ctx context.Context | ||
Users []*ecdsa.PrivateKey | ||
L1Client *L1Client | ||
L1Deployments *opgenesis.L1Deployments | ||
OptimismPortal *bindings.OptimismPortal | ||
L1StandardBridge *opbindings.L1StandardBridge | ||
L2OutputOracleCaller *bindings.L2OutputOracleCaller | ||
L2Client *bftclient.HTTP | ||
MonomerClient *MonomerClient | ||
RollupConfig *rollup.Config | ||
WaitL1 func(numBlocks int) error | ||
WaitL2 func(numBlocks int) error | ||
} | ||
|
||
func Run( | ||
ctx context.Context, | ||
env *environment.Env, | ||
outDir string, | ||
) error { | ||
monomerPath, err := filepath.Abs("..") | ||
if err != nil { | ||
return fmt.Errorf("absolute path to local monomer directory: %v", err) | ||
} | ||
const appName = "e2eapp" | ||
appDirPath := filepath.Join(outDir, appName) | ||
//nolint:gosec // We aren't worried about tainted cmd args. | ||
monogenCmd := setupCmd(exec.CommandContext(ctx, | ||
filepath.Join("..", "scripts", "go-wrapper.sh"), | ||
"run", filepath.Join("..", "cmd", "monogen"), | ||
"--app-dir-path", appDirPath, | ||
"--gomod-path", "github.com/e2e/"+appName, | ||
"--address-prefix", "e2e", | ||
"--monomer-path", monomerPath, | ||
)) | ||
if err := monogenCmd.Run(); err != nil { | ||
return fmt.Errorf("run monogen: %v", err) | ||
} | ||
|
||
setupHelperCmd := setupCmd(exec.CommandContext(ctx, filepath.Join(appDirPath, "setup-helper.sh"))) //nolint:gosec | ||
setupHelperCmd.Dir = appDirPath | ||
// Add the "GOFLAGS='-gcflags=all=-N -l'" environment variable to disable optimizations and make debugging easier. | ||
setupHelperCmd.Env = append(os.Environ(), "e2eapp_HOME="+outDir) | ||
if err := setupHelperCmd.Run(); err != nil { | ||
return fmt.Errorf("run setup helper: %v", err) | ||
} | ||
|
||
//nolint:gosec // We aren't worried about tainted cmd args. | ||
appCmd := setupCmd(exec.CommandContext(ctx, | ||
filepath.Join(appDirPath, appName+"d"), | ||
"monomer", | ||
"start", | ||
"--minimum-gas-prices", "0.001wei", | ||
"--monomer.dev-start", | ||
)) | ||
appCmd.Dir = appDirPath | ||
appCmd.Env = append(os.Environ(), "e2eapp_HOME="+outDir) | ||
if err := appCmd.Start(); err != nil { | ||
return fmt.Errorf("run app: %v", err) | ||
} | ||
env.DeferErr("wait for app", func() error { | ||
err := appCmd.Wait() | ||
if errors.Is(err, context.Canceled) { | ||
return nil | ||
} | ||
return err | ||
}) | ||
|
||
return nil | ||
} | ||
|
||
func setupCmd(cmd *exec.Cmd) *exec.Cmd { | ||
cmd.Cancel = func() error { | ||
return cmd.Process.Signal(syscall.SIGTERM) | ||
} | ||
cmd.Stdout = os.Stdout | ||
cmd.Stderr = os.Stderr | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package e2e_test | ||
|
||
import ( | ||
"context" | ||
"crypto/ecdsa" | ||
"errors" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
"time" | ||
|
||
bftclient "github.com/cometbft/cometbft/rpc/client/http" | ||
opbindings "github.com/ethereum-optimism/optimism/op-bindings/bindings" | ||
"github.com/ethereum-optimism/optimism/op-node/bindings" | ||
"github.com/ethereum-optimism/optimism/op-node/rollup" | ||
"github.com/ethereum/go-ethereum/rpc" | ||
"github.com/polymerdao/monomer/e2e" | ||
"github.com/polymerdao/monomer/e2e/url" | ||
"github.com/polymerdao/monomer/environment" | ||
"github.com/polymerdao/monomer/opdevnet" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
var e2eTests = []struct { | ||
name string | ||
run func(t *testing.T, stack *e2e.StackConfig) | ||
}{ | ||
{ | ||
name: "ETH L1 Deposits and L2 Withdrawals", | ||
run: ethRollupFlow, | ||
}, | ||
{ | ||
name: "ERC-20 L1 Deposits", | ||
run: erc20RollupFlow, | ||
}, | ||
{ | ||
name: "AttributesTX", | ||
run: containsAttributesTx, | ||
}, | ||
{ | ||
name: "No Rollbacks", | ||
run: checkForRollbacks, | ||
}, | ||
} | ||
|
||
func TestE2E(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip("skipping e2e tests in short mode") | ||
} | ||
|
||
env := environment.New() | ||
defer func() { | ||
require.NoError(t, env.Close()) | ||
}() | ||
artifactsDir, err := filepath.Abs("artifacts") | ||
require.NoError(t, err) | ||
|
||
if err := os.Mkdir(artifactsDir, 0o755); !errors.Is(err, os.ErrExist) { | ||
require.NoError(t, err) | ||
} | ||
|
||
stdoutFile, err := os.OpenFile(filepath.Join(artifactsDir, "stdout"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o666) | ||
require.NoError(t, err) | ||
env.DeferErr("close stdout file", stdoutFile.Close) | ||
stdout := os.Stdout | ||
os.Stdout = stdoutFile | ||
defer func() { | ||
os.Stdout = stdout | ||
}() | ||
stderrFile, err := os.OpenFile(filepath.Join(artifactsDir, "stderr"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o666) | ||
require.NoError(t, err) | ||
env.DeferErr("close stderr file", stderrFile.Close) | ||
stderr := os.Stderr | ||
os.Stderr = stderrFile | ||
defer func() { | ||
os.Stderr = stderr | ||
}() | ||
|
||
ctx, cancel := context.WithCancel(context.Background()) | ||
defer cancel() | ||
require.NoError(t, e2e.Run(ctx, env, t.TempDir())) | ||
|
||
for _, test := range e2eTests { | ||
t.Run(test.name, func(t *testing.T) { | ||
test.run(t, newStackConfig(t)) | ||
}) | ||
} | ||
} | ||
|
||
func newStackConfig(t *testing.T) *e2e.StackConfig { | ||
secrets, err := opdevnet.DefaultMnemonicConfig.Secrets() | ||
require.NoError(t, err) | ||
|
||
engineURL, err := url.ParseString("ws://127.0.0.1:9000") | ||
require.NoError(t, err) | ||
require.True(t, engineURL.IsReachable(context.Background())) | ||
monomerRPCClient, err := rpc.Dial(engineURL.String()) | ||
require.NoError(t, err) | ||
monomerClient := e2e.NewMonomerClient(monomerRPCClient) | ||
|
||
bftClient, err := bftclient.New("tcp://127.0.0.1:26657", "/websocket") | ||
require.NoError(t, err) | ||
require.NoError(t, bftClient.Start()) | ||
|
||
l1URL, err := url.ParseString("ws://127.0.0.1:9001") | ||
require.NoError(t, err) | ||
require.True(t, l1URL.IsReachable(context.Background())) | ||
l1RPCClient, err := rpc.Dial(l1URL.String()) | ||
require.NoError(t, err) | ||
l1Client := e2e.NewL1Client(l1RPCClient) | ||
|
||
l1Deployments, err := opdevnet.DefaultL1Deployments() | ||
require.NoError(t, err) | ||
|
||
opPortal, err := bindings.NewOptimismPortal(l1Deployments.OptimismPortalProxy, l1Client) | ||
require.NoError(t, err) | ||
l1StandardBridge, err := opbindings.NewL1StandardBridge(l1Deployments.L1StandardBridgeProxy, l1Client) | ||
require.NoError(t, err) | ||
l2OutputOracleCaller, err := bindings.NewL2OutputOracleCaller(l1Deployments.L2OutputOracleProxy, l1Client) | ||
require.NoError(t, err) | ||
|
||
deployConfig, err := opdevnet.DefaultDeployConfig(l1Deployments) | ||
require.NoError(t, err) | ||
|
||
return &e2e.StackConfig{ | ||
Ctx: context.Background(), | ||
Users: []*ecdsa.PrivateKey{secrets.Alice, secrets.Bob}, | ||
L1Client: l1Client, | ||
L1Deployments: l1Deployments, | ||
OptimismPortal: opPortal, | ||
L1StandardBridge: l1StandardBridge, | ||
L2OutputOracleCaller: l2OutputOracleCaller, | ||
L2Client: bftClient, | ||
MonomerClient: monomerClient, | ||
RollupConfig: &rollup.Config{ | ||
SeqWindowSize: deployConfig.SequencerWindowSize, | ||
}, | ||
WaitL1: func(numBlocks int) error { | ||
time.Sleep(time.Second * time.Duration(deployConfig.L1BlockTime*uint64(numBlocks))) | ||
return nil | ||
}, | ||
WaitL2: func(numBlocks int) error { | ||
time.Sleep(time.Second * time.Duration(deployConfig.L2BlockTime*uint64(numBlocks))) | ||
return nil | ||
}, | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.