mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-11 23:18:07 -05:00
Compare commits
30 Commits
alpha
...
feat/integ
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9175e769b | ||
|
|
a1476ab8db | ||
|
|
8052866492 | ||
|
|
6bf7fb7fca | ||
|
|
420efdbd70 | ||
|
|
f4246128a1 | ||
|
|
8ae1c5c44a | ||
|
|
a2c7b2449c | ||
|
|
5c2d60c676 | ||
|
|
b2807ecbef | ||
|
|
5c73beb461 | ||
|
|
906631e7d8 | ||
|
|
59df623b6a | ||
|
|
c1f02745e2 | ||
|
|
e66e2cc348 | ||
|
|
47b1fb7c09 | ||
|
|
d5cedb9876 | ||
|
|
3e5df55086 | ||
|
|
ed3486426b | ||
|
|
b78ec9a4a1 | ||
|
|
f60b4181e5 | ||
|
|
1060833f17 | ||
|
|
3de0f9c24f | ||
|
|
bc0d5a9696 | ||
|
|
1d70c0f36b | ||
|
|
a1099de5b2 | ||
|
|
aa352717f8 | ||
|
|
f26ab8b727 | ||
|
|
dd8b5ef0b5 | ||
|
|
4fd2abadd5 |
86
bridge/cmd/app/bridge_app.go
Normal file
86
bridge/cmd/app/bridge_app.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"scroll-tech/common/cmd"
|
||||
"scroll-tech/common/docker"
|
||||
"scroll-tech/common/utils"
|
||||
|
||||
bridgeConfig "scroll-tech/bridge/config"
|
||||
)
|
||||
|
||||
// BridgeApp bridge-test client manager.
|
||||
type BridgeApp struct {
|
||||
Config *bridgeConfig.Config
|
||||
|
||||
base *docker.App
|
||||
|
||||
originFile string
|
||||
bridgeFile string
|
||||
|
||||
name string
|
||||
args []string
|
||||
docker.AppAPI
|
||||
}
|
||||
|
||||
// NewBridgeApp return a new bridgeApp manager.
|
||||
func NewBridgeApp(base *docker.App, file string) *BridgeApp {
|
||||
bridgeFile := fmt.Sprintf("/tmp/%d_bridge-config.json", base.Timestamp)
|
||||
bridgeApp := &BridgeApp{
|
||||
base: base,
|
||||
name: "bridge-test",
|
||||
originFile: file,
|
||||
bridgeFile: bridgeFile,
|
||||
args: []string{"--log.debug", "--config", bridgeFile},
|
||||
}
|
||||
if err := bridgeApp.MockConfig(true); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bridgeApp
|
||||
}
|
||||
|
||||
// RunApp run bridge-test child process by multi parameters.
|
||||
func (b *BridgeApp) RunApp(t *testing.T, args ...string) {
|
||||
b.AppAPI = cmd.NewCmd("bridge-test", append(b.args, args...)...)
|
||||
b.AppAPI.RunApp(func() bool { return b.AppAPI.WaitResult(t, time.Second*20, "Start bridge successfully") })
|
||||
}
|
||||
|
||||
// Free stop and release bridge-test.
|
||||
func (b *BridgeApp) Free() {
|
||||
if !utils.IsNil(b.AppAPI) {
|
||||
b.AppAPI.WaitExit()
|
||||
}
|
||||
_ = os.Remove(b.bridgeFile)
|
||||
}
|
||||
|
||||
// MockConfig creates a new bridge config.
|
||||
func (b *BridgeApp) MockConfig(store bool) error {
|
||||
base := b.base
|
||||
// Load origin bridge config file.
|
||||
cfg, err := bridgeConfig.NewConfig(b.originFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.L1Config.Endpoint = base.L1gethImg.Endpoint()
|
||||
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1gethImg.Endpoint()
|
||||
cfg.L2Config.Endpoint = base.L2gethImg.Endpoint()
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2gethImg.Endpoint()
|
||||
cfg.DBConfig.DSN = base.DBImg.Endpoint()
|
||||
b.Config = cfg
|
||||
|
||||
if !store {
|
||||
return nil
|
||||
}
|
||||
// Store changed bridge config into a temp file.
|
||||
data, err := json.Marshal(b.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(b.bridgeFile, data, 0600)
|
||||
}
|
||||
@@ -27,10 +27,13 @@
|
||||
},
|
||||
"finalize_batch_interval_sec": 0,
|
||||
"message_sender_private_keys": [
|
||||
"1212121212121212121212121212121212121212121212121212121212121212"
|
||||
"1212121212121212121212121212121212121212121212121212121212121213"
|
||||
],
|
||||
"gas_oracle_sender_private_keys": [
|
||||
"1212121212121212121212121212121212121212121212121212121212121212"
|
||||
"1212121212121212121212121212121212121212121212121212121212121215"
|
||||
],
|
||||
"rollup_sender_private_keys": [
|
||||
"1212121212121212121212121212121212121212121212121212121212121214"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -61,13 +64,13 @@
|
||||
},
|
||||
"finalize_batch_interval_sec": 0,
|
||||
"message_sender_private_keys": [
|
||||
"1212121212121212121212121212121212121212121212121212121212121212"
|
||||
"1212121212121212121212121212121212121212121212121212121212121213"
|
||||
],
|
||||
"gas_oracle_sender_private_keys": [
|
||||
"1212121212121212121212121212121212121212121212121212121212121212"
|
||||
"1212121212121212121212121212121212121212121212121212121212121215"
|
||||
],
|
||||
"rollup_sender_private_keys": [
|
||||
"1212121212121212121212121212121212121212121212121212121212121212"
|
||||
"1212121212121212121212121212121212121212121212121212121212121214"
|
||||
]
|
||||
},
|
||||
"batch_proposer_config": {
|
||||
|
||||
@@ -3,8 +3,6 @@ package l1
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"scroll-tech/common/docker"
|
||||
|
||||
"scroll-tech/bridge/config"
|
||||
@@ -20,27 +18,16 @@ var (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
base = docker.NewDockerApp()
|
||||
var err error
|
||||
cfg, err = config.NewConfig("../config.json")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1gethImg.Endpoint()
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2gethImg.Endpoint()
|
||||
cfg.DBConfig = base.DBConfig
|
||||
|
||||
m.Run()
|
||||
|
||||
base.Free()
|
||||
}
|
||||
|
||||
func setupEnv(t *testing.T) {
|
||||
// Load config.
|
||||
var err error
|
||||
cfg, err = config.NewConfig("../config.json")
|
||||
assert.NoError(t, err)
|
||||
base.RunImages(t)
|
||||
|
||||
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1GethEndpoint()
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2GethEndpoint()
|
||||
cfg.DBConfig.DSN = base.DBEndpoint()
|
||||
}
|
||||
|
||||
func TestL1(t *testing.T) {
|
||||
setupEnv(t)
|
||||
|
||||
t.Run("testCreateNewL1Relayer", testCreateNewL1Relayer)
|
||||
t.Run("testStartWatcher", testStartWatcher)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,10 @@ import (
|
||||
"scroll-tech/database"
|
||||
)
|
||||
|
||||
// testCreateNewRelayer test create new relayer instance and stop
|
||||
func testCreateNewL1Relayer(t *testing.T) {
|
||||
// TestCreateNewL1Relayer test create new relayer instance and stop
|
||||
func TestCreateNewL1Relayer(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -15,9 +15,10 @@ import (
|
||||
geth_metrics "github.com/scroll-tech/go-ethereum/metrics"
|
||||
"github.com/scroll-tech/go-ethereum/rpc"
|
||||
|
||||
"scroll-tech/database"
|
||||
|
||||
"scroll-tech/common/metrics"
|
||||
"scroll-tech/common/types"
|
||||
"scroll-tech/database"
|
||||
|
||||
cutil "scroll-tech/common/utils"
|
||||
|
||||
|
||||
@@ -3,27 +3,30 @@ package l1
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/ethclient"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"scroll-tech/database"
|
||||
"scroll-tech/database/migrate"
|
||||
)
|
||||
|
||||
func testStartWatcher(t *testing.T) {
|
||||
func TestStartWatcher(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, migrate.ResetDB(db.GetDB().DB))
|
||||
defer db.Close()
|
||||
|
||||
client, err := ethclient.Dial(base.L1GethEndpoint())
|
||||
client, err := base.L1Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
l1Cfg := cfg.L1Config
|
||||
|
||||
watcher := NewWatcher(context.Background(), client, l1Cfg.StartHeight, l1Cfg.Confirmations, l1Cfg.L1MessengerAddress, l1Cfg.L1MessageQueueAddress, l1Cfg.RelayerConfig.RollupContractAddress, db)
|
||||
watcher.Start()
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
defer watcher.Stop()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,12 @@ import (
|
||||
"scroll-tech/common/types"
|
||||
)
|
||||
|
||||
func testBatchProposerProposeBatch(t *testing.T) {
|
||||
func TestBatchProposerProposeBatch(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
@@ -31,6 +36,16 @@ func testBatchProposerProposeBatch(t *testing.T) {
|
||||
wc.Start()
|
||||
defer wc.Stop()
|
||||
|
||||
batch, err := db.GetLatestBatch()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create a new batch.
|
||||
batchData := types.NewBatchData(&types.BlockBatch{
|
||||
Index: 0,
|
||||
Hash: batch.Hash,
|
||||
StateRoot: batch.StateRoot,
|
||||
}, []*types.WrappedBlock{wrappedBlock1}, nil)
|
||||
|
||||
relayer, err := NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -48,12 +63,17 @@ func testBatchProposerProposeBatch(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(infos))
|
||||
|
||||
exist, err := db.BatchRecordExist(batchData1.Hash().Hex())
|
||||
exist, err := db.BatchRecordExist(batchData.Hash().Hex())
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, exist)
|
||||
}
|
||||
|
||||
func testBatchProposerGracefulRestart(t *testing.T) {
|
||||
func TestBatchProposerGracefulRestart(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
package l2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/ethclient"
|
||||
"github.com/scroll-tech/go-ethereum/log"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"scroll-tech/common/testdata"
|
||||
|
||||
"scroll-tech/common/docker"
|
||||
"scroll-tech/common/types"
|
||||
@@ -21,9 +17,6 @@ var (
|
||||
|
||||
base *docker.App
|
||||
|
||||
// l2geth client
|
||||
l2Cli *ethclient.Client
|
||||
|
||||
// block trace
|
||||
wrappedBlock1 *types.WrappedBlock
|
||||
wrappedBlock2 *types.WrappedBlock
|
||||
@@ -33,84 +26,47 @@ var (
|
||||
batchData2 *types.BatchData
|
||||
)
|
||||
|
||||
func setupEnv(t *testing.T) (err error) {
|
||||
// Load config.
|
||||
cfg, err = config.NewConfig("../config.json")
|
||||
assert.NoError(t, err)
|
||||
|
||||
base.RunImages(t)
|
||||
|
||||
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1GethEndpoint()
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2GethEndpoint()
|
||||
cfg.DBConfig.DSN = base.DBEndpoint()
|
||||
|
||||
// Create l2geth client.
|
||||
l2Cli, err = base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
templateBlockTrace1, err := os.ReadFile("../../common/testdata/blockTrace_02.json")
|
||||
if err != nil {
|
||||
return err
|
||||
func init() {
|
||||
trace02 := testdata.GetTrace("../../common/testdata/blockTrace_02.json")
|
||||
wrappedBlock1 = &types.WrappedBlock{
|
||||
Header: trace02.Header,
|
||||
Transactions: trace02.Transactions,
|
||||
WithdrawTrieRoot: trace02.WithdrawTrieRoot,
|
||||
}
|
||||
// unmarshal blockTrace
|
||||
wrappedBlock1 = &types.WrappedBlock{}
|
||||
if err = json.Unmarshal(templateBlockTrace1, wrappedBlock1); err != nil {
|
||||
return err
|
||||
}
|
||||
parentBatch1 := &types.BlockBatch{
|
||||
batchData1 = types.NewBatchData(&types.BlockBatch{
|
||||
Index: 0,
|
||||
Hash: "0x0cc6b102c2924402c14b2e3a19baccc316252bfdc44d9ec62e942d34e39ec729",
|
||||
StateRoot: "0x2579122e8f9ec1e862e7d415cef2fb495d7698a8e5f0dddc5651ba4236336e7d",
|
||||
}
|
||||
batchData1 = types.NewBatchData(parentBatch1, []*types.WrappedBlock{wrappedBlock1}, nil)
|
||||
}, []*types.WrappedBlock{wrappedBlock1}, nil)
|
||||
|
||||
templateBlockTrace2, err := os.ReadFile("../../common/testdata/blockTrace_03.json")
|
||||
if err != nil {
|
||||
return err
|
||||
trace03 := testdata.GetTrace("../../common/testdata/blockTrace_03.json")
|
||||
wrappedBlock2 = &types.WrappedBlock{
|
||||
Header: trace03.Header,
|
||||
Transactions: trace03.Transactions,
|
||||
WithdrawTrieRoot: trace03.WithdrawTrieRoot,
|
||||
}
|
||||
// unmarshal blockTrace
|
||||
wrappedBlock2 = &types.WrappedBlock{}
|
||||
if err = json.Unmarshal(templateBlockTrace2, wrappedBlock2); err != nil {
|
||||
return err
|
||||
}
|
||||
parentBatch2 := &types.BlockBatch{
|
||||
batchData2 = types.NewBatchData(&types.BlockBatch{
|
||||
Index: batchData1.Batch.BatchIndex,
|
||||
Hash: batchData1.Hash().Hex(),
|
||||
StateRoot: batchData1.Batch.NewStateRoot.String(),
|
||||
}
|
||||
batchData2 = types.NewBatchData(parentBatch2, []*types.WrappedBlock{wrappedBlock2}, nil)
|
||||
}, []*types.WrappedBlock{wrappedBlock2}, nil)
|
||||
|
||||
log.Info("batchHash", "batchhash1", batchData1.Hash().Hex(), "batchhash2", batchData2.Hash().Hex())
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
base = docker.NewDockerApp()
|
||||
|
||||
// Load config.
|
||||
var err error
|
||||
cfg, err = config.NewConfig("../config.json")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1gethImg.Endpoint()
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2gethImg.Endpoint()
|
||||
cfg.DBConfig = base.DBConfig
|
||||
|
||||
m.Run()
|
||||
|
||||
base.Free()
|
||||
}
|
||||
|
||||
func TestFunction(t *testing.T) {
|
||||
if err := setupEnv(t); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Run l2 watcher test cases.
|
||||
t.Run("TestCreateNewWatcherAndStop", testCreateNewWatcherAndStop)
|
||||
t.Run("TestMonitorBridgeContract", testMonitorBridgeContract)
|
||||
t.Run("TestFetchMultipleSentMessageInOneBlock", testFetchMultipleSentMessageInOneBlock)
|
||||
|
||||
// Run l2 relayer test cases.
|
||||
t.Run("TestCreateNewRelayer", testCreateNewRelayer)
|
||||
t.Run("TestL2RelayerProcessSaveEvents", testL2RelayerProcessSaveEvents)
|
||||
t.Run("TestL2RelayerProcessCommittedBatches", testL2RelayerProcessCommittedBatches)
|
||||
t.Run("TestL2RelayerSkipBatches", testL2RelayerSkipBatches)
|
||||
|
||||
// Run batch proposer test cases.
|
||||
t.Run("TestBatchProposerProposeBatch", testBatchProposerProposeBatch)
|
||||
t.Run("TestBatchProposerGracefulRestart", testBatchProposerGracefulRestart)
|
||||
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@ import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
"modernc.org/mathutil"
|
||||
|
||||
"scroll-tech/database"
|
||||
|
||||
"scroll-tech/common/metrics"
|
||||
"scroll-tech/common/types"
|
||||
"scroll-tech/database"
|
||||
|
||||
cutil "scroll-tech/common/utils"
|
||||
|
||||
|
||||
@@ -32,7 +32,12 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func testCreateNewRelayer(t *testing.T) {
|
||||
func TestCreateNewRelayer(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
@@ -46,7 +51,12 @@ func testCreateNewRelayer(t *testing.T) {
|
||||
relayer.Start()
|
||||
}
|
||||
|
||||
func testL2RelayerProcessSaveEvents(t *testing.T) {
|
||||
func TestL2RelayerProcessSaveEvents(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
@@ -96,7 +106,12 @@ func testL2RelayerProcessSaveEvents(t *testing.T) {
|
||||
assert.Equal(t, types.MsgSubmitted, msg.Status)
|
||||
}
|
||||
|
||||
func testL2RelayerProcessCommittedBatches(t *testing.T) {
|
||||
func TestL2RelayerProcessCommittedBatches(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
@@ -132,7 +147,12 @@ func testL2RelayerProcessCommittedBatches(t *testing.T) {
|
||||
assert.Equal(t, types.RollupFinalizing, status)
|
||||
}
|
||||
|
||||
func testL2RelayerSkipBatches(t *testing.T) {
|
||||
func TestL2RelayerSkipBatches(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -19,10 +19,11 @@ import (
|
||||
geth_metrics "github.com/scroll-tech/go-ethereum/metrics"
|
||||
"github.com/scroll-tech/go-ethereum/rpc"
|
||||
|
||||
"scroll-tech/database"
|
||||
|
||||
"scroll-tech/common/metrics"
|
||||
"scroll-tech/common/types"
|
||||
cutil "scroll-tech/common/utils"
|
||||
"scroll-tech/database"
|
||||
|
||||
bridge_abi "scroll-tech/bridge/abi"
|
||||
"scroll-tech/bridge/utils"
|
||||
|
||||
@@ -24,7 +24,12 @@ import (
|
||||
"scroll-tech/database/migrate"
|
||||
)
|
||||
|
||||
func testCreateNewWatcherAndStop(t *testing.T) {
|
||||
func TestCreateNewWatcherAndStop(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
l2db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
@@ -55,7 +60,12 @@ func testCreateNewWatcherAndStop(t *testing.T) {
|
||||
assert.GreaterOrEqual(t, blockNum, uint64(numTransactions))
|
||||
}
|
||||
|
||||
func testMonitorBridgeContract(t *testing.T) {
|
||||
func TestMonitorBridgeContract(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
@@ -123,7 +133,12 @@ func testMonitorBridgeContract(t *testing.T) {
|
||||
assert.Equal(t, 2, len(msgs))
|
||||
}
|
||||
|
||||
func testFetchMultipleSentMessageInOneBlock(t *testing.T) {
|
||||
func TestFetchMultipleSentMessageInOneBlock(t *testing.T) {
|
||||
// Start docker containers.
|
||||
base.RunImages(t)
|
||||
l2Cli, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create db handler and reset db.
|
||||
db, err := database.NewOrmFactory(cfg.DBConfig)
|
||||
assert.NoError(t, err)
|
||||
@@ -149,10 +164,6 @@ func testFetchMultipleSentMessageInOneBlock(t *testing.T) {
|
||||
var tx *geth_types.Transaction
|
||||
|
||||
for i := 0; i < numTransactions; i++ {
|
||||
addr := common.HexToAddress("0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63")
|
||||
nonce, nounceErr := l2Cli.PendingNonceAt(context.Background(), addr)
|
||||
assert.NoError(t, nounceErr)
|
||||
auth.Nonce = big.NewInt(int64(nonce))
|
||||
toAddress := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d")
|
||||
message := []byte("testbridgecontract")
|
||||
fee := big.NewInt(0)
|
||||
@@ -167,10 +178,6 @@ func testFetchMultipleSentMessageInOneBlock(t *testing.T) {
|
||||
}
|
||||
|
||||
// extra block mined
|
||||
addr := common.HexToAddress("0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63")
|
||||
nonce, nounceErr := l2Cli.PendingNonceAt(context.Background(), addr)
|
||||
assert.NoError(t, nounceErr)
|
||||
auth.Nonce = big.NewInt(int64(nonce))
|
||||
toAddress := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d")
|
||||
message := []byte("testbridgecontract")
|
||||
fee := big.NewInt(0)
|
||||
|
||||
@@ -50,7 +50,7 @@ func setupEnv(t *testing.T) {
|
||||
// Load default private key.
|
||||
privateKeys = []*ecdsa.PrivateKey{priv}
|
||||
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2GethEndpoint()
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2gethImg.Endpoint()
|
||||
}
|
||||
|
||||
func TestSender(t *testing.T) {
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"github.com/scroll-tech/go-ethereum/core/types"
|
||||
"github.com/scroll-tech/go-ethereum/crypto"
|
||||
"github.com/scroll-tech/go-ethereum/ethclient"
|
||||
"github.com/scroll-tech/go-ethereum/rpc"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"scroll-tech/bridge/cmd/app"
|
||||
"scroll-tech/bridge/config"
|
||||
"scroll-tech/bridge/mock_bridge"
|
||||
|
||||
@@ -26,7 +26,9 @@ var (
|
||||
|
||||
// private key
|
||||
privateKey *ecdsa.PrivateKey
|
||||
base *docker.App
|
||||
|
||||
bridgeApp *app.BridgeApp
|
||||
base *docker.App
|
||||
|
||||
// clients
|
||||
l1Client *ethclient.Client
|
||||
@@ -51,99 +53,32 @@ var (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
base = docker.NewDockerApp()
|
||||
bridgeApp = app.NewBridgeApp(base, "../config.json")
|
||||
// Load config.
|
||||
cfg = bridgeApp.Config
|
||||
|
||||
m.Run()
|
||||
|
||||
bridgeApp.Free()
|
||||
base.Free()
|
||||
}
|
||||
|
||||
func setupEnv(t *testing.T) {
|
||||
// Start l1geth l2geth and postgres docker containers.
|
||||
base.RunImages(t)
|
||||
|
||||
var err error
|
||||
privateKey, err = crypto.ToECDSA(common.FromHex("1212121212121212121212121212121212121212121212121212121212121212"))
|
||||
assert.NoError(t, err)
|
||||
messagePrivateKey, err := crypto.ToECDSA(common.FromHex("1212121212121212121212121212121212121212121212121212121212121213"))
|
||||
assert.NoError(t, err)
|
||||
rollupPrivateKey, err := crypto.ToECDSA(common.FromHex("1212121212121212121212121212121212121212121212121212121212121214"))
|
||||
assert.NoError(t, err)
|
||||
gasOraclePrivateKey, err := crypto.ToECDSA(common.FromHex("1212121212121212121212121212121212121212121212121212121212121215"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Load config.
|
||||
cfg, err = config.NewConfig("../config.json")
|
||||
assert.NoError(t, err)
|
||||
cfg.L1Config.Confirmations = rpc.LatestBlockNumber
|
||||
cfg.L1Config.RelayerConfig.MessageSenderPrivateKeys = []*ecdsa.PrivateKey{messagePrivateKey}
|
||||
cfg.L1Config.RelayerConfig.RollupSenderPrivateKeys = []*ecdsa.PrivateKey{rollupPrivateKey}
|
||||
cfg.L1Config.RelayerConfig.GasOracleSenderPrivateKeys = []*ecdsa.PrivateKey{gasOraclePrivateKey}
|
||||
cfg.L2Config.Confirmations = rpc.LatestBlockNumber
|
||||
cfg.L2Config.RelayerConfig.MessageSenderPrivateKeys = []*ecdsa.PrivateKey{messagePrivateKey}
|
||||
cfg.L2Config.RelayerConfig.RollupSenderPrivateKeys = []*ecdsa.PrivateKey{rollupPrivateKey}
|
||||
cfg.L2Config.RelayerConfig.GasOracleSenderPrivateKeys = []*ecdsa.PrivateKey{gasOraclePrivateKey}
|
||||
base.RunImages(t)
|
||||
|
||||
// Create l1geth container.
|
||||
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1GethEndpoint()
|
||||
cfg.L1Config.Endpoint = base.L1GethEndpoint()
|
||||
|
||||
// Create l2geth container.
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2GethEndpoint()
|
||||
cfg.L2Config.Endpoint = base.L2GethEndpoint()
|
||||
|
||||
// Create db container.
|
||||
cfg.DBConfig.DSN = base.DBEndpoint()
|
||||
|
||||
// Create l1geth and l2geth client.
|
||||
l1Client, err = ethclient.Dial(cfg.L1Config.Endpoint)
|
||||
l1Client, err = base.L1Client()
|
||||
assert.NoError(t, err)
|
||||
l2Client, err = ethclient.Dial(cfg.L2Config.Endpoint)
|
||||
l2Client, err = base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create l1 and l2 auth
|
||||
l1Auth = prepareAuth(t, l1Client, privateKey)
|
||||
l2Auth = prepareAuth(t, l2Client, privateKey)
|
||||
|
||||
// send some balance to message and rollup sender
|
||||
transferEther(t, l1Auth, l1Client, messagePrivateKey)
|
||||
transferEther(t, l1Auth, l1Client, rollupPrivateKey)
|
||||
transferEther(t, l1Auth, l1Client, gasOraclePrivateKey)
|
||||
transferEther(t, l2Auth, l2Client, messagePrivateKey)
|
||||
transferEther(t, l2Auth, l2Client, rollupPrivateKey)
|
||||
transferEther(t, l2Auth, l2Client, gasOraclePrivateKey)
|
||||
}
|
||||
|
||||
func transferEther(t *testing.T, auth *bind.TransactOpts, client *ethclient.Client, privateKey *ecdsa.PrivateKey) {
|
||||
targetAddress := crypto.PubkeyToAddress(privateKey.PublicKey)
|
||||
|
||||
gasPrice, err := client.SuggestGasPrice(context.Background())
|
||||
assert.NoError(t, err)
|
||||
gasPrice.Mul(gasPrice, big.NewInt(2))
|
||||
|
||||
// Get pending nonce
|
||||
nonce, err := client.PendingNonceAt(context.Background(), auth.From)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 200 ether should be enough
|
||||
value, ok := big.NewInt(0).SetString("0xad78ebc5ac6200000", 0)
|
||||
assert.Equal(t, ok, true)
|
||||
|
||||
tx := types.NewTx(&types.LegacyTx{
|
||||
Nonce: nonce,
|
||||
To: &targetAddress,
|
||||
Value: value,
|
||||
Gas: 500000,
|
||||
GasPrice: gasPrice,
|
||||
})
|
||||
signedTx, err := auth.Signer(auth.From, tx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = client.SendTransaction(context.Background(), signedTx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
receipt, err := bind.WaitMined(context.Background(), client, signedTx)
|
||||
assert.NoError(t, err)
|
||||
if receipt.Status != types.ReceiptStatusSuccessful {
|
||||
t.Fatalf("Call failed")
|
||||
}
|
||||
l1Auth = prepareAuth(t, base.L1gethImg.ChainID(), privateKey)
|
||||
l2Auth = prepareAuth(t, base.L2gethImg.ChainID(), privateKey)
|
||||
}
|
||||
|
||||
func prepareContracts(t *testing.T) {
|
||||
@@ -181,9 +116,7 @@ func prepareContracts(t *testing.T) {
|
||||
cfg.L2Config.RelayerConfig.GasPriceOracleContractAddress = l2MessengerAddress
|
||||
}
|
||||
|
||||
func prepareAuth(t *testing.T, client *ethclient.Client, privateKey *ecdsa.PrivateKey) *bind.TransactOpts {
|
||||
chainID, err := client.ChainID(context.Background())
|
||||
assert.NoError(t, err)
|
||||
func prepareAuth(t *testing.T, chainID *big.Int, privateKey *ecdsa.PrivateKey) *bind.TransactOpts {
|
||||
auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID)
|
||||
assert.NoError(t, err)
|
||||
auth.Value = big.NewInt(0) // in wei
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
@@ -11,13 +11,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/modern-go/reflect2"
|
||||
"github.com/scroll-tech/go-ethereum/ethclient"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"scroll-tech/database"
|
||||
|
||||
"scroll-tech/common/cmd"
|
||||
"scroll-tech/common/utils"
|
||||
)
|
||||
|
||||
@@ -27,150 +25,154 @@ var (
|
||||
dbStartPort = 30000
|
||||
)
|
||||
|
||||
// AppAPI app interface.
|
||||
type AppAPI interface {
|
||||
WaitResult(t *testing.T, timeout time.Duration, keyword string) bool
|
||||
RunApp(waitResult func() bool)
|
||||
WaitExit()
|
||||
ExpectWithTimeout(t *testing.T, parallel bool, timeout time.Duration, keyword string)
|
||||
}
|
||||
|
||||
// App is collection struct of runtime docker images
|
||||
type App struct {
|
||||
l1gethImg ImgInstance
|
||||
l2gethImg ImgInstance
|
||||
L1gethImg GethImgInstance
|
||||
L2gethImg GethImgInstance
|
||||
DBImg ImgInstance
|
||||
|
||||
dbImg ImgInstance
|
||||
dbConfig *database.DBConfig
|
||||
dbClient *sql.DB
|
||||
DBConfig *database.DBConfig
|
||||
dbFile string
|
||||
|
||||
// common time stamp.
|
||||
timestamp int
|
||||
Timestamp int
|
||||
}
|
||||
|
||||
// NewDockerApp returns new instance of dokerApp struct
|
||||
func NewDockerApp() *App {
|
||||
timestamp := time.Now().Nanosecond()
|
||||
return &App{
|
||||
timestamp: timestamp,
|
||||
app := &App{
|
||||
Timestamp: timestamp,
|
||||
L1gethImg: newTestL1Docker(),
|
||||
L2gethImg: newTestL2Docker(),
|
||||
DBImg: newTestDBDocker("postgres"),
|
||||
dbFile: fmt.Sprintf("/tmp/%d_db-config.json", timestamp),
|
||||
}
|
||||
if err := app.mockDBConfig(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return app
|
||||
}
|
||||
|
||||
// RunImages runs all images togather
|
||||
func (b *App) RunImages(t *testing.T) {
|
||||
b.runDBImage(t)
|
||||
b.runL1Geth(t)
|
||||
b.runL2Geth(t)
|
||||
b.RunDBImage(t)
|
||||
b.RunL1Geth(t)
|
||||
b.RunL2Geth(t)
|
||||
}
|
||||
|
||||
func (b *App) runDBImage(t *testing.T) {
|
||||
if b.dbImg != nil {
|
||||
// RunDBImage starts postgres docker container.
|
||||
func (b *App) RunDBImage(t *testing.T) {
|
||||
if b.DBImg.IsRunning() {
|
||||
return
|
||||
}
|
||||
b.dbImg = newTestDBDocker(t, "postgres")
|
||||
if err := b.mockDBConfig(); err != nil {
|
||||
_ = b.dbImg.Stop()
|
||||
b.dbImg = nil
|
||||
_ = os.Remove(b.dbFile)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// RunDBApp runs DB app with command
|
||||
func (b *App) RunDBApp(t *testing.T, option, keyword string) {
|
||||
args := []string{option, "--config", b.dbFile}
|
||||
app := cmd.NewCmd("db_cli-test", args...)
|
||||
defer app.WaitExit()
|
||||
|
||||
// Wait expect result.
|
||||
app.ExpectWithTimeout(t, true, time.Second*3, keyword)
|
||||
app.RunApp(nil)
|
||||
assert.NoError(t, b.DBImg.Start())
|
||||
var isRun bool
|
||||
// try 5 times until the db is ready.
|
||||
utils.TryTimes(10, func() bool {
|
||||
db, _ := sqlx.Open("postgres", b.DBImg.Endpoint())
|
||||
isRun = db != nil && db.Ping() == nil
|
||||
return isRun
|
||||
})
|
||||
assert.Equal(t, true, isRun)
|
||||
}
|
||||
|
||||
// Free clear all running images
|
||||
func (b *App) Free() {
|
||||
if b.l1gethImg != nil {
|
||||
_ = b.l1gethImg.Stop()
|
||||
b.l1gethImg = nil
|
||||
if b.L1gethImg.IsRunning() {
|
||||
_ = b.L1gethImg.Stop()
|
||||
}
|
||||
if b.l2gethImg != nil {
|
||||
_ = b.l2gethImg.Stop()
|
||||
b.l2gethImg = nil
|
||||
if b.L2gethImg.IsRunning() {
|
||||
_ = b.L2gethImg.Stop()
|
||||
}
|
||||
if b.dbImg != nil {
|
||||
_ = b.dbImg.Stop()
|
||||
b.dbImg = nil
|
||||
if b.DBImg.IsRunning() {
|
||||
_ = b.DBImg.Stop()
|
||||
_ = os.Remove(b.dbFile)
|
||||
if !utils.IsNil(b.dbClient) {
|
||||
_ = b.dbClient.Close()
|
||||
b.dbClient = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// L1GethEndpoint returns l1gethimg endpoint
|
||||
func (b *App) L1GethEndpoint() string {
|
||||
if b.l1gethImg != nil {
|
||||
return b.l1gethImg.Endpoint()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// L2GethEndpoint returns l2gethimg endpoint
|
||||
func (b *App) L2GethEndpoint() string {
|
||||
if b.l2gethImg != nil {
|
||||
return b.l2gethImg.Endpoint()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// DBEndpoint returns the endpoint of the dbimg
|
||||
func (b *App) DBEndpoint() string {
|
||||
return b.dbImg.Endpoint()
|
||||
}
|
||||
|
||||
func (b *App) runL1Geth(t *testing.T) {
|
||||
if b.l1gethImg != nil {
|
||||
// RunL1Geth starts l1geth docker container.
|
||||
func (b *App) RunL1Geth(t *testing.T) {
|
||||
if b.L1gethImg.IsRunning() {
|
||||
return
|
||||
}
|
||||
b.l1gethImg = newTestL1Docker(t)
|
||||
assert.NoError(t, b.L1gethImg.Start())
|
||||
}
|
||||
|
||||
// L1Client returns a ethclient by dialing running l1geth
|
||||
func (b *App) L1Client() (*ethclient.Client, error) {
|
||||
if b.l1gethImg == nil || reflect2.IsNil(b.l1gethImg) {
|
||||
if utils.IsNil(b.L1gethImg) {
|
||||
return nil, fmt.Errorf("l1 geth is not running")
|
||||
}
|
||||
client, err := ethclient.Dial(b.l1gethImg.Endpoint())
|
||||
client, err := ethclient.Dial(b.L1gethImg.Endpoint())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (b *App) runL2Geth(t *testing.T) {
|
||||
if b.l2gethImg != nil {
|
||||
// RunL2Geth starts l2geth docker container.
|
||||
func (b *App) RunL2Geth(t *testing.T) {
|
||||
if b.L2gethImg.IsRunning() {
|
||||
return
|
||||
}
|
||||
b.l2gethImg = newTestL2Docker(t)
|
||||
assert.NoError(t, b.L2gethImg.Start())
|
||||
}
|
||||
|
||||
// L2Client returns a ethclient by dialing running l2geth
|
||||
func (b *App) L2Client() (*ethclient.Client, error) {
|
||||
if b.l2gethImg == nil || reflect2.IsNil(b.l2gethImg) {
|
||||
if utils.IsNil(b.L2gethImg) {
|
||||
return nil, fmt.Errorf("l2 geth is not running")
|
||||
}
|
||||
client, err := ethclient.Dial(b.l2gethImg.Endpoint())
|
||||
client, err := ethclient.Dial(b.L2gethImg.Endpoint())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// DBClient create and return *sql.DB instance.
|
||||
func (b App) DBClient(t *testing.T) *sql.DB {
|
||||
if !utils.IsNil(b.dbClient) {
|
||||
return b.dbClient
|
||||
}
|
||||
var (
|
||||
cfg = b.DBConfig
|
||||
err error
|
||||
)
|
||||
b.dbClient, err = sql.Open(cfg.DriverName, cfg.DSN)
|
||||
assert.NoError(t, err)
|
||||
b.dbClient.SetMaxOpenConns(cfg.MaxOpenNum)
|
||||
b.dbClient.SetMaxIdleConns(cfg.MaxIdleNum)
|
||||
assert.NoError(t, b.dbClient.Ping())
|
||||
return b.dbClient
|
||||
}
|
||||
|
||||
func (b *App) mockDBConfig() error {
|
||||
if b.dbConfig == nil {
|
||||
|
||||
b.dbConfig = &database.DBConfig{
|
||||
DSN: "",
|
||||
DriverName: "postgres",
|
||||
MaxOpenNum: 200,
|
||||
MaxIdleNum: 20,
|
||||
}
|
||||
b.DBConfig = &database.DBConfig{
|
||||
DSN: "",
|
||||
DriverName: "postgres",
|
||||
MaxOpenNum: 200,
|
||||
MaxIdleNum: 20,
|
||||
}
|
||||
|
||||
if b.dbImg != nil {
|
||||
b.dbConfig.DSN = b.dbImg.Endpoint()
|
||||
if b.DBImg != nil {
|
||||
b.DBConfig.DSN = b.DBImg.Endpoint()
|
||||
}
|
||||
data, err := json.Marshal(b.dbConfig)
|
||||
data, err := json.Marshal(b.DBConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -178,57 +180,17 @@ func (b *App) mockDBConfig() error {
|
||||
return os.WriteFile(b.dbFile, data, 0644) //nolint:gosec
|
||||
}
|
||||
|
||||
func newTestL1Docker(t *testing.T) ImgInstance {
|
||||
func newTestL1Docker() GethImgInstance {
|
||||
id, _ := rand.Int(rand.Reader, big.NewInt(2000))
|
||||
imgL1geth := NewImgGeth("scroll_l1geth", "", "", 0, l1StartPort+int(id.Int64()))
|
||||
assert.NoError(t, imgL1geth.Start())
|
||||
|
||||
// try 3 times to get chainID until is ok.
|
||||
utils.TryTimes(10, func() bool {
|
||||
client, _ := ethclient.Dial(imgL1geth.Endpoint())
|
||||
if client != nil {
|
||||
if _, err := client.ChainID(context.Background()); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return imgL1geth
|
||||
return NewImgGeth("scroll_l1geth", "", "", 0, l1StartPort+int(id.Int64()))
|
||||
}
|
||||
|
||||
func newTestL2Docker(t *testing.T) ImgInstance {
|
||||
func newTestL2Docker() GethImgInstance {
|
||||
id, _ := rand.Int(rand.Reader, big.NewInt(2000))
|
||||
imgL2geth := NewImgGeth("scroll_l2geth", "", "", 0, l2StartPort+int(id.Int64()))
|
||||
assert.NoError(t, imgL2geth.Start())
|
||||
|
||||
// try 3 times to get chainID until is ok.
|
||||
utils.TryTimes(10, func() bool {
|
||||
client, _ := ethclient.Dial(imgL2geth.Endpoint())
|
||||
if client != nil {
|
||||
if _, err := client.ChainID(context.Background()); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return imgL2geth
|
||||
return NewImgGeth("scroll_l2geth", "", "", 0, l2StartPort+int(id.Int64()))
|
||||
}
|
||||
|
||||
func newTestDBDocker(t *testing.T, driverName string) ImgInstance {
|
||||
func newTestDBDocker(driverName string) ImgInstance {
|
||||
id, _ := rand.Int(rand.Reader, big.NewInt(2000))
|
||||
imgDB := NewImgDB(driverName, "123456", "test_db", dbStartPort+int(id.Int64()))
|
||||
assert.NoError(t, imgDB.Start())
|
||||
|
||||
// try 5 times until the db is ready.
|
||||
utils.TryTimes(10, func() bool {
|
||||
db, _ := sqlx.Open(driverName, imgDB.Endpoint())
|
||||
if db != nil {
|
||||
return db.Ping() == nil
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return imgDB
|
||||
return NewImgDB(driverName, "123456", "test_db", dbStartPort+int(id.Int64()))
|
||||
}
|
||||
|
||||
@@ -75,12 +75,14 @@ func (i *ImgDB) Stop() error {
|
||||
|
||||
// Endpoint return the dsn.
|
||||
func (i *ImgDB) Endpoint() string {
|
||||
if !i.running {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("postgres://postgres:%s@localhost:%d/%s?sslmode=disable", i.password, i.port, i.dbName)
|
||||
}
|
||||
|
||||
// IsRunning returns docker container's running status.
|
||||
func (i *ImgDB) IsRunning() bool {
|
||||
return i.running
|
||||
}
|
||||
|
||||
func (i *ImgDB) prepare() []string {
|
||||
cmd := []string{"docker", "run", "--name", i.name, "-p", fmt.Sprintf("%d:5432", i.port)}
|
||||
envs := []string{
|
||||
|
||||
@@ -3,11 +3,13 @@ package docker
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/scroll-tech/go-ethereum/ethclient"
|
||||
|
||||
"scroll-tech/common/cmd"
|
||||
"scroll-tech/common/utils"
|
||||
@@ -23,13 +25,14 @@ type ImgGeth struct {
|
||||
ipcPath string
|
||||
httpPort int
|
||||
wsPort int
|
||||
chainID *big.Int
|
||||
|
||||
running bool
|
||||
cmd *cmd.Cmd
|
||||
}
|
||||
|
||||
// NewImgGeth return geth img instance.
|
||||
func NewImgGeth(image, volume, ipc string, hPort, wPort int) ImgInstance {
|
||||
func NewImgGeth(image, volume, ipc string, hPort, wPort int) GethImgInstance {
|
||||
img := &ImgGeth{
|
||||
image: image,
|
||||
name: fmt.Sprintf("%s-%d", image, time.Now().Nanosecond()),
|
||||
@@ -53,14 +56,28 @@ func (i *ImgGeth) Start() error {
|
||||
_ = i.Stop()
|
||||
return fmt.Errorf("failed to start image: %s", i.image)
|
||||
}
|
||||
|
||||
// try 10 times to get chainID until is ok.
|
||||
utils.TryTimes(10, func() bool {
|
||||
client, _ := ethclient.Dial(i.Endpoint())
|
||||
if client != nil {
|
||||
var err error
|
||||
i.chainID, err = client.ChainID(context.Background())
|
||||
return err == nil && i.chainID != nil
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsRunning returns docker container's running status.
|
||||
func (i *ImgGeth) IsRunning() bool {
|
||||
return i.running
|
||||
}
|
||||
|
||||
// Endpoint return the connection endpoint.
|
||||
func (i *ImgGeth) Endpoint() string {
|
||||
if !i.running {
|
||||
return ""
|
||||
}
|
||||
switch true {
|
||||
case i.httpPort != 0:
|
||||
return fmt.Sprintf("http://127.0.0.1:%d", i.httpPort)
|
||||
@@ -71,6 +88,11 @@ func (i *ImgGeth) Endpoint() string {
|
||||
}
|
||||
}
|
||||
|
||||
// ChainID return chainID.
|
||||
func (i *ImgGeth) ChainID() *big.Int {
|
||||
return i.chainID
|
||||
}
|
||||
|
||||
func (i *ImgGeth) isOk() bool {
|
||||
keyword := "WebSocket enabled"
|
||||
okCh := make(chan struct{}, 1)
|
||||
|
||||
@@ -8,8 +8,6 @@ import (
|
||||
_ "github.com/lib/pq" //nolint:golint
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
_ "scroll-tech/database/cmd/app"
|
||||
|
||||
"scroll-tech/common/docker"
|
||||
)
|
||||
|
||||
@@ -25,50 +23,32 @@ func TestMain(m *testing.M) {
|
||||
base.Free()
|
||||
}
|
||||
|
||||
func TestStartProcess(t *testing.T) {
|
||||
base.RunImages(t)
|
||||
func TestDB(t *testing.T) {
|
||||
base.RunDBImage(t)
|
||||
|
||||
// migrate db.
|
||||
base.RunDBApp(t, "reset", "successful to reset")
|
||||
base.RunDBApp(t, "migrate", "current version:")
|
||||
db, err := sqlx.Open("postgres", base.DBImg.Endpoint())
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, db.Ping())
|
||||
}
|
||||
|
||||
func TestDocker(t *testing.T) {
|
||||
base.RunImages(t)
|
||||
t.Parallel()
|
||||
t.Run("testL1Geth", testL1Geth)
|
||||
t.Run("testL2Geth", testL2Geth)
|
||||
t.Run("testDB", testDB)
|
||||
}
|
||||
|
||||
func testL1Geth(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
func TestL1Geth(t *testing.T) {
|
||||
base.RunL1Geth(t)
|
||||
|
||||
client, err := base.L1Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
chainID, err := client.ChainID(ctx)
|
||||
chainID, err := client.ChainID(context.Background())
|
||||
assert.NoError(t, err)
|
||||
t.Logf("chainId: %s", chainID.String())
|
||||
}
|
||||
|
||||
func testL2Geth(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
func TestL2Geth(t *testing.T) {
|
||||
base.RunL2Geth(t)
|
||||
|
||||
client, err := base.L2Client()
|
||||
assert.NoError(t, err)
|
||||
|
||||
chainID, err := client.ChainID(ctx)
|
||||
chainID, err := client.ChainID(context.Background())
|
||||
assert.NoError(t, err)
|
||||
t.Logf("chainId: %s", chainID.String())
|
||||
}
|
||||
|
||||
func testDB(t *testing.T) {
|
||||
driverName := "postgres"
|
||||
|
||||
db, err := sqlx.Open(driverName, base.DBEndpoint())
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, db.Ping())
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
@@ -26,6 +27,13 @@ type ImgInstance interface {
|
||||
Start() error
|
||||
Stop() error
|
||||
Endpoint() string
|
||||
IsRunning() bool
|
||||
}
|
||||
|
||||
// GethImgInstance based on ImgInstance and add chainID interface.
|
||||
type GethImgInstance interface {
|
||||
ImgInstance
|
||||
ChainID() *big.Int
|
||||
}
|
||||
|
||||
// GetContainerID returns the ID of Container.
|
||||
|
||||
@@ -28,6 +28,15 @@
|
||||
"alloc": {
|
||||
"1c5a77d9fa7ef466951b2f01f724bca3a5820b63": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"9df85aB621C5F676D4b7fC5Ba6b8eD3E79b424e4": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"78d46B4eFB1cF32757277B7828E2765A3f8f9F14": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"60147F812CB308ee3aA7FF839e1f46a289e5FbF5": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"number": "0x0",
|
||||
|
||||
@@ -28,6 +28,15 @@
|
||||
"alloc": {
|
||||
"1c5a77d9fa7ef466951b2f01f724bca3a5820b63": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"9df85aB621C5F676D4b7fC5Ba6b8eD3E79b424e4": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"78d46B4eFB1cF32757277B7828E2765A3f8f9F14": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"60147F812CB308ee3aA7FF839e1f46a289e5FbF5": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"number": "0x0",
|
||||
|
||||
21
common/testdata/testdata.go
vendored
Normal file
21
common/testdata/testdata.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// GetTrace returns trace by file name.
|
||||
func GetTrace(file string) *types.BlockTrace {
|
||||
data, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
trace := &types.BlockTrace{}
|
||||
if err = json.Unmarshal(data, &trace); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return trace
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package utils
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/modern-go/reflect2"
|
||||
)
|
||||
|
||||
// TryTimes try run several times until the function return true.
|
||||
@@ -42,3 +44,8 @@ func Loop(ctx context.Context, period time.Duration, f func()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil Check if the interface is empty.
|
||||
func IsNil(i interface{}) bool {
|
||||
return i == nil || reflect2.IsNil(i)
|
||||
}
|
||||
|
||||
103
coordinator/cmd/app/mock_app.go
Normal file
103
coordinator/cmd/app/mock_app.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
coordinatorConfig "scroll-tech/coordinator/config"
|
||||
|
||||
"scroll-tech/common/cmd"
|
||||
"scroll-tech/common/docker"
|
||||
"scroll-tech/common/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
wsStartPort int64 = 40000
|
||||
)
|
||||
|
||||
// CoordinatorApp coordinator-test client manager.
|
||||
type CoordinatorApp struct {
|
||||
Config *coordinatorConfig.Config
|
||||
|
||||
base *docker.App
|
||||
|
||||
originFile string
|
||||
coordinatorFile string
|
||||
WSPort int64
|
||||
|
||||
args []string
|
||||
docker.AppAPI
|
||||
}
|
||||
|
||||
// NewCoordinatorApp return a new coordinatorApp manager.
|
||||
func NewCoordinatorApp(base *docker.App, file string) *CoordinatorApp {
|
||||
coordinatorFile := fmt.Sprintf("/tmp/%d_coordinator-config.json", base.Timestamp)
|
||||
port, _ := rand.Int(rand.Reader, big.NewInt(2000))
|
||||
wsPort := port.Int64() + wsStartPort
|
||||
coordinatorApp := &CoordinatorApp{
|
||||
base: base,
|
||||
originFile: file,
|
||||
coordinatorFile: coordinatorFile,
|
||||
WSPort: wsPort,
|
||||
args: []string{"--log.debug", "--config", coordinatorFile, "--ws", "--ws.port", strconv.Itoa(int(wsPort))},
|
||||
}
|
||||
if err := coordinatorApp.MockConfig(true); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return coordinatorApp
|
||||
}
|
||||
|
||||
// RunApp run coordinator-test child process by multi parameters.
|
||||
func (c *CoordinatorApp) RunApp(t *testing.T, args ...string) {
|
||||
c.AppAPI = cmd.NewCmd("coordinator-test", append(c.args, args...)...)
|
||||
c.AppAPI.RunApp(func() bool { return c.AppAPI.WaitResult(t, time.Second*20, "Start coordinator successfully") })
|
||||
}
|
||||
|
||||
// Free stop and release coordinator-test.
|
||||
func (c *CoordinatorApp) Free() {
|
||||
if !utils.IsNil(c.AppAPI) {
|
||||
c.AppAPI.WaitExit()
|
||||
}
|
||||
_ = os.Remove(c.coordinatorFile)
|
||||
}
|
||||
|
||||
// WSEndpoint returns ws endpoint.
|
||||
func (c *CoordinatorApp) WSEndpoint() string {
|
||||
return fmt.Sprintf("ws://localhost:%d", c.WSPort)
|
||||
}
|
||||
|
||||
// MockConfig creates a new coordinator config.
|
||||
func (c *CoordinatorApp) MockConfig(store bool) error {
|
||||
base := c.base
|
||||
cfg, err := coordinatorConfig.NewConfig(c.originFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Reset roller manager config for manager test cases.
|
||||
cfg.RollerManagerConfig = &coordinatorConfig.RollerManagerConfig{
|
||||
RollersPerSession: 1,
|
||||
Verifier: &coordinatorConfig.VerifierConfig{MockMode: true},
|
||||
CollectionTime: 1,
|
||||
TokenTimeToLive: 1,
|
||||
}
|
||||
cfg.DBConfig.DSN = base.DBImg.Endpoint()
|
||||
cfg.L2Config.Endpoint = base.L2gethImg.Endpoint()
|
||||
c.Config = cfg
|
||||
|
||||
if !store {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := json.Marshal(c.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(c.coordinatorFile, data, 0644)
|
||||
}
|
||||
@@ -18,10 +18,11 @@ import (
|
||||
geth_metrics "github.com/scroll-tech/go-ethereum/metrics"
|
||||
"github.com/scroll-tech/go-ethereum/rpc"
|
||||
|
||||
"scroll-tech/database"
|
||||
|
||||
"scroll-tech/common/message"
|
||||
"scroll-tech/common/metrics"
|
||||
"scroll-tech/common/types"
|
||||
"scroll-tech/database"
|
||||
|
||||
"scroll-tech/common/utils/workerpool"
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ func setEnv(t *testing.T) (err error) {
|
||||
base.RunImages(t)
|
||||
|
||||
// Create db container.
|
||||
cfg.DBConfig.DSN = base.DBEndpoint()
|
||||
cfg.DBConfig = base.DBConfig
|
||||
|
||||
templateBlockTrace, err := os.ReadFile("../common/testdata/blockTrace_02.json")
|
||||
if err != nil {
|
||||
|
||||
@@ -1,43 +1,29 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"testing"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"scroll-tech/common/docker"
|
||||
|
||||
"scroll-tech/database"
|
||||
)
|
||||
|
||||
var (
|
||||
base *docker.App
|
||||
pgDB *sqlx.DB
|
||||
pgDB *sql.DB
|
||||
)
|
||||
|
||||
func initEnv(t *testing.T) error {
|
||||
func initEnv(t *testing.T) {
|
||||
// Start db container.
|
||||
base.RunImages(t)
|
||||
|
||||
// Create db orm handler.
|
||||
factory, err := database.NewOrmFactory(&database.DBConfig{
|
||||
DriverName: "postgres",
|
||||
DSN: base.DBEndpoint(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pgDB = factory.GetDB()
|
||||
return nil
|
||||
base.RunDBImage(t)
|
||||
pgDB = base.DBClient(t)
|
||||
}
|
||||
|
||||
func TestMigrate(t *testing.T) {
|
||||
base = docker.NewDockerApp()
|
||||
if err := initEnv(t); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initEnv(t)
|
||||
|
||||
t.Run("testCurrent", testCurrent)
|
||||
t.Run("testStatus", testStatus)
|
||||
@@ -51,39 +37,39 @@ func TestMigrate(t *testing.T) {
|
||||
}
|
||||
|
||||
func testCurrent(t *testing.T) {
|
||||
cur, err := Current(pgDB.DB)
|
||||
cur, err := Current(pgDB)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, int(cur))
|
||||
}
|
||||
|
||||
func testStatus(t *testing.T) {
|
||||
status := Status(pgDB.DB)
|
||||
status := Status(pgDB)
|
||||
assert.NoError(t, status)
|
||||
}
|
||||
|
||||
func testResetDB(t *testing.T) {
|
||||
assert.NoError(t, ResetDB(pgDB.DB))
|
||||
cur, err := Current(pgDB.DB)
|
||||
assert.NoError(t, ResetDB(pgDB))
|
||||
cur, err := Current(pgDB)
|
||||
assert.NoError(t, err)
|
||||
// total number of tables.
|
||||
assert.Equal(t, 6, int(cur))
|
||||
}
|
||||
|
||||
func testMigrate(t *testing.T) {
|
||||
assert.NoError(t, Migrate(pgDB.DB))
|
||||
cur, err := Current(pgDB.DB)
|
||||
assert.NoError(t, Migrate(pgDB))
|
||||
cur, err := Current(pgDB)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, cur > 0)
|
||||
}
|
||||
|
||||
func testRollback(t *testing.T) {
|
||||
version, err := Current(pgDB.DB)
|
||||
version, err := Current(pgDB)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, version > 0)
|
||||
|
||||
assert.NoError(t, Rollback(pgDB.DB, nil))
|
||||
assert.NoError(t, Rollback(pgDB, nil))
|
||||
|
||||
cur, err := Current(pgDB.DB)
|
||||
cur, err := Current(pgDB)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, cur+1 == version)
|
||||
}
|
||||
|
||||
@@ -84,11 +84,16 @@ var (
|
||||
ormSession orm.SessionInfoOrm
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
base = docker.NewDockerApp()
|
||||
dbConfig = base.DBConfig
|
||||
m.Run()
|
||||
base.Free()
|
||||
}
|
||||
|
||||
func setupEnv(t *testing.T) error {
|
||||
// Init db config and start db container.
|
||||
dbConfig = &database.DBConfig{DriverName: "postgres"}
|
||||
base.RunImages(t)
|
||||
dbConfig.DSN = base.DBEndpoint()
|
||||
base.RunDBImage(t)
|
||||
|
||||
// Create db handler and reset db.
|
||||
factory, err := database.NewOrmFactory(dbConfig)
|
||||
@@ -97,7 +102,7 @@ func setupEnv(t *testing.T) error {
|
||||
assert.NoError(t, migrate.ResetDB(db.DB))
|
||||
|
||||
// Init several orm handles.
|
||||
ormBlock = orm.NewBlockTraceOrm(db)
|
||||
ormBlock = factory
|
||||
ormLayer1 = orm.NewL1MessageOrm(db)
|
||||
ormLayer2 = orm.NewL2MessageOrm(db)
|
||||
ormBatch = orm.NewBlockBatchOrm(db)
|
||||
@@ -155,10 +160,6 @@ func setupEnv(t *testing.T) error {
|
||||
|
||||
// TestOrmFactory run several test cases.
|
||||
func TestOrmFactory(t *testing.T) {
|
||||
base = docker.NewDockerApp()
|
||||
defer func() {
|
||||
base.Free()
|
||||
}()
|
||||
if err := setupEnv(t); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -175,10 +176,8 @@ func TestOrmFactory(t *testing.T) {
|
||||
}
|
||||
|
||||
func testOrmBlockTraces(t *testing.T) {
|
||||
// Create db handler and reset db.
|
||||
factory, err := database.NewOrmFactory(dbConfig)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, migrate.ResetDB(factory.GetDB().DB))
|
||||
// reset db.
|
||||
assert.NoError(t, migrate.ResetDB(base.DBClient(t)))
|
||||
|
||||
res, err := ormBlock.GetL2WrappedBlocks(map[string]interface{}{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
164
roller/cmd/app/mock_app.go
Normal file
164
roller/cmd/app/mock_app.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
rollerConfig "scroll-tech/roller/config"
|
||||
|
||||
"scroll-tech/common/cmd"
|
||||
"scroll-tech/common/docker"
|
||||
"scroll-tech/common/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
rollerIndex int
|
||||
)
|
||||
|
||||
func getIndex() int {
|
||||
defer func() { rollerIndex++ }()
|
||||
return rollerIndex
|
||||
}
|
||||
|
||||
// RollerApp roller-test client manager.
|
||||
type RollerApp struct {
|
||||
Config *rollerConfig.Config
|
||||
|
||||
base *docker.App
|
||||
|
||||
originFile string
|
||||
rollerFile string
|
||||
bboltDB string
|
||||
keystore string
|
||||
|
||||
index int
|
||||
name string
|
||||
args []string
|
||||
docker.AppAPI
|
||||
}
|
||||
|
||||
// NewRollerApp return a new rollerApp manager.
|
||||
func NewRollerApp(base *docker.App, file string, wsUrl string) *RollerApp {
|
||||
rollerFile := fmt.Sprintf("/tmp/%d_roller-config.json", base.Timestamp)
|
||||
rollerApp := &RollerApp{
|
||||
base: base,
|
||||
originFile: file,
|
||||
rollerFile: rollerFile,
|
||||
bboltDB: fmt.Sprintf("/tmp/%d_bbolt_db", base.Timestamp),
|
||||
index: getIndex(),
|
||||
name: "roller-test",
|
||||
args: []string{"--log.debug", "--config", rollerFile},
|
||||
}
|
||||
if err := rollerApp.MockConfig(true, wsUrl); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return rollerApp
|
||||
}
|
||||
|
||||
// RunApp run roller-test child process by multi parameters.
|
||||
func (r *RollerApp) RunApp(t *testing.T, args ...string) {
|
||||
r.AppAPI = cmd.NewCmd(r.name, append(r.args, args...)...)
|
||||
r.AppAPI.RunApp(func() bool { return r.AppAPI.WaitResult(t, time.Second*40, "roller start successfully") })
|
||||
}
|
||||
|
||||
// Free stop and release roller-test.
|
||||
func (r *RollerApp) Free() {
|
||||
if !utils.IsNil(r.AppAPI) {
|
||||
r.AppAPI.WaitExit()
|
||||
}
|
||||
_ = os.Remove(r.rollerFile)
|
||||
_ = os.Remove(r.Config.KeystorePath)
|
||||
_ = os.Remove(r.bboltDB)
|
||||
}
|
||||
|
||||
// MockConfig creates a new roller config.
|
||||
func (r *RollerApp) MockConfig(store bool, wsUrl string) error {
|
||||
cfg, err := rollerConfig.NewConfig(r.originFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.RollerName = fmt.Sprintf("%s_%d", r.name, r.index)
|
||||
cfg.KeystorePath = fmt.Sprintf("/tmp/%d_%s.json", r.base.Timestamp, cfg.RollerName)
|
||||
// Reuse l1geth's keystore file
|
||||
cfg.KeystorePassword = "scrolltest"
|
||||
cfg.DBPath = r.bboltDB
|
||||
// Create keystore file.
|
||||
_, err = utils.LoadOrCreateKey(cfg.KeystorePath, cfg.KeystorePassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.CoordinatorURL = wsUrl
|
||||
r.Config = cfg
|
||||
|
||||
if !store {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := json.Marshal(r.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(r.rollerFile, data, 0644)
|
||||
}
|
||||
|
||||
// RollerApps rollerApp list.
|
||||
type RollerApps []*RollerApp
|
||||
|
||||
// RunApps starts all the rollerApps.
|
||||
func (r RollerApps) RunApps(t *testing.T, args ...string) {
|
||||
var eg errgroup.Group
|
||||
for i := range r {
|
||||
i := i
|
||||
eg.Go(func() error {
|
||||
r[i].RunApp(t, args...)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
_ = eg.Wait()
|
||||
}
|
||||
|
||||
// MockConfigs creates all the rollerApps' configs.
|
||||
func (r RollerApps) MockConfigs(store bool, wsUrl string) error {
|
||||
var eg errgroup.Group
|
||||
for _, roller := range r {
|
||||
roller := roller
|
||||
eg.Go(func() error {
|
||||
return roller.MockConfig(store, wsUrl)
|
||||
})
|
||||
}
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
// Free releases rollerApps.
|
||||
func (r RollerApps) Free() {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(r))
|
||||
for i := range r {
|
||||
i := i
|
||||
go func() {
|
||||
r[i].Free()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// WaitExit wait rollerApps stopped.
|
||||
func (r RollerApps) WaitExit() {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(r))
|
||||
for i := range r {
|
||||
i := i
|
||||
go func() {
|
||||
r[i].WaitExit()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -7,6 +7,7 @@ require (
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
golang.org/x/sync v0.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -79,6 +79,8 @@ golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/crypto"
|
||||
"github.com/scroll-tech/go-ethereum/rpc"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"scroll-tech/database"
|
||||
_ "scroll-tech/database/cmd/app"
|
||||
|
||||
_ "scroll-tech/roller/cmd/app"
|
||||
rollerConfig "scroll-tech/roller/config"
|
||||
|
||||
_ "scroll-tech/bridge/cmd/app"
|
||||
bridgeConfig "scroll-tech/bridge/config"
|
||||
"scroll-tech/bridge/sender"
|
||||
|
||||
"scroll-tech/common/cmd"
|
||||
"scroll-tech/common/docker"
|
||||
|
||||
_ "scroll-tech/coordinator/cmd/app"
|
||||
coordinatorConfig "scroll-tech/coordinator/config"
|
||||
)
|
||||
|
||||
var (
|
||||
base *docker.App
|
||||
|
||||
timestamp int
|
||||
wsPort int64
|
||||
|
||||
bridgeFile string
|
||||
dbFile string
|
||||
coordinatorFile string
|
||||
|
||||
bboltDB string
|
||||
rollerFile string
|
||||
)
|
||||
|
||||
func setupEnv(t *testing.T) {
|
||||
// Start l1geth l2geth and postgres.
|
||||
base.RunImages(t)
|
||||
|
||||
// Create a random ws port.
|
||||
port, _ := rand.Int(rand.Reader, big.NewInt(2000))
|
||||
wsPort = port.Int64() + 22000
|
||||
timestamp = time.Now().Nanosecond()
|
||||
|
||||
// Load reset and store config into a random file.
|
||||
bridgeFile = mockBridgeConfig(t)
|
||||
dbFile = mockDatabaseConfig(t)
|
||||
coordinatorFile = mockCoordinatorConfig(t)
|
||||
rollerFile = mockRollerConfig(t)
|
||||
}
|
||||
|
||||
func free(t *testing.T) {
|
||||
base.Free()
|
||||
|
||||
// Delete temporary files.
|
||||
assert.NoError(t, os.Remove(bridgeFile))
|
||||
assert.NoError(t, os.Remove(dbFile))
|
||||
assert.NoError(t, os.Remove(coordinatorFile))
|
||||
assert.NoError(t, os.Remove(rollerFile))
|
||||
assert.NoError(t, os.Remove(bboltDB))
|
||||
}
|
||||
|
||||
type appAPI interface {
|
||||
WaitResult(t *testing.T, timeout time.Duration, keyword string) bool
|
||||
RunApp(waitResult func() bool)
|
||||
WaitExit()
|
||||
ExpectWithTimeout(t *testing.T, parallel bool, timeout time.Duration, keyword string)
|
||||
}
|
||||
|
||||
func runBridgeApp(t *testing.T, args ...string) appAPI {
|
||||
args = append(args, "--log.debug", "--config", bridgeFile)
|
||||
return cmd.NewCmd("bridge-test", args...)
|
||||
}
|
||||
|
||||
func runCoordinatorApp(t *testing.T, args ...string) appAPI {
|
||||
args = append(args, "--log.debug", "--config", coordinatorFile, "--ws", "--ws.port", strconv.Itoa(int(wsPort)))
|
||||
// start process
|
||||
return cmd.NewCmd("coordinator-test", args...)
|
||||
}
|
||||
|
||||
func runDBCliApp(t *testing.T, option, keyword string) {
|
||||
args := []string{option, "--config", dbFile}
|
||||
app := cmd.NewCmd("db_cli-test", args...)
|
||||
defer app.WaitExit()
|
||||
|
||||
// Wait expect result.
|
||||
app.ExpectWithTimeout(t, true, time.Second*3, keyword)
|
||||
app.RunApp(nil)
|
||||
}
|
||||
|
||||
func runRollerApp(t *testing.T, args ...string) appAPI {
|
||||
args = append(args, "--log.debug", "--config", rollerFile)
|
||||
return cmd.NewCmd("roller-test", args...)
|
||||
}
|
||||
|
||||
func runSender(t *testing.T, endpoint string) *sender.Sender {
|
||||
priv, err := crypto.HexToECDSA("1212121212121212121212121212121212121212121212121212121212121212")
|
||||
assert.NoError(t, err)
|
||||
newSender, err := sender.NewSender(context.Background(), &bridgeConfig.SenderConfig{
|
||||
Endpoint: endpoint,
|
||||
CheckPendingTime: 3,
|
||||
EscalateBlocks: 100,
|
||||
Confirmations: rpc.LatestBlockNumber,
|
||||
EscalateMultipleNum: 11,
|
||||
EscalateMultipleDen: 10,
|
||||
TxType: "LegacyTx",
|
||||
}, []*ecdsa.PrivateKey{priv})
|
||||
assert.NoError(t, err)
|
||||
return newSender
|
||||
}
|
||||
|
||||
func mockBridgeConfig(t *testing.T) string {
|
||||
// Load origin bridge config file.
|
||||
cfg, err := bridgeConfig.NewConfig("../../bridge/config.json")
|
||||
assert.NoError(t, err)
|
||||
|
||||
cfg.L1Config.Endpoint = base.L1GethEndpoint()
|
||||
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1GethEndpoint()
|
||||
cfg.L2Config.Endpoint = base.L2GethEndpoint()
|
||||
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2GethEndpoint()
|
||||
cfg.DBConfig.DSN = base.DBEndpoint()
|
||||
|
||||
// Store changed bridge config into a temp file.
|
||||
data, err := json.Marshal(cfg)
|
||||
assert.NoError(t, err)
|
||||
file := fmt.Sprintf("/tmp/%d_bridge-config.json", timestamp)
|
||||
err = os.WriteFile(file, data, 0644)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
func mockCoordinatorConfig(t *testing.T) string {
|
||||
cfg, err := coordinatorConfig.NewConfig("../../coordinator/config.json")
|
||||
assert.NoError(t, err)
|
||||
|
||||
cfg.RollerManagerConfig.Verifier.MockMode = true
|
||||
|
||||
cfg.DBConfig.DSN = base.DBEndpoint()
|
||||
|
||||
cfg.L2Config.Endpoint = base.L2GethEndpoint()
|
||||
|
||||
data, err := json.Marshal(cfg)
|
||||
assert.NoError(t, err)
|
||||
|
||||
file := fmt.Sprintf("/tmp/%d_coordinator-config.json", timestamp)
|
||||
err = os.WriteFile(file, data, 0644)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
func mockDatabaseConfig(t *testing.T) string {
|
||||
cfg, err := database.NewConfig("../../database/config.json")
|
||||
assert.NoError(t, err)
|
||||
cfg.DSN = base.DBEndpoint()
|
||||
|
||||
data, err := json.Marshal(cfg)
|
||||
assert.NoError(t, err)
|
||||
|
||||
file := fmt.Sprintf("/tmp/%d_db-config.json", timestamp)
|
||||
err = os.WriteFile(file, data, 0644)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
func mockRollerConfig(t *testing.T) string {
|
||||
cfg, err := rollerConfig.NewConfig("../../roller/config.json")
|
||||
assert.NoError(t, err)
|
||||
cfg.CoordinatorURL = fmt.Sprintf("ws://localhost:%d", wsPort)
|
||||
|
||||
// Reuse l1geth's keystore file
|
||||
cfg.KeystorePath = "../../common/docker/l1geth/genesis-keystore"
|
||||
cfg.KeystorePassword = "scrolltest"
|
||||
|
||||
bboltDB = fmt.Sprintf("/tmp/%d_bbolt_db", timestamp)
|
||||
cfg.DBPath = bboltDB
|
||||
assert.NoError(t, os.WriteFile(bboltDB, []byte{}, 0644))
|
||||
|
||||
data, err := json.Marshal(cfg)
|
||||
assert.NoError(t, err)
|
||||
|
||||
file := fmt.Sprintf("/tmp/%d_roller-config.json", timestamp)
|
||||
err = os.WriteFile(file, data, 0644)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return file
|
||||
}
|
||||
@@ -5,75 +5,83 @@ import (
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net/http"
|
||||
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"scroll-tech/common/docker"
|
||||
|
||||
_ "scroll-tech/database/cmd/app"
|
||||
"scroll-tech/database/migrate"
|
||||
|
||||
rApp "scroll-tech/roller/cmd/app"
|
||||
|
||||
cApp "scroll-tech/coordinator/cmd/app"
|
||||
|
||||
bApp "scroll-tech/bridge/cmd/app"
|
||||
)
|
||||
|
||||
func TestIntegration(t *testing.T) {
|
||||
var (
|
||||
base *docker.App
|
||||
bridge *bApp.BridgeApp
|
||||
coordinator *cApp.CoordinatorApp
|
||||
rollers rApp.RollerApps
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
base = docker.NewDockerApp()
|
||||
setupEnv(t)
|
||||
bridge = bApp.NewBridgeApp(base, "../../bridge/config.json")
|
||||
coordinator = cApp.NewCoordinatorApp(base, "../../coordinator/config.json")
|
||||
rollers = append(rollers, rApp.NewRollerApp(base, "../../roller/config.json", coordinator.WSEndpoint()))
|
||||
|
||||
// test db_cli migrate cmd.
|
||||
t.Run("testDBClientMigrate", func(t *testing.T) {
|
||||
runDBCliApp(t, "migrate", "current version:")
|
||||
})
|
||||
m.Run()
|
||||
|
||||
// test bridge service
|
||||
t.Run("testStartProcess", testStartProcess)
|
||||
|
||||
// test monitor metrics
|
||||
t.Run("testMonitorMetrics", testMonitorMetrics)
|
||||
|
||||
t.Cleanup(func() {
|
||||
free(t)
|
||||
})
|
||||
base.Free()
|
||||
bridge.Free()
|
||||
coordinator.Free()
|
||||
rollers.Free()
|
||||
}
|
||||
|
||||
func testStartProcess(t *testing.T) {
|
||||
// migrate db.
|
||||
runDBCliApp(t, "reset", "successful to reset")
|
||||
runDBCliApp(t, "migrate", "current version:")
|
||||
func TestStartProcess(t *testing.T) {
|
||||
// Start l1geth l2geth and postgres docker containers.
|
||||
base.RunImages(t)
|
||||
// reset db.
|
||||
assert.NoError(t, migrate.ResetDB(base.DBClient(t)))
|
||||
|
||||
// Start bridge process.
|
||||
bridgeCmd := runBridgeApp(t)
|
||||
bridgeCmd.RunApp(func() bool { return bridgeCmd.WaitResult(t, time.Second*20, "Start bridge successfully") })
|
||||
// Start bridge.
|
||||
bridge.RunApp(t)
|
||||
|
||||
// Start coordinator process.
|
||||
coordinatorCmd := runCoordinatorApp(t, "--ws", "--ws.port", "8391")
|
||||
coordinatorCmd.RunApp(func() bool { return coordinatorCmd.WaitResult(t, time.Second*20, "Start coordinator successfully") })
|
||||
// Start coordinator, ws is enabled by default.
|
||||
coordinator.RunApp(t)
|
||||
|
||||
// Start roller process.
|
||||
rollerCmd := runRollerApp(t)
|
||||
rollerCmd.ExpectWithTimeout(t, true, time.Second*60, "register to coordinator successfully!")
|
||||
rollerCmd.RunApp(func() bool { return rollerCmd.WaitResult(t, time.Second*40, "roller start successfully") })
|
||||
// Start rollers.
|
||||
rollers.RunApps(t)
|
||||
|
||||
rollerCmd.WaitExit()
|
||||
bridgeCmd.WaitExit()
|
||||
coordinatorCmd.WaitExit()
|
||||
rollers.WaitExit()
|
||||
coordinator.WaitExit()
|
||||
bridge.WaitExit()
|
||||
}
|
||||
|
||||
func testMonitorMetrics(t *testing.T) {
|
||||
// migrate db.
|
||||
runDBCliApp(t, "reset", "successful to reset")
|
||||
runDBCliApp(t, "migrate", "current version:")
|
||||
func TestMonitorMetrics(t *testing.T) {
|
||||
// Start l1geth l2geth and postgres docker containers.
|
||||
base.RunImages(t)
|
||||
// reset db.
|
||||
assert.NoError(t, migrate.ResetDB(base.DBClient(t)))
|
||||
|
||||
// Start bridge process with metrics server.
|
||||
port1, _ := rand.Int(rand.Reader, big.NewInt(2000))
|
||||
svrPort1 := strconv.FormatInt(port1.Int64()+50000, 10)
|
||||
bridgeCmd := runBridgeApp(t, "--metrics", "--metrics.addr", "localhost", "--metrics.port", svrPort1)
|
||||
bridgeCmd.RunApp(func() bool { return bridgeCmd.WaitResult(t, time.Second*20, "Start bridge successfully") })
|
||||
// Start bridge and open metrics flag.
|
||||
bridge.RunApp(t, "--metrics", "--metrics.addr", "localhost", "--metrics.port", svrPort1)
|
||||
|
||||
// Start coordinator process with metrics server.
|
||||
port, _ := rand.Int(rand.Reader, big.NewInt(2000))
|
||||
svrPort2 := strconv.FormatInt(port.Int64()+52000, 10)
|
||||
coordinatorCmd := runCoordinatorApp(t, "--metrics", "--metrics.addr", "localhost", "--metrics.port", svrPort2)
|
||||
coordinatorCmd.RunApp(func() bool { return coordinatorCmd.WaitResult(t, time.Second*20, "Start coordinator successfully") })
|
||||
// Start coordinator.
|
||||
coordinator.RunApp(t, "--metrics", "--metrics.addr", "localhost", "--metrics.port", svrPort2)
|
||||
|
||||
// Get bridge monitor metrics.
|
||||
resp, err := http.Get("http://localhost:" + svrPort1)
|
||||
@@ -98,6 +106,6 @@ func testMonitorMetrics(t *testing.T) {
|
||||
assert.Equal(t, true, strings.Contains(bodyStr, "coordinator_rollers_disconnects_total"))
|
||||
|
||||
// Exit.
|
||||
bridgeCmd.WaitExit()
|
||||
coordinatorCmd.WaitExit()
|
||||
coordinator.WaitExit()
|
||||
bridge.WaitExit()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user