modify testcontainer (#1302)

Co-authored-by: georgehao <haohongfan@gmail.com>
This commit is contained in:
Xin.Zh
2024-04-30 14:44:26 +08:00
committed by GitHub
parent a3635dba52
commit 46b1ff3284
19 changed files with 121 additions and 177 deletions

View File

@@ -1,127 +0,0 @@
package dockercompose
import (
"context"
"crypto/rand"
"fmt"
"math/big"
"os"
"path/filepath"
"time"
"github.com/cloudflare/cfssl/log"
"github.com/scroll-tech/go-ethereum/ethclient"
tc "github.com/testcontainers/testcontainers-go/modules/compose"
"github.com/testcontainers/testcontainers-go/wait"
)
// PoSL1TestEnv represents the config needed to test in PoS Layer 1.
type PoSL1TestEnv struct {
dockerComposeFile string
compose tc.ComposeStack
gethHTTPPort int
hostPath string
}
// NewPoSL1TestEnv creates and initializes a new instance of PoSL1TestEnv with a random HTTP port.
func NewPoSL1TestEnv() (*PoSL1TestEnv, error) {
rootDir, err := findProjectRootDir()
if err != nil {
return nil, fmt.Errorf("failed to find project root directory: %v", err)
}
hostPath, found := os.LookupEnv("HOST_PATH")
if !found {
hostPath = ""
}
rnd, err := rand.Int(rand.Reader, big.NewInt(65536-1024))
if err != nil {
return nil, fmt.Errorf("failed to generate a random: %v", err)
}
gethHTTPPort := int(rnd.Int64()) + 1024
if err := os.Setenv("GETH_HTTP_PORT", fmt.Sprintf("%d", gethHTTPPort)); err != nil {
return nil, fmt.Errorf("failed to set GETH_HTTP_PORT: %v", err)
}
return &PoSL1TestEnv{
dockerComposeFile: filepath.Join(rootDir, "common", "docker-compose", "l1", "docker-compose.yml"),
gethHTTPPort: gethHTTPPort,
hostPath: hostPath,
}, nil
}
// Start starts the PoS L1 test environment by running the associated Docker Compose configuration.
func (e *PoSL1TestEnv) Start() error {
var err error
e.compose, err = tc.NewDockerCompose([]string{e.dockerComposeFile}...)
if err != nil {
return fmt.Errorf("failed to create docker compose: %w", err)
}
env := map[string]string{
"GETH_HTTP_PORT": fmt.Sprintf("%d", e.gethHTTPPort),
}
if e.hostPath != "" {
env["HOST_PATH"] = e.hostPath
}
if err = e.compose.WaitForService("geth", wait.NewHTTPStrategy("/").WithPort("8545/tcp").WithStartupTimeout(15*time.Second)).WithEnv(env).Up(context.Background()); err != nil {
if errStop := e.Stop(); errStop != nil {
log.Error("failed to stop PoS L1 test environment", "err", errStop)
}
return fmt.Errorf("failed to start PoS L1 test environment: %w", err)
}
return nil
}
// Stop stops the PoS L1 test environment by stopping and removing the associated Docker Compose services.
func (e *PoSL1TestEnv) Stop() error {
if e.compose != nil {
if err := e.compose.Down(context.Background(), tc.RemoveOrphans(true), tc.RemoveVolumes(true), tc.RemoveImagesLocal); err != nil {
return fmt.Errorf("failed to stop PoS L1 test environment: %w", err)
}
}
return nil
}
// Endpoint returns the HTTP endpoint for the PoS L1 test environment.
func (e *PoSL1TestEnv) Endpoint() string {
return fmt.Sprintf("http://127.0.0.1:%d", e.gethHTTPPort)
}
// L1Client returns an ethclient by dialing the running PoS L1 test environment
func (e *PoSL1TestEnv) L1Client() (*ethclient.Client, error) {
if e == nil {
return nil, fmt.Errorf("PoS L1 test environment is not initialized")
}
client, err := ethclient.Dial(e.Endpoint())
if err != nil {
return nil, fmt.Errorf("failed to dial PoS L1 test environment: %w", err)
}
return client, nil
}
func findProjectRootDir() (string, error) {
currentDir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get working directory: %w", err)
}
for {
_, err := os.Stat(filepath.Join(currentDir, "go.work"))
if err == nil {
return currentDir, nil
}
parentDir := filepath.Dir(currentDir)
if parentDir == currentDir {
return "", fmt.Errorf("go.work file not found in any parent directory")
}
currentDir = parentDir
}
}

