diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index deec70bf1..5785290a2 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -1440,9 +1440,6 @@
-
- True
-
True
@@ -1487,6 +1484,9 @@
+
+ True
+
True
@@ -1681,6 +1681,11 @@
+
+ True
+
+
+
True
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index 9f89b82bd..2117a5a2a 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -286,6 +286,9 @@
{CE126498-A44D-30A2-345B-0F672BCDF947}
+
+ {55A76B5B-A18E-E655-1A07-9492C6F8F356}
+
{91D5931B-D981-52BC-BC12-08DA9F7BF606}
@@ -307,6 +310,9 @@
{07831F2A-6752-E81C-87AF-4D47D425BE8E}
+
+ {2E791662-6ED0-D1E1-03A4-0CB35473EC56}
+
{418BEF0D-AAAB-C368-7D9E-0A97636DE5A6}
@@ -2259,9 +2265,6 @@
ripple\app\ledger
-
- ripple\app\ledger
-
ripple\app\ledger
@@ -2316,6 +2319,9 @@
ripple\app\ledger
+
+ ripple\app\ledger\tests
+
ripple\app\ledger
@@ -2547,6 +2553,12 @@
ripple\app\peers
+
+ ripple\app\tests
+
+
+ ripple\app\tests
+
ripple\app\transactors
diff --git a/src/ripple/app/ledger/Ledger.test.cpp b/src/ripple/app/ledger/Ledger.test.cpp
deleted file mode 100644
index 4a3e4c098..000000000
--- a/src/ripple/app/ledger/Ledger.test.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of rippled: https://github.com/ripple/rippled
- Copyright (c) 2012, 2013 Ripple Labs Inc.
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace ripple {
-
-class Ledger_test : public beast::unit_test::suite
-{
- using TestAccount = std::pair;
-
- struct Amount
- {
- Amount (double value_, std::string currency_, TestAccount issuer_)
- : value(value_)
- , currency(currency_)
- , issuer(issuer_)
- {
- }
-
- double value;
- std::string currency;
- TestAccount issuer;
-
- Json::Value
- getJson() const
- {
- Json::Value tx_json;
- tx_json["currency"] = currency;
- tx_json["issuer"] = issuer.first.humanAccountID();
- tx_json["value"] = std::to_string(value);
- return tx_json;
- }
- };
-
- // Helper function to parse a transaction in Json, sign it with account,
- // and return it as a STTx
- STTx
- parseTransaction(TestAccount& account, Json::Value const& tx_json)
- {
- STParsedJSONObject parsed("tx_json", tx_json);
- std::unique_ptr sopTrans = std::move(parsed.object);
- expect(sopTrans != nullptr);
- sopTrans->setFieldVL(sfSigningPubKey, account.first.getAccountPublic());
- return STTx(*sopTrans);
- }
-
- // Helper function to apply a transaction to a ledger
- void
- applyTransaction(Ledger::pointer const& ledger, STTx const& tx)
- {
- TransactionEngine engine(ledger);
- bool didApply = false;
- auto r = engine.applyTransaction(tx, tapOPEN_LEDGER | tapNO_CHECK_SIGN,
- didApply);
- expect(r == tesSUCCESS);
- expect(didApply);
- }
-
- // Create genesis ledger from a start amount in drops, and the public
- // master RippleAddress
- Ledger::pointer
- createGenesisLedger(std::uint64_t start_amount_drops, TestAccount const& master)
- {
- Ledger::pointer ledger = std::make_shared(master.first,
- start_amount_drops);
- ledger->updateHash();
- ledger->setClosed();
- expect(ledger->assertSane());
- return ledger;
- }
-
- // Create an account represented by public RippleAddress and private
- // RippleAddress
- TestAccount
- createAccount()
- {
- static RippleAddress const seed
- = RippleAddress::createSeedGeneric ("masterpassphrase");
- static RippleAddress const generator
- = RippleAddress::createGeneratorPublic (seed);
- static int iSeq = -1;
- ++iSeq;
- return std::make_pair(RippleAddress::createAccountPublic(generator, iSeq),
- std::uint64_t(0));
- }
-
- void
- freezeAccount(TestAccount& account, Ledger::pointer const& ledger)
- {
- Json::Value tx_json;
- tx_json["TransactionType"] = "AccountSet";
- tx_json["Fee"] = std::to_string(10);
- tx_json["Account"] = account.first.humanAccountID();
- tx_json["SetFlag"] = asfGlobalFreeze;
- tx_json["Sequence"] = ++account.second;
- STTx tx = parseTransaction(account, tx_json);
- applyTransaction(ledger, tx);
- }
-
- void
- unfreezeAccount(TestAccount& account, Ledger::pointer const& ledger)
- {
- Json::Value tx_json;
- tx_json["TransactionType"] = "AccountSet";
- tx_json["Fee"] = std::to_string(10);
- tx_json["Account"] = account.first.humanAccountID();
- tx_json["ClearFlag"] = asfGlobalFreeze;
- tx_json["Sequence"] = ++account.second;
- STTx tx = parseTransaction(account, tx_json);
- applyTransaction(ledger, tx);
- }
-
- void
- makePayment(TestAccount& from, TestAccount const& to,
- std::uint64_t amountDrops,
- Ledger::pointer const& ledger)
- {
- Json::Value tx_json;
- tx_json["Account"] = from.first.humanAccountID();
- tx_json["Amount"] = std::to_string(amountDrops);
- tx_json["Destination"] = to.first.humanAccountID();
- tx_json["TransactionType"] = "Payment";
- tx_json["Fee"] = std::to_string(10);
- tx_json["Sequence"] = ++from.second;
- tx_json["Flags"] = tfUniversal;
- STTx tx = parseTransaction(from, tx_json);
- applyTransaction(ledger, tx);
- }
-
- void
- makePayment(TestAccount& from, TestAccount const& to,
- std::string const& currency, std::string const& amount,
- Ledger::pointer const& ledger)
- {
- Json::Value tx_json;
- tx_json["Account"] = from.first.humanAccountID();
- tx_json["Amount"] = Amount(std::stod(amount), currency, to).getJson();
- tx_json["Destination"] = to.first.humanAccountID();
- tx_json["TransactionType"] = "Payment";
- tx_json["Fee"] = std::to_string(10);
- tx_json["Sequence"] = ++from.second;
- tx_json["Flags"] = tfUniversal;
- STTx tx = parseTransaction(from, tx_json);
- applyTransaction(ledger, tx);
- }
-
- void
- createOffer(TestAccount& from, Amount const& in, Amount const& out,
- Ledger::pointer ledger)
- {
- Json::Value tx_json;
- tx_json["TransactionType"] = "OfferCreate";
- tx_json["Fee"] = std::to_string(10);
- tx_json["Account"] = from.first.humanAccountID();
- tx_json["TakerPays"] = in.getJson();
- tx_json["TakerGets"] = out.getJson();
- tx_json["Sequence"] = ++from.second;
- STTx tx = parseTransaction(from, tx_json);
- applyTransaction(ledger, tx);
- }
-
- // As currently implemented, this will cancel only the last offer made
- // from this account.
- void
- cancelOffer(TestAccount& from, Ledger::pointer ledger)
- {
- Json::Value tx_json;
- tx_json["TransactionType"] = "OfferCancel";
- tx_json["Fee"] = std::to_string(10);
- tx_json["Account"] = from.first.humanAccountID();
- tx_json["OfferSequence"] = from.second;
- tx_json["Sequence"] = ++from.second;
- STTx tx = parseTransaction(from, tx_json);
- applyTransaction(ledger, tx);
- }
-
- void
- makeTrustSet(TestAccount& from, TestAccount const& issuer,
- std::string const& currency, double amount,
- Ledger::pointer const& ledger)
- {
- Json::Value tx_json;
- tx_json["Account"] = from.first.humanAccountID();
- Json::Value& limitAmount = tx_json["LimitAmount"];
- limitAmount["currency"] = currency;
- limitAmount["issuer"] = issuer.first.humanAccountID();
- limitAmount["value"] = std::to_string(amount);
- tx_json["TransactionType"] = "TrustSet";
- tx_json["Fee"] = std::to_string(10);
- tx_json["Sequence"] = ++from.second;
- tx_json["Flags"] = tfClearNoRipple;
- STTx tx = parseTransaction(from, tx_json);
- applyTransaction(ledger, tx);
- }
-
- Ledger::pointer
- close_and_advance(Ledger::pointer ledger, Ledger::pointer LCL)
- {
- SHAMap::pointer set = ledger->peekTransactionMap();
- CanonicalTXSet retriableTransactions(set->getHash());
- Ledger::pointer newLCL = std::make_shared(false, *LCL);
- // Set up to write SHAMap changes to our database,
- // perform updates, extract changes
- applyTransactions(set, newLCL, newLCL, retriableTransactions, false);
- newLCL->updateSkipList();
- newLCL->setClosed();
- newLCL->peekAccountStateMap()->flushDirty(
- hotACCOUNT_NODE, newLCL->getLedgerSeq());
- newLCL->peekTransactionMap()->flushDirty(
- hotTRANSACTION_NODE, newLCL->getLedgerSeq());
- using namespace std::chrono;
- auto const epoch_offset = days(10957); // 2000-01-01
- std::uint32_t closeTime = time_point_cast // now
- (system_clock::now()-epoch_offset).
- time_since_epoch().count();
- int CloseResolution = seconds(LEDGER_TIME_ACCURACY).count();
- bool closeTimeCorrect = true;
- newLCL->setAccepted(closeTime, CloseResolution, closeTimeCorrect);
- return newLCL;
- }
-
- void test_genesisLedger ()
- {
- std::uint64_t const xrp = std::mega::num;
-
- // Create master account
- auto master = createAccount();
-
- // Create genesis ledger
- Ledger::pointer LCL = createGenesisLedger(100000*xrp, master);
-
- // Create open scratch ledger
- Ledger::pointer ledger = std::make_shared(false, *LCL);
-
- // Create user accounts
- auto gw1 = createAccount();
- auto gw2 = createAccount();
- auto gw3 = createAccount();
- auto alice = createAccount();
- auto mark = createAccount();
-
- // Fund gw1, gw2, gw3, alice, mark from master
- makePayment(master, gw1, 5000*xrp, ledger);
- makePayment(master, gw2, 4000*xrp, ledger);
- makePayment(master, gw3, 3000*xrp, ledger);
- makePayment(master, alice, 2000*xrp, ledger);
- makePayment(master, mark, 1000*xrp, ledger);
-
- LCL = close_and_advance(ledger, LCL);
- ledger = std::make_shared(false, *LCL);
-
- // alice trusts FOO/gw1
- makeTrustSet(alice, gw1, "FOO", 1, ledger);
-
- // mark trusts FOO/gw2
- makeTrustSet(mark, gw2, "FOO", 1, ledger);
-
- // mark trusts FOO/gw3
- makeTrustSet(mark, gw3, "FOO", 1, ledger);
-
- // gw2 pays mark with FOO
- makePayment(gw2, mark, "FOO", ".1", ledger);
-
- // gw3 pays mark with FOO
- makePayment(gw3, mark, "FOO", ".2", ledger);
-
- // gw1 pays alice with FOO
- makePayment(gw1, alice, "FOO", ".3", ledger);
-
- LCL = close_and_advance(ledger, LCL);
- ledger = std::make_shared(false, *LCL);
-
- createOffer(mark, Amount(1, "FOO", gw1), Amount(1, "FOO", gw2), ledger);
- createOffer(mark, Amount(1, "FOO", gw2), Amount(1, "FOO", gw3), ledger);
- cancelOffer(mark, ledger);
- freezeAccount(alice, ledger);
-
- LCL = close_and_advance(ledger, LCL);
- ledger = std::make_shared(false, *LCL);
-
- makePayment(alice, mark, 1*xrp, ledger);
-
- LCL = close_and_advance(ledger, LCL);
- ledger = std::make_shared(false, *LCL);
- }
-
- void test_getQuality ()
- {
- uint256 uBig (
- "D2DC44E5DC189318DB36EF87D2104CDF0A0FE3A4B698BEEE55038D7EA4C68000");
- expect (6125895493223874560 == getQuality (uBig));
- }
-public:
- void run ()
- {
- test_genesisLedger ();
- test_getQuality ();
- }
-};
-
-BEAST_DEFINE_TESTSUITE(Ledger,ripple_app,ripple);
-
-} // ripple
diff --git a/src/ripple/app/ledger/tests/Ledger_test.cpp b/src/ripple/app/ledger/tests/Ledger_test.cpp
new file mode 100644
index 000000000..70597aa52
--- /dev/null
+++ b/src/ripple/app/ledger/tests/Ledger_test.cpp
@@ -0,0 +1,149 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of rippled: https://github.com/ripple/rippled
+ Copyright (c) 2012, 2013 Ripple Labs Inc.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include
+
+namespace ripple {
+namespace test {
+
+class Ledger_test : public beast::unit_test::suite
+{
+ void test_genesisLedger (bool sign)
+ {
+ std::uint64_t const xrp = std::mega::num;
+
+ auto master = createAccount ("masterpassphrase");
+
+ Ledger::pointer LCL = createGenesisLedger(100000*xrp, master);
+
+ Ledger::pointer ledger = std::make_shared(false, *LCL);
+
+ // User accounts
+ auto gw1 = createAccount ("gw1");
+ expect (gw1.pk != master.pk, "gw1.pk != master.pk");
+ expect (gw1.sk != master.sk, "gw1.sk != master.sk");
+ auto gw2 = createAccount ("gw2");
+ auto gw3 = createAccount ("gw3");
+ auto alice = createAccount ("alice");
+ auto mark = createAccount ("mark");
+
+ // Fund gw1, gw2, gw3, alice, mark from master
+ makeAndApplyPayment(master, gw1, 5000 * xrp, ledger, sign);
+ makeAndApplyPayment(master, gw2, 4000 * xrp, ledger, sign);
+ makeAndApplyPayment(master, gw3, 3000 * xrp, ledger, sign);
+ makeAndApplyPayment(master, alice, 2000 * xrp, ledger, sign);
+ makeAndApplyPayment(master, mark, 1000 * xrp, ledger, sign);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+
+ // alice trusts FOO/gw1
+ makeTrustSet (alice, gw1, "FOO", 1, ledger, sign);
+
+ // mark trusts FOO/gw2
+ makeTrustSet (mark, gw2, "FOO", 1, ledger, sign);
+
+ // mark trusts FOO/gw3
+ makeTrustSet (mark, gw3, "FOO", 1, ledger, sign);
+
+ // gw2 pays mark with FOO
+ makeAndApplyPayment(gw2, mark, "FOO", ".1", ledger, sign);
+
+ // gw3 pays mark with FOO
+ makeAndApplyPayment(gw3, mark, "FOO", ".2", ledger, sign);
+
+ // gw1 pays alice with FOO
+ makeAndApplyPayment(gw1, alice, "FOO", ".3", ledger, sign);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+
+ createOffer (mark, Amount (1, "FOO", gw1), Amount (1, "FOO", gw2), ledger, sign);
+ createOffer (mark, Amount (1, "FOO", gw2), Amount (1, "FOO", gw3), ledger, sign);
+ cancelOffer (mark, ledger, sign);
+ freezeAccount (alice, ledger, sign);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+
+ makeAndApplyPayment(alice, mark, 1 * xrp, ledger, sign);
+
+ LCL = close_and_advance(ledger, LCL);
+ ledger = std::make_shared(false, *LCL);
+
+ pass ();
+ }
+
+ void test_unsigned_fails ()
+ {
+ std::uint64_t const xrp = std::mega::num;
+
+ auto master = createAccount ("masterpassphrase");
+
+ Ledger::pointer LCL = createGenesisLedger (100000 * xrp, master);
+
+ Ledger::pointer ledger = std::make_shared (false, *LCL);
+
+ auto gw1 = createAccount ("gw1");
+
+ auto tx = getPaymentTx(master, gw1, 5000 * xrp, false);
+
+ try
+ {
+ applyTransaction (ledger, tx, true);
+ fail ("apply unsigned transaction should fail");
+ }
+ catch (std::runtime_error const& e)
+ {
+ if (std::string (e.what()) != "r != tesSUCCESS")
+ throw std::runtime_error(e.what());
+ }
+
+ pass ();
+ }
+
+ void test_getQuality ()
+ {
+ uint256 uBig (
+ "D2DC44E5DC189318DB36EF87D2104CDF0A0FE3A4B698BEEE55038D7EA4C68000");
+ expect (6125895493223874560 == getQuality (uBig));
+
+ pass ();
+ }
+public:
+ void run ()
+ {
+ testcase ("genesisLedger signed transactions");
+ test_genesisLedger (true);
+
+ testcase ("genesisLedger unsigned transactions");
+ test_genesisLedger (false);
+
+ testcase ("unsigned invalid");
+ test_unsigned_fails ();
+
+ testcase ("getQuality");
+ test_getQuality ();
+ }
+};
+
+BEAST_DEFINE_TESTSUITE(Ledger,ripple_app,ripple);
+
+} // test
+} // ripple
diff --git a/src/ripple/app/tests/common_ledger.cpp b/src/ripple/app/tests/common_ledger.cpp
new file mode 100644
index 000000000..46f2d5fb8
--- /dev/null
+++ b/src/ripple/app/tests/common_ledger.cpp
@@ -0,0 +1,262 @@
+//------------------------------------------------------------------------------
+/*
+This file is part of rippled: https://github.com/ripple/rippled
+Copyright (c) 2012, 2013 Ripple Labs Inc.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include
+
+namespace ripple {
+namespace test {
+
+Amount::Amount(double value_, std::string currency_, TestAccount issuer_)
+ : value(value_)
+ , currency(currency_)
+ , issuer(issuer_)
+{
+}
+
+Json::Value
+Amount::getJson() const
+{
+ Json::Value tx_json;
+ tx_json["currency"] = currency;
+ tx_json["issuer"] = issuer.pk.humanAccountID();
+ tx_json["value"] = std::to_string(value);
+ return tx_json;
+}
+
+// Helper function to parse a transaction in Json, sign it with account,
+// and return it as a STTx
+STTx
+parseTransaction(TestAccount& account, Json::Value const& tx_json, bool sign)
+{
+ STParsedJSONObject parsed("tx_json", tx_json);
+ std::unique_ptr sopTrans = std::move(parsed.object);
+ if (sopTrans == nullptr)
+ throw std::runtime_error(
+ "sopTrans == nullptr");
+ sopTrans->setFieldVL(sfSigningPubKey, account.pk.getAccountPublic());
+ auto tx = STTx(*sopTrans);
+ if (sign)
+ tx.sign(account.sk);
+ return tx;
+}
+
+// Helper function to apply a transaction to a ledger
+void
+applyTransaction(Ledger::pointer const& ledger, STTx const& tx, bool check)
+{
+ TransactionEngine engine(ledger);
+ bool didApply = false;
+ auto r = engine.applyTransaction(tx, tapOPEN_LEDGER | (check ? tapNONE : tapNO_CHECK_SIGN),
+ didApply);
+ if (r != tesSUCCESS)
+ throw std::runtime_error(
+ "r != tesSUCCESS");
+ if (!didApply)
+ throw std::runtime_error(
+ "didApply");
+}
+
+// Create genesis ledger from a start amount in drops, and the public
+// master RippleAddress
+Ledger::pointer
+createGenesisLedger(std::uint64_t start_amount_drops, TestAccount const& master)
+{
+ Ledger::pointer ledger = std::make_shared(master.pk,
+ start_amount_drops);
+ ledger->updateHash();
+ ledger->setClosed();
+ if (!ledger->assertSane())
+ throw std::runtime_error(
+ "! ledger->assertSane()");
+ return ledger;
+}
+
+// Create an account represented by public RippleAddress and private
+// RippleAddress
+TestAccount
+createAccount(std::string const& passphrase)
+{
+ RippleAddress const seed
+ = RippleAddress::createSeedGeneric(passphrase);
+ RippleAddress const generator
+ = RippleAddress::createGeneratorPublic(seed);
+
+ return {
+ std::move(RippleAddress::createAccountPublic(generator, 0)),
+ std::move(RippleAddress::createAccountPrivate(generator, seed, 0)),
+ std::uint64_t(0)
+ };
+}
+
+void
+freezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign)
+{
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "AccountSet";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = account.pk.humanAccountID();
+ tx_json["SetFlag"] = asfGlobalFreeze;
+ tx_json["Sequence"] = ++account.sequence;
+ STTx tx = parseTransaction(account, tx_json, sign);
+ applyTransaction(ledger, tx, sign);
+}
+
+void
+unfreezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign)
+{
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "AccountSet";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = account.pk.humanAccountID();
+ tx_json["ClearFlag"] = asfGlobalFreeze;
+ tx_json["Sequence"] = ++account.sequence;
+ STTx tx = parseTransaction(account, tx_json, sign);
+ applyTransaction(ledger, tx, sign);
+}
+
+STTx
+getPaymentTx(TestAccount& from, TestAccount const& to,
+ std::uint64_t amountDrops,
+ bool sign)
+{
+ Json::Value tx_json;
+ tx_json["Account"] = from.pk.humanAccountID();
+ tx_json["Amount"] = std::to_string(amountDrops);
+ tx_json["Destination"] = to.pk.humanAccountID();
+ tx_json["TransactionType"] = "Payment";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Sequence"] = ++from.sequence;
+ tx_json["Flags"] = tfUniversal;
+ return parseTransaction(from, tx_json, sign);
+}
+
+STTx
+makeAndApplyPayment(TestAccount& from, TestAccount const& to,
+ std::uint64_t amountDrops,
+ Ledger::pointer const& ledger, bool sign)
+{
+ auto tx = getPaymentTx(from, to, amountDrops, sign);
+ applyTransaction(ledger, tx, sign);
+ return tx;
+}
+
+STTx
+getPaymentTx(TestAccount& from, TestAccount const& to,
+ std::string const& currency, std::string const& amount,
+ bool sign)
+{
+ Json::Value tx_json;
+ tx_json["Account"] = from.pk.humanAccountID();
+ tx_json["Amount"] = Amount(std::stod(amount), currency, to).getJson();
+ tx_json["Destination"] = to.pk.humanAccountID();
+ tx_json["TransactionType"] = "Payment";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Sequence"] = ++from.sequence;
+ tx_json["Flags"] = tfUniversal;
+ return parseTransaction(from, tx_json, sign);
+}
+
+STTx
+makeAndApplyPayment(TestAccount& from, TestAccount const& to,
+ std::string const& currency, std::string const& amount,
+ Ledger::pointer const& ledger, bool sign)
+{
+ auto tx = getPaymentTx(from, to, currency, amount, sign);
+ applyTransaction(ledger, tx, sign);
+ return tx;
+}
+
+void
+createOffer(TestAccount& from, Amount const& in, Amount const& out,
+ Ledger::pointer ledger, bool sign)
+{
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "OfferCreate";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = from.pk.humanAccountID();
+ tx_json["TakerPays"] = in.getJson();
+ tx_json["TakerGets"] = out.getJson();
+ tx_json["Sequence"] = ++from.sequence;
+ STTx tx = parseTransaction(from, tx_json, sign);
+ applyTransaction(ledger, tx, sign);
+}
+
+// As currently implemented, this will cancel only the last offer made
+// from this account.
+void
+cancelOffer(TestAccount& from, Ledger::pointer ledger, bool sign)
+{
+ Json::Value tx_json;
+ tx_json["TransactionType"] = "OfferCancel";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Account"] = from.pk.humanAccountID();
+ tx_json["OfferSequence"] = from.sequence;
+ tx_json["Sequence"] = ++from.sequence;
+ STTx tx = parseTransaction(from, tx_json, sign);
+ applyTransaction(ledger, tx, sign);
+}
+
+void
+makeTrustSet(TestAccount& from, TestAccount const& issuer,
+ std::string const& currency, double amount,
+ Ledger::pointer const& ledger, bool sign)
+{
+ Json::Value tx_json;
+ tx_json["Account"] = from.pk.humanAccountID();
+ Json::Value& limitAmount = tx_json["LimitAmount"];
+ limitAmount["currency"] = currency;
+ limitAmount["issuer"] = issuer.pk.humanAccountID();
+ limitAmount["value"] = std::to_string(amount);
+ tx_json["TransactionType"] = "TrustSet";
+ tx_json["Fee"] = std::to_string(10);
+ tx_json["Sequence"] = ++from.sequence;
+ tx_json["Flags"] = tfClearNoRipple;
+ STTx tx = parseTransaction(from, tx_json, sign);
+ applyTransaction(ledger, tx, sign);
+}
+
+Ledger::pointer
+close_and_advance(Ledger::pointer ledger, Ledger::pointer LCL)
+{
+ SHAMap::pointer set = ledger->peekTransactionMap();
+ CanonicalTXSet retriableTransactions(set->getHash());
+ Ledger::pointer newLCL = std::make_shared(false, *LCL);
+ // Set up to write SHAMap changes to our database,
+ // perform updates, extract changes
+ applyTransactions(set, newLCL, newLCL, retriableTransactions, false);
+ newLCL->updateSkipList();
+ newLCL->setClosed();
+ newLCL->peekAccountStateMap()->flushDirty(
+ hotACCOUNT_NODE, newLCL->getLedgerSeq());
+ newLCL->peekTransactionMap()->flushDirty(
+ hotTRANSACTION_NODE, newLCL->getLedgerSeq());
+ using namespace std::chrono;
+ auto const epoch_offset = days(10957); // 2000-01-01
+ std::uint32_t closeTime = time_point_cast // now
+ (system_clock::now() - epoch_offset).
+ time_since_epoch().count();
+ int closeResolution = seconds(LEDGER_TIME_ACCURACY).count();
+ bool closeTimeCorrect = true;
+ newLCL->setAccepted(closeTime, closeResolution, closeTimeCorrect);
+ return newLCL;
+}
+
+
+}
+}
\ No newline at end of file
diff --git a/src/ripple/app/tests/common_ledger.h b/src/ripple/app/tests/common_ledger.h
new file mode 100644
index 000000000..403113069
--- /dev/null
+++ b/src/ripple/app/tests/common_ledger.h
@@ -0,0 +1,126 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of rippled: https://github.com/ripple/rippled
+ Copyright (c) 2012, 2013 Ripple Labs Inc.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef RIPPLE_APP_TESTS_COMMON_LEDGER_H_INCLUDED
+#define RIPPLE_APP_TESTS_COMMON_LEDGER_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+namespace test {
+
+struct TestAccount
+{
+ RippleAddress pk;
+ RippleAddress sk;
+ unsigned sequence;
+};
+
+struct Amount
+{
+ Amount(double value_, std::string currency_, TestAccount issuer_);
+
+ Json::Value
+ getJson() const;
+
+private:
+ double value;
+ std::string currency;
+ TestAccount issuer;
+};
+
+// Helper function to parse a transaction in Json, sign it with account,
+// and return it as a STTx
+STTx
+parseTransaction(TestAccount& account, Json::Value const& tx_json, bool sign = true);
+
+// Helper function to apply a transaction to a ledger
+void
+applyTransaction(Ledger::pointer const& ledger, STTx const& tx, bool check = true);
+
+// Create genesis ledger from a start amount in drops, and the public
+// master RippleAddress
+Ledger::pointer
+createGenesisLedger(std::uint64_t start_amount_drops, TestAccount const& master);
+
+// Create an account represented by public RippleAddress and private
+// RippleAddress
+TestAccount
+createAccount(std::string const& passphrase);
+
+void
+freezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign = true);
+
+void
+unfreezeAccount(TestAccount& account, Ledger::pointer const& ledger, bool sign = true);
+
+STTx
+getPaymentTx(TestAccount& from, TestAccount const& to,
+ std::uint64_t amountDrops,
+ bool sign = true);
+
+STTx
+makeAndApplyPayment(TestAccount& from, TestAccount const& to,
+ std::uint64_t amountDrops,
+ Ledger::pointer const& ledger, bool sign = true);
+
+STTx
+getPaymentTx(TestAccount& from, TestAccount const& to,
+ std::string const& currency, std::string const& amount,
+ bool sign = true);
+
+STTx
+makeAndApplyPayment(TestAccount& from, TestAccount const& to,
+ std::string const& currency, std::string const& amount,
+ Ledger::pointer const& ledger, bool sign = true);
+
+void
+createOffer(TestAccount& from, Amount const& in, Amount const& out,
+ Ledger::pointer ledger, bool sign = true);
+
+// As currently implemented, this will cancel only the last offer made
+// from this account.
+void
+cancelOffer(TestAccount& from, Ledger::pointer ledger, bool sign = true);
+
+void
+makeTrustSet(TestAccount& from, TestAccount const& issuer,
+ std::string const& currency, double amount,
+ Ledger::pointer const& ledger, bool sign = true);
+
+Ledger::pointer
+close_and_advance(Ledger::pointer ledger, Ledger::pointer LCL);
+
+} // test
+} // ripple
+
+#endif
diff --git a/src/ripple/unity/app3.cpp b/src/ripple/unity/app3.cpp
index dc7973d6e..ba6b58c25 100644
--- a/src/ripple/unity/app3.cpp
+++ b/src/ripple/unity/app3.cpp
@@ -20,5 +20,7 @@
#include
#include
-#include
#include
+
+#include
+#include