diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index 39e36e52fc..92c1adda74 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -3375,6 +3375,14 @@ True True + + True + True + + + True + True + True True @@ -3431,8 +3439,12 @@ True True + + + + diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 5d4913dde1..9e451707c1 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -4104,6 +4104,12 @@ ripple\test\jtx\impl + + ripple\test\jtx\impl + + + ripple\test\jtx\impl + ripple\test\jtx\impl @@ -4146,9 +4152,15 @@ ripple\test\jtx\impl + + ripple\test\jtx + ripple\test\jtx + + ripple\test\jtx + ripple\test\jtx diff --git a/src/ripple/test/jtx.h b/src/ripple/test/jtx.h index 0c8784fb16..f6ea000276 100644 --- a/src/ripple/test/jtx.h +++ b/src/ripple/test/jtx.h @@ -28,7 +28,9 @@ #include #include #include +#include #include +#include #include #include #include diff --git a/src/ripple/test/jtx/Env.h b/src/ripple/test/jtx/Env.h index 34cff51f16..7f203de1f1 100644 --- a/src/ripple/test/jtx/Env.h +++ b/src/ripple/test/jtx/Env.h @@ -125,6 +125,22 @@ public: public: Env (beast::unit_test::suite& test_); + + /** Turn on JSON tracing. + With no arguments, trace all + */ + void + trace(int howMany = -1) + { + trace_ = howMany; + } + + /** Turn off JSON tracing. */ + void + notrace() + { + trace_ = 0; + } /** Associate AccountID with account. */ void @@ -310,6 +326,17 @@ public: These convenience functions are for easy set-up of the environment, they bypass fee, seq, and sig settings. + + Preconditions: + The account must already exist + + Effects: + A trust line is added for the account. + The account's sequence number is incremented. + The account is refunded for the transaction fee + to set the trust line. + + The refund comes from the master account. */ /** @{ */ void @@ -327,6 +354,8 @@ public: /** @} */ protected: + int trace_ = 0; + void autofill_sig (JTx& jt); diff --git a/src/ripple/test/jtx/amount.h b/src/ripple/test/jtx/amount.h index a63dd5a904..8ab4db930c 100644 --- a/src/ripple/test/jtx/amount.h +++ b/src/ripple/test/jtx/amount.h @@ -167,10 +167,12 @@ struct XRP_t PrettyAmount operator()(T v) const { - return { v * - dropsPerXRP::value }; + return { std::conditional_t< + std::is_signed::value, + std::int64_t, std::uint64_t>{v} * + dropsPerXRP::value }; } - + PrettyAmount operator()(double v) const { diff --git a/src/ripple/test/jtx/impl/Env.cpp b/src/ripple/test/jtx/impl/Env.cpp index 97c6162b5a..a4f5df61c5 100644 --- a/src/ripple/test/jtx/impl/Env.cpp +++ b/src/ripple/test/jtx/impl/Env.cpp @@ -175,10 +175,17 @@ void Env::trust (STAmount const& amount, Account const& account) { + auto const start = balance(account); apply(jtx::trust(account, amount), jtx::seq(jtx::autofill), fee(jtx::autofill), sig(jtx::autofill)); + apply(pay(master, account, + drops(ledger->getBaseFee())), + jtx::seq(jtx::autofill), + fee(jtx::autofill), + sig(jtx::autofill)); + test.expect(balance(account) == start); } void @@ -211,6 +218,12 @@ Env::submit (JTx const& jt) // we didn't get the expected result. return; } + if (trace_) + { + if (trace_ > 0) + --trace_; + test.log << pretty(jt.jv); + } for (auto const& f : jt.requires) f(*this); } @@ -243,7 +256,17 @@ Env::autofill (JTx& jt) if(jt.fill_seq) jtx::fill_seq(jv, *ledger); // Must come last - autofill_sig(jt); + try + { + autofill_sig(jt); + } + catch (parse_error const&) + { + test.log << + "parse failed:\n" << + pretty(jv); + throw; + } } std::shared_ptr diff --git a/src/ripple/test/jtx/impl/Env_test.cpp b/src/ripple/test/jtx/impl/Env_test.cpp index ef4ea7074c..def29388be 100644 --- a/src/ripple/test/jtx/impl/Env_test.cpp +++ b/src/ripple/test/jtx/impl/Env_test.cpp @@ -110,6 +110,7 @@ public: expect(to_string(XRP(.80)) == "0.8 XRP"); expect(to_string(XRP(.005)) == "5000 drops"); expect(to_string(XRP(0.1)) == "0.1 XRP"); + expect(to_string(XRP(10000)) == "10000 XRP"); expect(to_string(drops(10)) == "10 drops"); expect(to_string(drops(123400000)) == "123.4 XRP"); expect(to_string(XRP(-5)) == "-5 XRP"); @@ -226,7 +227,7 @@ public: env.fund(XRP(10000), "alice", gw); env.require(balance("alice", USD(none))); env.trust(USD(100), "alice"); - env.require(balance("alice", XRP(10000) - drops(10))); + env.require(balance("alice", XRP(10000))); // fee refunded env.require(balance("alice", USD(0))); env(pay(gw, "alice", USD(10)), require(balance("alice", USD(10)))); @@ -413,6 +414,22 @@ public: Env env(*this); } + void + testMemo() + { + using namespace jtx; + Env env(*this); + env.fund(XRP(10000), "alice"); + env(noop("alice"), memodata("data")); + env(noop("alice"), memoformat("format")); + env(noop("alice"), memotype("type")); + env(noop("alice"), memondata("format", "type")); + env(noop("alice"), memonformat("data", "type")); + env(noop("alice"), memontype("data", "format")); + env(noop("alice"), memo("data", "format", "type")); + env(noop("alice"), memo("data1", "format1", "type1"), memo("data2", "format2", "type2")); + } + void run() { @@ -430,6 +447,7 @@ public: testMultiSign(); testMultiSign2(); testTicket(); + testMemo(); } }; diff --git a/src/ripple/test/jtx/impl/json.cpp b/src/ripple/test/jtx/impl/json.cpp new file mode 100644 index 0000000000..f67187c396 --- /dev/null +++ b/src/ripple/test/jtx/impl/json.cpp @@ -0,0 +1,47 @@ +//------------------------------------------------------------------------------ +/* + 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 + +namespace ripple { +namespace test { +namespace jtx { + +json::json(std::string const& s) +{ + if (! Json::Reader().parse(s, jv_)) + throw parse_error("bad json"); + +} + +void +json::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + for (auto iter = jv_.begin(); + iter != jv_.end(); ++iter) + jv[iter.key().asString()] = *iter; +} + +} // jtx +} // test +} // ripple diff --git a/src/ripple/test/jtx/impl/memo.cpp b/src/ripple/test/jtx/impl/memo.cpp new file mode 100644 index 0000000000..0b0e799580 --- /dev/null +++ b/src/ripple/test/jtx/impl/memo.cpp @@ -0,0 +1,107 @@ +//------------------------------------------------------------------------------ +/* + 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 + +namespace ripple { +namespace test { +namespace jtx { + +void +memo::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + auto& ma = jv["Memos"]; + auto& mi = ma[ma.size()]; + auto& m = mi["Memo"]; + m["MemoData"] = strHex(data_); + m["MemoFormat"] = strHex(format_); + m["MemoType"] = strHex(type_); +} + +void +memodata::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + auto& ma = jv["Memos"]; + auto& mi = ma[ma.size()]; + auto& m = mi["Memo"]; + m["MemoData"] = strHex(s_); +} + +void +memoformat::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + auto& ma = jv["Memos"]; + auto& mi = ma[ma.size()]; + auto& m = mi["Memo"]; + m["MemoFormat"] = strHex(s_); +} + +void +memotype::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + auto& ma = jv["Memos"]; + auto& mi = ma[ma.size()]; + auto& m = mi["Memo"]; + m["MemoType"] = strHex(s_); +} + +void +memondata::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + auto& ma = jv["Memos"]; + auto& mi = ma[ma.size()]; + auto& m = mi["Memo"]; + m["MemoFormat"] = strHex(format_); + m["MemoType"] = strHex(type_); +} + +void +memonformat::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + auto& ma = jv["Memos"]; + auto& mi = ma[ma.size()]; + auto& m = mi["Memo"]; + m["MemoData"] = strHex(data_); + m["MemoType"] = strHex(type_); +} + +void +memontype::operator()(Env const&, JTx& jt) const +{ + auto& jv = jt.jv; + auto& ma = jv["Memos"]; + auto& mi = ma[ma.size()]; + auto& m = mi["Memo"]; + m["MemoData"] = strHex(data_); + m["MemoFormat"] = strHex(format_); +} + + +} // jtx +} // test +} // ripple diff --git a/src/ripple/test/jtx/json.h b/src/ripple/test/jtx/json.h new file mode 100644 index 0000000000..c25c3e4923 --- /dev/null +++ b/src/ripple/test/jtx/json.h @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +/* + 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_TEST_JTX_JSON_H_INCLUDED +#define RIPPLE_TEST_JTX_JSON_H_INCLUDED + +#include +#include + +namespace ripple { +namespace test { +namespace jtx { + +/** Inject raw JSON. */ +class json +{ +private: + Json::Value jv_; + +public: + explicit + json (std::string const&); + + void + operator()(Env const&, JTx& jt) const; +}; + +} // jtx +} // test +} // ripple + +#endif diff --git a/src/ripple/test/jtx/memo.h b/src/ripple/test/jtx/memo.h new file mode 100644 index 0000000000..84031d5c99 --- /dev/null +++ b/src/ripple/test/jtx/memo.h @@ -0,0 +1,159 @@ +//------------------------------------------------------------------------------ +/* + 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_TEST_JTX_MEMO_H_INCLUDED +#define RIPPLE_TEST_JTX_MEMO_H_INCLUDED + +#include +#include + +namespace ripple { +namespace test { +namespace jtx { + +/** Add a memo to a JTx. + + If a memo already exists, the new + memo is appended to the array. +*/ +class memo +{ +private: + std::string data_; + std::string format_; + std::string type_; + +public: + memo (std::string const& data, + std::string const& format, + std::string const& type) + : data_(data) + , format_(format) + , type_(type) + { + } + + void + operator()(Env const&, JTx& jt) const; +}; + +class memodata +{ +private: + std::string s_; + +public: + memodata (std::string const& s) + : s_(s) + { + } + + void + operator()(Env const&, JTx& jt) const; +}; + +class memoformat +{ +private: + std::string s_; + +public: + memoformat (std::string const& s) + : s_(s) + { + } + + void + operator()(Env const&, JTx& jt) const; +}; + +class memotype +{ +private: + std::string s_; + +public: + memotype (std::string const& s) + : s_(s) + { + } + + void + operator()(Env const&, JTx& jt) const; +}; + +class memondata +{ +private: + std::string format_; + std::string type_; + +public: + memondata (std::string const& format, + std::string const& type) + : format_(format) + , type_(type) + { + } + + void + operator()(Env const&, JTx& jt) const; +}; + +class memonformat +{ +private: + std::string data_; + std::string type_; + +public: + memonformat (std::string const& data, + std::string const& type) + : data_(data) + , type_(type) + { + } + + void + operator()(Env const&, JTx& jt) const; +}; + +class memontype +{ +private: + std::string data_; + std::string format_; + +public: + memontype (std::string const& data, + std::string const& format) + : data_(data) + , format_(format) + { + } + + void + operator()(Env const&, JTx& jt) const; +}; + +} // jtx +} // test +} // ripple + +#endif diff --git a/src/ripple/unity/test.cpp b/src/ripple/unity/test.cpp index dec9e16596..8429b9c47c 100644 --- a/src/ripple/unity/test.cpp +++ b/src/ripple/unity/test.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include