View File

@@ -5,7 +5,6 @@ go 1.21
require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/bits-and-blooms/bitset v1.12.0
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004
github.com/docker/docker v25.0.3+incompatible
github.com/gin-contrib/pprof v1.4.0
github.com/gin-gonic/gin v1.9.1

View File

@@ -8,8 +8,8 @@ services:
mkdir -p /data/execution &&
cp -a /execution/* /data/execution/"
volumes:
- ${HOST_PATH:-../../..}/common/docker-compose/l1/consensus:/consensus
- ${HOST_PATH:-../../..}/common/docker-compose/l1/execution:/execution
- ../../common/testcontainers/consensus:/consensus
- ../../common/testcontainers/execution:/execution
- data:/data
# Creates a genesis state for the beacon chain using a YAML configuration file and
@@ -96,7 +96,7 @@ services:
- --nodiscover
- --syncmode=full
ports:
- ${GETH_HTTP_PORT:-8545}:8545
- 8545
depends_on:
geth-genesis:
condition: service_completed_successfully

View File

@@ -4,10 +4,13 @@ import (
"context"
"fmt"
"log"
"os"
"path/filepath"
"time"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/compose"
"github.com/testcontainers/testcontainers-go/modules/postgres"
"github.com/testcontainers/testcontainers-go/wait"
"gorm.io/gorm"
@@ -20,6 +23,7 @@ type TestcontainerApps struct {
postgresContainer *postgres.PostgresContainer
l1GethContainer *testcontainers.DockerContainer
l2GethContainer *testcontainers.DockerContainer
poSL1Container compose.ComposeStack
// common time stamp in nanoseconds.
Timestamp int
@@ -106,6 +110,55 @@ func (t *TestcontainerApps) StartL2GethContainer() error {
return nil
}
// StartPoSL1Container starts the PoS L1 container by running the associated Docker Compose configuration
func (t *TestcontainerApps) StartPoSL1Container() error {
var (
err error
rootDir string
dockerComposeFile string
)
if rootDir, err = findProjectRootDir(); err != nil {
return fmt.Errorf("failed to find project root directory: %v", err)
}
dockerComposeFile = filepath.Join(rootDir, "common", "testcontainers", "docker-compose.yml")
if t.poSL1Container, err = compose.NewDockerCompose([]string{dockerComposeFile}...); err != nil {
return err
}
err = t.poSL1Container.WaitForService("geth", wait.NewHTTPStrategy("/").
WithPort("8545/tcp").
WithStartupTimeout(15*time.Second)).
Up(context.Background())
if err != nil {
t.poSL1Container = nil
return fmt.Errorf("failed to start PoS L1 container: %w", err)
}
return nil
}
// GetPoSL1EndPoint returns the endpoint of the running PoS L1 endpoint
func (t *TestcontainerApps) GetPoSL1EndPoint() (string, error) {
if t.poSL1Container == nil {
return "", fmt.Errorf("PoS L1 container is not running")
}
contrainer, err := t.poSL1Container.ServiceContainer(context.Background(), "geth")
if err != nil {
panic(err)
}
return contrainer.PortEndpoint(context.Background(), "8545/tcp", "http")
}
// GetPoSL1Client returns a ethclient by dialing running PoS L1 client
func (t *TestcontainerApps) GetPoSL1Client() (*ethclient.Client, error) {
endpoint, err := t.GetPoSL1EndPoint()
if err != nil {
return nil, err
}
return ethclient.Dial(endpoint)
}
// GetDBEndPoint returns the endpoint of the running postgres container
func (t *TestcontainerApps) GetDBEndPoint() (string, error) {
if t.postgresContainer == nil || !t.postgresContainer.IsRunning() {
@@ -197,4 +250,33 @@ func (t *TestcontainerApps) Free() {
log.Printf("failed to stop scroll_l2geth container: %s", err)
}
}
if t.poSL1Container != nil {
if err := t.poSL1Container.Down(context.Background(), compose.RemoveOrphans(true), compose.RemoveVolumes(true), compose.RemoveImagesLocal); err != nil {
log.Printf("failed to stop PoS L1 container: %s", err)
} else {
t.poSL1Container = nil
}
}
}
// findProjectRootDir find project root directory
func findProjectRootDir() (string, error) {
currentDir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get working directory: %w", err)
}
for {
_, err := os.Stat(filepath.Join(currentDir, "go.work"))
if err == nil {
return currentDir, nil
}
parentDir := filepath.Dir(currentDir)
if parentDir == currentDir {
return "", fmt.Errorf("go.work file not found in any parent directory")
}
currentDir = parentDir
}
}

View File

@@ -17,8 +17,9 @@ func TestNewTestcontainerApps(t *testing.T) {
ethclient *ethclient.Client
)
// test start testcontainers
testApps := NewTestcontainerApps()
// test start testcontainers
assert.NoError(t, testApps.StartPostgresContainer())
endpoint, err = testApps.GetDBEndPoint()
assert.NoError(t, err)
@@ -43,6 +44,14 @@ func TestNewTestcontainerApps(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, ethclient)
assert.NoError(t, testApps.StartPoSL1Container())
endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
assert.NotEmpty(t, endpoint)
ethclient, err = testApps.GetPoSL1Client()
assert.NoError(t, err)
assert.NotNil(t, ethclient)
// test free testcontainers
testApps.Free()
endpoint, err = testApps.GetDBEndPoint()
@@ -56,4 +65,8 @@ func TestNewTestcontainerApps(t *testing.T) {
endpoint, err = testApps.GetL2GethEndPoint()
assert.EqualError(t, err, "l2 geth is not running")
assert.Empty(t, endpoint)
endpoint, err = testApps.GetPoSL1EndPoint()
assert.EqualError(t, err, "PoS L1 container is not running")
assert.Empty(t, endpoint)
}

View File

@@ -19,13 +19,12 @@ import (
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
"scroll-tech/database/migrate"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types"
"scroll-tech/common/types/encoding"
"scroll-tech/common/types/message"
"scroll-tech/common/version"
"scroll-tech/database/migrate"
"scroll-tech/coordinator/internal/config"
"scroll-tech/coordinator/internal/controller/api"

View File

@@ -9,12 +9,12 @@ import (
"github.com/scroll-tech/go-ethereum/rpc"
"scroll-tech/prover/config"
"scroll-tech/common/cmd"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types/message"
"scroll-tech/common/utils"
"scroll-tech/prover/config"
)
var (

View File

@@ -7,11 +7,11 @@ import (
"testing"
"time"
"scroll-tech/rollup/internal/config"
"scroll-tech/common/cmd"
"scroll-tech/common/testcontainers"
"scroll-tech/common/utils"
"scroll-tech/rollup/internal/config"
)
// MockApp mockApp-test client manager.

View File

@@ -14,7 +14,6 @@ import (
"github.com/stretchr/testify/assert"
"scroll-tech/common/database"
dockercompose "scroll-tech/common/docker-compose/l1"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types/encoding"
"scroll-tech/common/types/encoding/codecv0"
@@ -26,9 +25,7 @@ var (
// config
cfg *config.Config
testApps *testcontainers.TestcontainerApps
posL1TestEnv *dockercompose.PoSL1TestEnv
testApps *testcontainers.TestcontainerApps
// l2geth client
l2Cli *ethclient.Client
@@ -53,15 +50,13 @@ func setupEnv(t *testing.T) {
cfg, err = config.NewConfig("../../../conf/config.json")
assert.NoError(t, err)
posL1TestEnv, err = dockercompose.NewPoSL1TestEnv()
assert.NoError(t, err, "failed to create PoS L1 test environment")
assert.NoError(t, posL1TestEnv.Start(), "failed to start PoS L1 test environment")
testApps = testcontainers.NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
assert.NoError(t, testApps.StartL2GethContainer())
assert.NoError(t, testApps.StartPoSL1Container())
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = posL1TestEnv.Endpoint()
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetL2GethEndPoint()
assert.NoError(t, err)
@@ -110,9 +105,6 @@ func TestMain(m *testing.M) {
if testApps != nil {
testApps.Free()
}
if posL1TestEnv != nil {
posL1TestEnv.Stop()
}
}()
m.Run()
}

View File

@@ -26,7 +26,6 @@ import (
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
dockercompose "scroll-tech/common/docker-compose/l1"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types"
"scroll-tech/database/migrate"
@@ -41,7 +40,6 @@ var (
privateKey *ecdsa.PrivateKey
cfg *config.Config
testApps *testcontainers.TestcontainerApps
posL1TestEnv *dockercompose.PoSL1TestEnv
txTypes = []string{"LegacyTx", "DynamicFeeTx", "DynamicFeeTx"}
txBlob = []*kzg4844.Blob{nil, nil, randBlob()}
txUint8Types = []uint8{0, 2, 3}
@@ -54,9 +52,6 @@ func TestMain(m *testing.M) {
if testApps != nil {
testApps.Free()
}
if posL1TestEnv != nil {
posL1TestEnv.Stop()
}
}()
m.Run()
}
@@ -73,16 +68,14 @@ func setupEnv(t *testing.T) {
assert.NoError(t, err)
privateKey = priv
posL1TestEnv, err = dockercompose.NewPoSL1TestEnv()
assert.NoError(t, err, "failed to create PoS L1 test environment")
assert.NoError(t, posL1TestEnv.Start(), "failed to start PoS L1 test environment")
testApps = testcontainers.NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
assert.NoError(t, testApps.StartL1GethContainer())
assert.NoError(t, testApps.StartL2GethContainer())
assert.NoError(t, testApps.StartPoSL1Container())
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = posL1TestEnv.Endpoint()
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
db, err = testApps.GetGormDBClient()
assert.NoError(t, err)
@@ -90,7 +83,7 @@ func setupEnv(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, migrate.ResetDB(sqlDB))
l1Client, err := posL1TestEnv.L1Client()
l1Client, err := testApps.GetPoSL1Client()
assert.NoError(t, err)
chainID, err := l1Client.ChainID(context.Background())

View File

@@ -12,13 +12,12 @@ import (
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
"scroll-tech/database/migrate"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types"
"scroll-tech/common/types/encoding"
"scroll-tech/common/types/encoding/codecv0"
"scroll-tech/common/types/encoding/codecv1"
"scroll-tech/database/migrate"
)
var (

View File

@@ -14,7 +14,6 @@ import (
"scroll-tech/database/migrate"
"scroll-tech/common/database"
dockercompose "scroll-tech/common/docker-compose/l1"
tc "scroll-tech/common/testcontainers"
"scroll-tech/common/utils"
@@ -34,9 +33,8 @@ import (
)
var (
testApps *tc.TestcontainerApps
rollupApp *bcmd.MockApp
posL1TestEnv *dockercompose.PoSL1TestEnv
testApps *tc.TestcontainerApps
rollupApp *bcmd.MockApp
// clients
l1Client *ethclient.Client
@@ -72,9 +70,6 @@ func TestMain(m *testing.M) {
if rollupApp != nil {
rollupApp.Free()
}
if posL1TestEnv != nil {
posL1TestEnv.Stop()
}
}()
m.Run()
}
@@ -89,17 +84,14 @@ func setupEnv(t *testing.T) {
l1GethChainID *big.Int
)
posL1TestEnv, err = dockercompose.NewPoSL1TestEnv()
assert.NoError(t, err, "failed to create PoS L1 test environment")
assert.NoError(t, posL1TestEnv.Start(), "failed to start PoS L1 test environment")
testApps = tc.NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
assert.NoError(t, testApps.StartL1GethContainer())
assert.NoError(t, testApps.StartL2GethContainer())
assert.NoError(t, testApps.StartPoSL1Container())
rollupApp = bcmd.NewRollupApp(testApps, "../conf/config.json")
l1Client, err = posL1TestEnv.L1Client()
l1Client, err = testApps.GetPoSL1Client()
assert.NoError(t, err)
l2Client, err = testApps.GetL2GethClient()
assert.NoError(t, err)
@@ -114,8 +106,10 @@ func setupEnv(t *testing.T) {
l1Auth, err = bind.NewKeyedTransactorWithChainID(rollupApp.Config.L2Config.RelayerConfig.CommitSenderPrivateKey, l1GethChainID)
assert.NoError(t, err)
rollupApp.Config.L1Config.Endpoint = posL1TestEnv.Endpoint()
rollupApp.Config.L2Config.RelayerConfig.SenderConfig.Endpoint = posL1TestEnv.Endpoint()
rollupApp.Config.L1Config.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
rollupApp.Config.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
port, err := rand.Int(rand.Reader, big.NewInt(10000))
assert.NoError(t, err)