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