From eac93731132594cfb2c88b111a65d37077185023 Mon Sep 17 00:00:00 2001 From: Bartek Nowotarski Date: Tue, 15 Jun 2021 12:35:30 +0200 Subject: [PATCH] services/horizon: Add txsub integration test (#3689) Adds sanity integration test for txsub. Add a test (`submit_transaction_test.go`) I forgot to include in #3653. While we have some unit tests for txsub we don't test the transaction submission endpoint during mirroring test. A simple integration test should at least catch the most obvious bugs. --- .../actions/submit_transaction_test.go | 66 ++++++++++++++++++ .../internal/integration/txsub_test.go | 69 +++++++++++++++++++ .../internal/test/integration/integration.go | 4 ++ 3 files changed, 139 insertions(+) create mode 100644 services/horizon/internal/actions/submit_transaction_test.go create mode 100644 services/horizon/internal/integration/txsub_test.go diff --git a/services/horizon/internal/actions/submit_transaction_test.go b/services/horizon/internal/actions/submit_transaction_test.go new file mode 100644 index 0000000000..129f9de6f5 --- /dev/null +++ b/services/horizon/internal/actions/submit_transaction_test.go @@ -0,0 +1,66 @@ +package actions + +import ( + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + + "github.com/stellar/go/network" + "github.com/stellar/go/services/horizon/internal/corestate" + "github.com/stellar/go/support/render/problem" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestStellarCoreMalformedTx(t *testing.T) { + handler := SubmitTransactionHandler{} + + r := httptest.NewRequest("POST", "https://horizon.stellar.org/transactions", nil) + w := httptest.NewRecorder() + _, err := handler.GetResource(w, r) + assert.Error(t, err) + assert.Equal(t, http.StatusBadRequest, err.(*problem.P).Status) + assert.Equal(t, "Transaction Malformed", err.(*problem.P).Title) +} + +type coreStateGetterMock struct { + mock.Mock +} + +func (m *coreStateGetterMock) GetCoreState() corestate.State { + a := m.Called() + return a.Get(0).(corestate.State) +} + +func TestStellarCoreNotSynced(t *testing.T) { + mock := &coreStateGetterMock{} + mock.On("GetCoreState").Return(corestate.State{ + Synced: false, + }) + + handler := SubmitTransactionHandler{ + NetworkPassphrase: network.PublicNetworkPassphrase, + CoreStateGetter: mock, + } + + form := url.Values{} + form.Set("tx", "AAAAAAGUcmKO5465JxTSLQOQljwk2SfqAJmZSG6JH6wtqpwhAAABLAAAAAAAAAABAAAAAAAAAAEAAAALaGVsbG8gd29ybGQAAAAAAwAAAAAAAAAAAAAAABbxCy3mLg3hiTqX4VUEEp60pFOrJNxYM1JtxXTwXhY2AAAAAAvrwgAAAAAAAAAAAQAAAAAW8Qst5i4N4Yk6l+FVBBKetKRTqyTcWDNSbcV08F4WNgAAAAAN4Lazj4x61AAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLaqcIQAAAEBKwqWy3TaOxoGnfm9eUjfTRBvPf34dvDA0Nf+B8z4zBob90UXtuCqmQqwMCyH+okOI3c05br3khkH0yP4kCwcE") + + request, err := http.NewRequest( + "POST", + "https://horizon.stellar.org/transactions", + strings.NewReader(form.Encode()), + ) + require.NoError(t, err) + request.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + w := httptest.NewRecorder() + _, err = handler.GetResource(w, request) + assert.Error(t, err) + assert.Equal(t, http.StatusServiceUnavailable, err.(problem.P).Status) + assert.Equal(t, "stale_history", err.(problem.P).Type) + assert.Equal(t, "Historical DB Is Too Stale", err.(problem.P).Title) +} diff --git a/services/horizon/internal/integration/txsub_test.go b/services/horizon/internal/integration/txsub_test.go new file mode 100644 index 0000000000..c0b1abe694 --- /dev/null +++ b/services/horizon/internal/integration/txsub_test.go @@ -0,0 +1,69 @@ +package integration + +import ( + "strconv" + "sync" + "testing" + + "github.com/stellar/go/services/horizon/internal/test/integration" + "github.com/stellar/go/txnbuild" + "github.com/stretchr/testify/assert" +) + +func TestTxsub(t *testing.T) { + tt := assert.New(t) + itest := integration.NewTest(t, integration.Config{ProtocolVersion: 17}) + master := itest.Master() + + // Sanity check: create 20 accounts and submit 2 txs from each of them as + // a source at the same time. Then check if the results are correct. + t.Run("Sanity", func(t *testing.T) { + testAccounts := 20 + subsPerAccont := 2 + keys, accounts := itest.CreateAccounts(testAccounts, "1000") + + var wg sync.WaitGroup + + for i := 0; i < testAccounts; i++ { + for j := 0; j < subsPerAccont; j++ { + wg.Add(1) + + seq, err := accounts[i].GetSequenceNumber() + assert.NoError(t, err) + + var account txnbuild.SimpleAccount + if j == 0 { + account = txnbuild.SimpleAccount{ + AccountID: keys[i].Address(), + Sequence: seq, + } + } else { + account = txnbuild.SimpleAccount{ + AccountID: keys[i].Address(), + Sequence: seq + 1, + } + } + + go func(i int, j int, account txnbuild.SimpleAccount) { + defer wg.Done() + + op := txnbuild.Payment{ + Destination: master.Address(), + Amount: "10", + Asset: txnbuild.NativeAsset{}, + } + + txResp := itest.MustSubmitOperations(&account, keys[i], &op) + + tt.Equal(accounts[i].GetAccountID(), txResp.Account) + seq, err := account.GetSequenceNumber() + assert.NoError(t, err) + tt.Equal(strconv.FormatInt(seq, 10), txResp.AccountSequence) + t.Logf("%d/%d done", i, j) + }(i, j, account) + } + } + + wg.Wait() + }) +} diff --git a/services/horizon/internal/test/integration/integration.go b/services/horizon/internal/test/integration/integration.go index 8ce35386f4..3e93df7786 100644 --- a/services/horizon/internal/test/integration/integration.go +++ b/services/horizon/internal/test/integration/integration.go @@ -226,6 +226,10 @@ of accounts, subscribe to event streams, and more.`, // due to ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING "--checkpoint-frequency", "8", + + // disable rate limiting + "--per-hour-rate-limit", + "0", } // initialize core arguments