diff --git a/dapps/valuetransfers/packages/tangle/snapshot_test.go b/dapps/valuetransfers/packages/tangle/snapshot_test.go index 4011f34d9ecf46c1e0e4bcdb055619726cc5efea..7ef8b153864d90fdfebd5034ec22ab676f87f6bb 100644 --- a/dapps/valuetransfers/packages/tangle/snapshot_test.go +++ b/dapps/valuetransfers/packages/tangle/snapshot_test.go @@ -43,7 +43,7 @@ func TestLoadSnapshot(t *testing.T) { } func TestSnapshotMarshalUnmarshal(t *testing.T) { - const genesisBalance = 3333 + const genesisBalance = 1000000000 seed := wallet.NewSeed() genesisAddr := seed.Address(GENESIS) diff --git a/tools/integration-tests/assets/7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih.bin b/tools/integration-tests/assets/7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih.bin new file mode 100644 index 0000000000000000000000000000000000000000..2e55197593a21cb650727fb4a4f9c58e92acbc4d Binary files /dev/null and b/tools/integration-tests/assets/7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih.bin differ diff --git a/tools/integration-tests/assets/entrypoint.sh b/tools/integration-tests/assets/entrypoint.sh new file mode 100644 index 0000000000000000000000000000000000000000..a5ec0407b81c57c162ead53b0494c224f3c76ae7 --- /dev/null +++ b/tools/integration-tests/assets/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/bash +echo "copying assets into shared volume..." +rm -rf /assets/* +cp -rp /tmp/assets/* /assets +chmod 777 /assets/* +echo "assets:" +ls /assets +echo "running tests..." +go test ./tests/"${TEST_NAME}" -v -timeout 30m diff --git a/tools/integration-tests/runTests.sh b/tools/integration-tests/runTests.sh index 71a65da52f4cf9fb0441d8caeef39e2d578b8c0a..51612ed3052eb7028dbcf77006651e09ed09cce6 100755 --- a/tools/integration-tests/runTests.sh +++ b/tools/integration-tests/runTests.sh @@ -1,6 +1,6 @@ #!/bin/bash -TEST_NAMES='autopeering common drng message' +TEST_NAMES='consensus' echo "Build GoShimmer image" docker build -t iotaledger/goshimmer ../../. @@ -10,8 +10,6 @@ docker pull angelocapossele/drand:latest docker pull gaiaadm/pumba:latest docker pull gaiadocker/iproute2:latest -echo "Run integration tests" - for name in $TEST_NAMES do TEST_NAME=$name docker-compose -f tester/docker-compose.yml up --abort-on-container-exit --exit-code-from tester --build diff --git a/tools/integration-tests/tester/docker-compose.yml b/tools/integration-tests/tester/docker-compose.yml index 3b291d69fabb2447f74b68d6e3421b85600efd25..592f47e7af9eade0bf1a1fcd61c161723e4c3870 100644 --- a/tools/integration-tests/tester/docker-compose.yml +++ b/tools/integration-tests/tester/docker-compose.yml @@ -5,13 +5,19 @@ services: container_name: tester image: golang:1.14 working_dir: /tmp/goshimmer/tools/integration-tests/tester - entrypoint: go test ./tests/${TEST_NAME} -v -mod=readonly -timeout 30m + command: /tmp/assets/entrypoint.sh + environment: + - TEST_NAME=${TEST_NAME} volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - - ../../..:/tmp/goshimmer:ro + - ../../..:/tmp/goshimmer:rw - ../logs:/tmp/logs + - ../assets:/tmp/assets - goshimmer-testing-cache:/go + - goshimmer-testing-assets:/assets volumes: goshimmer-testing-cache: name: goshimmer-testing-cache + goshimmer-testing-assets: + name: goshimmer-testing-assets \ No newline at end of file diff --git a/tools/integration-tests/tester/framework/docker.go b/tools/integration-tests/tester/framework/docker.go index 9bee5dba909165382e91f38268e9cca3a932ef27..86b42d778f3fce8c00129b6c8416f12ef920a375 100644 --- a/tools/integration-tests/tester/framework/docker.go +++ b/tools/integration-tests/tester/framework/docker.go @@ -94,6 +94,7 @@ func (d *DockerContainer) CreateGoShimmerPeer(config GoShimmerConfig) error { } return strings.Join(plugins[:], ",") }()), + fmt.Sprintf("--valueLayer.snapshot.file=%s", config.SnapshotFilePath), fmt.Sprintf("--bootstrap.initialIssuance.timePeriodSec=%d", config.BootstrapInitialIssuanceTimePeriodSec), "--webapi.bindAddress=0.0.0.0:8080", fmt.Sprintf("--autopeering.seed=base58:%s", config.Seed), @@ -105,7 +106,9 @@ func (d *DockerContainer) CreateGoShimmerPeer(config GoShimmerConfig) error { }, } - return d.CreateContainer(config.Name, containerConfig) + return d.CreateContainer(config.Name, containerConfig, &container.HostConfig{ + Binds: []string{"goshimmer-testing-assets:/assets:rw"}, + }) } // CreateDrandMember creates a new container with the drand configuration. diff --git a/tools/integration-tests/tester/framework/network.go b/tools/integration-tests/tester/framework/network.go index 4580588fedf103c88770044e22cf1cb7c8b6babd..b2001e554c81fc8bcfd922a6acf5b23466b32bdc 100644 --- a/tools/integration-tests/tester/framework/network.go +++ b/tools/integration-tests/tester/framework/network.go @@ -100,6 +100,7 @@ func (n *Network) CreatePeer(c GoShimmerConfig) (*Peer, error) { config.EntryNodeHost = n.namePrefix(containerNameEntryNode) config.EntryNodePublicKey = n.entryNodePublicKey() config.DisabledPlugins = disabledPluginsPeer + config.SnapshotFilePath = snapshotFilePath // create wallet var nodeWallet *wallet.Wallet diff --git a/tools/integration-tests/tester/framework/parameters.go b/tools/integration-tests/tester/framework/parameters.go index fb4e14353b68638eebb4f53a2266a99a8e1253b0..ed820a976893a6b9a4b4415a044da5dbb67806d7 100644 --- a/tools/integration-tests/tester/framework/parameters.go +++ b/tools/integration-tests/tester/framework/parameters.go @@ -19,8 +19,8 @@ const ( disabledPluginsEntryNode = "portcheck,dashboard,analysis-client,profiling,gossip,drng,issuer,sync,metrics,valuetransfers,testsnapshots,messagelayer,webapi,webapibroadcastdataendpoint,webapifindtransactionhashesendpoint,webapigetneighborsendpoint,webapigettransactionobjectsbyhashendpoint,webapigettransactiontrytesbyhashendpoint" disabledPluginsPeer = "portcheck,dashboard,analysis-client,profiling" - - dockerLogsPrefixLen = 8 + snapshotFilePath = "/assets/7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih.bin" + dockerLogsPrefixLen = 8 dkgMaxTries = 50 @@ -39,6 +39,7 @@ type GoShimmerConfig struct { EntryNodeHost string EntryNodePublicKey string DisabledPlugins string + SnapshotFilePath string Bootstrap bool BootstrapInitialIssuanceTimePeriodSec int diff --git a/tools/integration-tests/tester/go.mod b/tools/integration-tests/tester/go.mod index 81fe8f1db5258747f5dd843238207468d7dc4c99..6b1a07c6b278e4e2d5f257601111fd368c254353 100644 --- a/tools/integration-tests/tester/go.mod +++ b/tools/integration-tests/tester/go.mod @@ -11,6 +11,7 @@ require ( github.com/drand/drand v0.8.1 github.com/iotaledger/goshimmer v0.1.3 github.com/iotaledger/hive.go v0.0.0-20200610104211-d603429af242 + github.com/mr-tron/base58 v1.1.3 github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/stretchr/testify v1.5.1 ) diff --git a/tools/integration-tests/tester/tests/consensus/consensus_test.go b/tools/integration-tests/tester/tests/consensus/consensus_test.go new file mode 100644 index 0000000000000000000000000000000000000000..43e937f4836e5258d326c3101fb5b303298c0f8a --- /dev/null +++ b/tools/integration-tests/tester/tests/consensus/consensus_test.go @@ -0,0 +1,79 @@ +package autopeering + +import ( + "testing" + "time" + + "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address" + "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address/signaturescheme" + "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance" + "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction" + "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/wallet" + "github.com/iotaledger/goshimmer/tools/integration-tests/tester/tests" + "github.com/mr-tron/base58/base58" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestConsensusNoConflicts issues valid non-conflicting value objects and then checks +// whether the ledger of every peer reflects the same correct state. +func TestConsensusNoConflicts(t *testing.T) { + n, err := f.CreateNetwork("consensus_TestConsensusNoConflicts", 4, 2) + require.NoError(t, err) + defer tests.ShutdownNetwork(t, n) + + time.Sleep(5 * time.Second) + + // genesis wallet + genesisSeedBytes, err := base58.Decode("7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih") + require.NoError(t, err, "couldn't decode genesis seed from base58 seed") + + const genesisBalance = 1000000000 + genesisWallet := wallet.New(genesisSeedBytes) + genesisAddr := genesisWallet.Seed().Address(0) + genesisOutputID := transaction.NewOutputID(genesisAddr, transaction.GenesisID) + + w := wallet.New() + addr1 := w.Seed().Address(0) + addr2 := w.Seed().Address(1) + const deposit = genesisBalance / 2 + + // issue transaction spending from the genesis output + tx := transaction.New( + transaction.NewInputs(genesisOutputID), + transaction.NewOutputs(map[address.Address][]*balance.Balance{ + addr1: {{Value: deposit, Color: balance.ColorIOTA}}, + addr2: {{Value: deposit, Color: balance.ColorIOTA}}, + }), + ) + tx = tx.Sign(signaturescheme.ED25519(*genesisWallet.Seed().KeyPair(0))) + + txID, err := n.Peers()[0].SendTransaction(tx.Bytes()) + require.NoError(t, err) + + // wait for the transaction to be propagated through the network + time.Sleep(10 * time.Second) + + // check that each node has the same perception + for _, p := range n.Peers() { + // check existence of the transaction we just created + res, err := p.GetTransactionByID(txID) + assert.NoError(t, err) + assert.Len(t, res.Error, 0, "there shouldn't be any error from submitting the valid transaction") + assert.Len(t, res.Transaction.Inputs, 1) + assert.Equal(t, genesisOutputID.String(), res.Transaction.Inputs[0]) + + // check that genesis UTXO is spent + utxos, err := p.GetUnspentOutputs([]string{genesisAddr.String()}) + assert.NoError(t, err) + assert.Len(t, utxos.UnspentOutputs, 0, "genesis address should not have any UTXOs") + + // check UTXOs + utxos, err = p.GetUnspentOutputs([]string{addr1.String(), addr2.String()}) + assert.Len(t, utxos.UnspentOutputs, 2, "addresses should have UTXOs") + assert.Equal(t, addr1.String(), utxos.UnspentOutputs[0].Address) + assert.Equal(t, deposit, utxos.UnspentOutputs[0].OutputIDs[0].Balances[0].Value) + assert.Equal(t, addr2.String(), utxos.UnspentOutputs[1].Address) + assert.Equal(t, deposit, utxos.UnspentOutputs[1].OutputIDs[0].Balances[0].Value) + } +} diff --git a/tools/integration-tests/tester/tests/consensus/main_test.go b/tools/integration-tests/tester/tests/consensus/main_test.go new file mode 100644 index 0000000000000000000000000000000000000000..bcc09c2e53590df061cbff5a2159071d567440f1 --- /dev/null +++ b/tools/integration-tests/tester/tests/consensus/main_test.go @@ -0,0 +1,23 @@ +package autopeering + +import ( + "os" + "testing" + + "github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework" +) + +var f *framework.Framework + +// TestMain gets called by the test utility and is executed before any other test in this package. +// It is therefore used to initialize the integration testing framework. +func TestMain(m *testing.M) { + var err error + f, err = framework.Instance() + if err != nil { + panic(err) + } + + // call the tests + os.Exit(m.Run()) +}