Skip to content

Commit

Permalink
ARCO-198: refactor integration tests (#579)
Browse files Browse the repository at this point in the history
* move docker related code to test/utils
* move common test functions to test/utils
* decorate test helper functions with t.Helper() for better logs
* ensure all docker resources are removed after tests even on errors
  • Loading branch information
arkadiuszos4chain authored Sep 4, 2024
1 parent 0e31930 commit 2b723dd
Show file tree
Hide file tree
Showing 11 changed files with 480 additions and 708 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.22.5

require (
github.com/bitcoin-sv/go-sdk v1.0.0
github.com/bitcoinsv/bsvutil v0.0.0-20181216182056-1d77cf353ea9
github.com/cenkalti/backoff/v4 v4.3.0
github.com/enescakir/emoji v1.0.0
github.com/getkin/kin-openapi v0.127.0
Expand Down Expand Up @@ -54,7 +55,6 @@ require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bitcoinsv/bsvd v0.0.0-20190609155523-4c29707f7173 // indirect
github.com/bitcoinsv/bsvutil v0.0.0-20181216182056-1d77cf353ea9 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/continuity v0.4.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
Expand Down
222 changes: 60 additions & 162 deletions internal/blocktx/store/postgresql/postgres_test.go

Large diffs are not rendered by default.

127 changes: 21 additions & 106 deletions internal/callbacker/store/postgresql/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,117 +3,55 @@ package postgresql
import (
"context"
"database/sql"
"errors"
"fmt"
"log"
"os"
"sync"
"testing"
"time"

"github.com/bitcoin-sv/arc/internal/callbacker/store"
testutils "github.com/bitcoin-sv/arc/internal/test_utils"
"github.com/bitcoin-sv/arc/internal/testdata"
"github.com/go-testfixtures/testfixtures/v3"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/stretchr/testify/require"

"github.com/golang-migrate/migrate/v4"
migratepostgres "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"

tutils "github.com/bitcoin-sv/arc/internal/callbacker/store/postgresql/internal/tests"
)

const (
postgresPort = "5432"
migrationsPath = "file://migrations"
dbName = "main_test"
dbUsername = "arcuser"
dbPassword = "arcpass"
)

var dbInfo string

func TestMain(m *testing.M) {
pool, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("failed to create pool: %v", err)
}

port := "5433"
opts := dockertest.RunOptions{
Repository: "postgres",
Tag: "15.4",
Env: []string{
fmt.Sprintf("POSTGRES_PASSWORD=%s", dbPassword),
fmt.Sprintf("POSTGRES_USER=%s", dbUsername),
fmt.Sprintf("POSTGRES_DB=%s", dbName),
"listen_addresses = '*'",
},
ExposedPorts: []string{"5432"},
PortBindings: map[docker.Port][]docker.PortBinding{
postgresPort: {
{HostIP: "0.0.0.0", HostPort: port},
},
},
}

resource, err := pool.RunWithOptions(&opts, func(config *docker.HostConfig) {
// set AutoRemove to true so that stopped container goes away by itself
config.AutoRemove = true
config.RestartPolicy = docker.RestartPolicy{
Name: "no",
}
config.Tmpfs = map[string]string{
"/var/lib/postgresql/data": "",
}
})
if err != nil {
log.Fatalf("failed to create resource: %v", err)
}

hostPort := resource.GetPort("5432/tcp")

dbInfo = fmt.Sprintf("host=localhost port=%s user=%s password=%s dbname=%s sslmode=disable", hostPort, dbUsername, dbPassword, dbName)
dbConn, err := sql.Open("postgres", dbInfo)
if err != nil {
log.Fatalf("failed to create db connection: %v", err)
}
err = pool.Retry(func() error {
return dbConn.Ping()
})

if err != nil {
log.Fatalf("failed to connect to docker: %s", err)
}

driver, err := migratepostgres.WithInstance(dbConn, &migratepostgres.Config{
MigrationsTable: "callbacker",
})
if err != nil {
log.Fatalf("failed to create driver: %v", err)
}
os.Exit(testmain(m))
}

migrations, err := migrate.NewWithDatabaseInstance(
migrationsPath,
"postgres", driver)
func testmain(m *testing.M) int {
pool, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("failed to initialize migrate instance: %v", err)
}
err = migrations.Up()
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
log.Fatalf("failed to initialize migrate instance: %v", err)
log.Printf("failed to create pool: %v", err)
return 1
}

code := m.Run()

err = pool.Purge(resource)
port := "5436"
resource, connStr, err := testutils.RunAndMigratePostgresql(pool, port, "callbacker", migrationsPath)
if err != nil {
log.Fatalf("failed to purge pool: %v", err)
log.Print(err)
return 1
}
defer func() {
err = pool.Purge(resource)
if err != nil {
log.Fatalf("failed to purge pool: %v", err)
}
}()

