rippled
Transaction_ordering_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5  Permission to use, copy, modify, and/or distribute this software for any
6  purpose with or without fee is hereby granted, provided that the above
7  copyright notice and this permission notice appear in all copies.
8  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 //==============================================================================
17 
18 #include <ripple/core/JobQueue.h>
19 #include <ripple/protocol/ErrorCodes.h>
20 #include <test/jtx.h>
21 
22 namespace ripple {
23 namespace test {
24 
25 struct Transaction_ordering_test : public beast::unit_test::suite
26 {
27  void
29  {
30  using namespace jtx;
31  testcase("Correct Order");
32 
33  Env env(*this);
34  auto const alice = Account("alice");
35  env.fund(XRP(1000), noripple(alice));
36 
37  auto const aliceSequence = env.seq(alice);
38 
39  auto const tx1 = env.jt(noop(alice), seq(aliceSequence));
40  auto const tx2 = env.jt(
41  noop(alice),
42  seq(aliceSequence + 1),
43  json(R"({"LastLedgerSequence":7})"));
44 
45  env(tx1);
46  env.close();
47  BEAST_EXPECT(env.seq(alice) == aliceSequence + 1);
48  env(tx2);
49  env.close();
50  BEAST_EXPECT(env.seq(alice) == aliceSequence + 2);
51 
52  env.close();
53 
54  {
55  auto const result =
56  env.rpc("tx", to_string(tx1.stx->getTransactionID()));
57  BEAST_EXPECT(
58  result["result"]["meta"]["TransactionResult"] == "tesSUCCESS");
59  }
60  {
61  auto const result =
62  env.rpc("tx", to_string(tx2.stx->getTransactionID()));
63  BEAST_EXPECT(
64  result["result"]["meta"]["TransactionResult"] == "tesSUCCESS");
65  }
66  }
67 
68  void
70  {
71  using namespace jtx;
72 
73  testcase("Incorrect order");
74 
75  Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
76  cfg->FORCE_MULTI_THREAD = false;
77  return cfg;
78  }));
79 
80  auto const alice = Account("alice");
81  env.fund(XRP(1000), noripple(alice));
82 
83  auto const aliceSequence = env.seq(alice);
84 
85  auto const tx1 = env.jt(noop(alice), seq(aliceSequence));
86  auto const tx2 = env.jt(
87  noop(alice),
88  seq(aliceSequence + 1),
89  json(R"({"LastLedgerSequence":7})"));
90 
91  env(tx2, ter(terPRE_SEQ));
92  BEAST_EXPECT(env.seq(alice) == aliceSequence);
93  env(tx1);
94  env.app().getJobQueue().rendezvous();
95  BEAST_EXPECT(env.seq(alice) == aliceSequence + 2);
96 
97  env.close();
98 
99  {
100  auto const result =
101  env.rpc("tx", to_string(tx1.stx->getTransactionID()));
102  BEAST_EXPECT(
103  result["result"]["meta"]["TransactionResult"] == "tesSUCCESS");
104  }
105  {
106  auto const result =
107  env.rpc("tx", to_string(tx2.stx->getTransactionID()));
108  BEAST_EXPECT(
109  result["result"]["meta"]["TransactionResult"] == "tesSUCCESS");
110  }
111  }
112 
113  void
115  {
116  using namespace jtx;
117 
118  testcase("Incorrect order multiple intermediaries");
119 
120  Env env(*this, envconfig([](std::unique_ptr<Config> cfg) {
121  cfg->FORCE_MULTI_THREAD = true;
122  return cfg;
123  }));
124 
125  auto const alice = Account("alice");
126  env.fund(XRP(1000), noripple(alice));
127 
128  auto const aliceSequence = env.seq(alice);
129 
130  std::vector<JTx> tx;
131  for (auto i = 0; i < 5; ++i)
132  {
133  tx.emplace_back(env.jt(
134  noop(alice),
135  seq(aliceSequence + i),
136  json(R"({"LastLedgerSequence":7})")));
137  }
138 
139  for (auto i = 1; i < 5; ++i)
140  {
141  env(tx[i], ter(terPRE_SEQ));
142  BEAST_EXPECT(env.seq(alice) == aliceSequence);
143  }
144 
145  env(tx[0]);
146  env.app().getJobQueue().rendezvous();
147  BEAST_EXPECT(env.seq(alice) == aliceSequence + 5);
148 
149  env.close();
150 
151  for (auto i = 0; i < 5; ++i)
152  {
153  auto const result =
154  env.rpc("tx", to_string(tx[i].stx->getTransactionID()));
155  BEAST_EXPECT(
156  result["result"]["meta"]["TransactionResult"] == "tesSUCCESS");
157  }
158  }
159 
160  void
161  run() override
162  {
166  }
167 };
168 
169 BEAST_DEFINE_TESTSUITE(Transaction_ordering, app, ripple);
170 
171 } // namespace test
172 } // namespace ripple
ripple::test::jtx::json
Inject raw JSON.
Definition: jtx_json.h:31
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
std::vector
STL class.
ripple::test::jtx::Env::jt
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:439
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:241
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::test::Transaction_ordering_test::testIncorrectOrder
void testIncorrectOrder()
Definition: Transaction_ordering_test.cpp:69
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::test::Transaction_ordering_test::testIncorrectOrderMultipleIntermediaries
void testIncorrectOrderMultipleIntermediaries()
Definition: Transaction_ordering_test.cpp:114
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::test::jtx::Env::seq
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:207
ripple::JobQueue::rendezvous
void rendezvous()
Block until no jobs running.
Definition: JobQueue.cpp:254
ripple::test::Transaction_ordering_test::testCorrectOrder
void testCorrectOrder()
Definition: Transaction_ordering_test.cpp:28
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:33
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::jtx::noripple
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
Definition: Env.h:64
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:228
ripple::test::Transaction_ordering_test::run
void run() override
Definition: Transaction_ordering_test.cpp:161
ripple::test::Transaction_ordering_test
Definition: Transaction_ordering_test.cpp:25
ripple::terPRE_SEQ
@ terPRE_SEQ
Definition: TER.h:202
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
std::unique_ptr
STL class.
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:687
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)