os.Exit(code)
dbInfo = connStr
return m.Run()
}

func TestPostgresDBt(t *testing.T) {
Expand Down Expand Up @@ -219,7 +157,7 @@ func TestPostgresDBt(t *testing.T) {
t.Run("pop many", func(t *testing.T) {
// given
defer pruneTables(t, postgresDB.db)
loadFixtures(t, postgresDB.db, "fixtures/pop_many")
testutils.LoadFixtures(t, postgresDB.db, "fixtures/pop_many")

const concurentCalls = 5
const popLimit = 10
Expand Down Expand Up @@ -266,28 +204,5 @@ func TestPostgresDBt(t *testing.T) {
}

func pruneTables(t *testing.T, db *sql.DB) {
t.Helper()

_, err := db.Exec("TRUNCATE TABLE callbacker.callbacks;")
if err != nil {
t.Fatal(err)
}
}

func loadFixtures(t *testing.T, db *sql.DB, path string) {
t.Helper()

fixtures, err := testfixtures.New(
testfixtures.Database(db),
testfixtures.Dialect("postgresql"),
testfixtures.Directory(path), // The directory containing the YAML files
)
if err != nil {
t.Fatalf("failed to create fixtures: %v", err)
}

err = fixtures.Load()
if err != nil {
t.Fatalf("failed to load fixtures: %v", err)
}
testutils.PruneTables(t, db, "callbacker.callbacks")
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package integration_test

import (
"fmt"
"log"
"log/slog"
"os"
Expand All @@ -12,16 +11,15 @@ import (
"github.com/bitcoin-sv/arc/internal/message_queue/nats/client/nats_core"
"github.com/bitcoin-sv/arc/internal/message_queue/nats/nats_connection"
"github.com/bitcoin-sv/arc/internal/metamorph/metamorph_api"
testutils "github.com/bitcoin-sv/arc/internal/test_utils"
"github.com/bitcoin-sv/arc/internal/testdata"
"github.com/nats-io/nats.go"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
)

const (
natsPort = "4222"
SubmitTxTopic = "submit-tx"
MinedTxsTopic = "mined-txs"
)
Expand All @@ -33,67 +31,54 @@ var (
)

func TestMain(m *testing.M) {
os.Exit(testmain(m))
}

func testmain(m *testing.M) int {
pool, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("failed to create pool: %v", err)
log.Printf("failed to create pool: %v", err)
return 1
}

port := "4336"
opts := dockertest.RunOptions{
Repository: "nats",
Tag: "2.10.10",
ExposedPorts: []string{natsPort},
PortBindings: map[docker.Port][]docker.PortBinding{
natsPort: {
{HostIP: "0.0.0.0", HostPort: port},
},
},
Name: "nats-core",
}

resource, err := pool.RunWithOptions(&opts, func(config *docker.HostConfig) {
// set AutoRemove to true so that stopped container goes away by itself
config.AutoRemove = true
config.RestartPolicy = docker.RestartPolicy{
Name: "no",
}
})
name := "nats-core"
resource, natsURL, err := testutils.RunNats(pool, port, name)
if err != nil {
log.Fatalf("failed to create resource: %v", err)
log.Print(err)
return 1
}

hostPort := resource.GetPort(fmt.Sprintf("%s/tcp", natsPort))
natsURL := fmt.Sprintf("nats://localhost:%s", hostPort)

logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))

natsConnClient, err = nats_connection.New(natsURL, logger)
if err != nil {
log.Fatalf("failed to create nats connection: %v", err)
log.Printf("failed to create nats connection: %v", err)
return 1
}

natsConn, err = nats_connection.New(natsURL, logger)
if err != nil {
log.Fatalf("failed to create nats connection: %v", err)
log.Printf("failed to create nats connection: %v", err)
return 1
}

time.Sleep(5 * time.Second)

code := m.Run()

err = natsConn.Drain()
if err != nil {
log.Fatalf("failed to drain nats connection: %v", err)
}
defer func() {
err = natsConn.Drain()
if err != nil {
log.Fatalf("failed to drain nats connection: %v", err)
}

mqClient.Shutdown()
mqClient.Shutdown()

err = pool.Purge(resource)
if err != nil {
log.Fatalf("failed to purge pool: %v", err)
}
err = pool.Purge(resource)
if err != nil {
log.Fatalf("failed to purge pool: %v", err)
}
}()

os.Exit(code)
time.Sleep(5 * time.Second)
return m.Run()
}

func TestNatsClient(t *testing.T) {
Expand Down
Loading

0 comments on commit 2b723dd

Please sign in to comment.