diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index 92c1adda74..bc089866bb 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -3341,6 +3341,8 @@ + + @@ -3457,6 +3459,8 @@ + + diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 9e451707c1..4cf6a31ca8 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -4074,6 +4074,9 @@ ripple\test\jtx + + ripple\test\jtx + ripple\test\jtx @@ -4179,6 +4182,9 @@ ripple\test\jtx + + ripple\test\jtx + ripple\test\jtx diff --git a/src/ripple/test/jtx.h b/src/ripple/test/jtx.h index f6ea000276..ed8ea395ed 100644 --- a/src/ripple/test/jtx.h +++ b/src/ripple/test/jtx.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include diff --git a/src/ripple/test/jtx/JTx.h b/src/ripple/test/jtx/JTx.h index 1b3e9ad84a..b6dce761cb 100644 --- a/src/ripple/test/jtx/JTx.h +++ b/src/ripple/test/jtx/JTx.h @@ -21,9 +21,12 @@ #define RIPPLE_TEST_JTX_JTX_H_INCLUDED #include +#include #include #include #include +#include +#include namespace ripple { namespace test { @@ -46,6 +49,34 @@ struct JTx JTx() = default; +#if defined(_MSC_VER) && _MSC_VER <= 1800 + JTx(JTx&& src) + : jv(std::move(src.jv)) + , fill_fee(std::move(src.fill_fee)) + , fill_seq(std::move(src.fill_seq)) + , fill_sig(std::move(src.fill_sig)) + , signer(std::move(src.signer)) + , requires(std::move(src.requires)) + , ter(std::move(src.ter)) + , props_(std::move(src.props_)) + { + } + + JTx& operator=(JTx&& src) noexcept + { + jv = std::move(src.jv); + fill_fee = std::move(src.fill_fee); + fill_seq = std::move(src.fill_seq); + fill_sig = std::move(src.fill_sig); + signer = std::move(src.signer); + requires = std::move(src.requires); + ter = std::move(src.ter); + props_ = std::move(src.props_); + + return *this; + } +#endif + JTx (Json::Value&& jv_) : jv(std::move(jv_)) { @@ -62,6 +93,115 @@ struct JTx { return jv[key]; } + +public: + /** Return a property if it exists + + @return nullptr if the Prop does not exist + */ + /** @{ */ + template + Prop* + get() + { + for (auto& prop : props_.list) + { + if (auto test = dynamic_cast< + prop_type*>( + prop.get())) + return &test->t; + } + return nullptr; + } + + template + Prop const* + get() const + { + for (auto& prop : props_.list) + { + if (auto test = dynamic_cast< + prop_type const*>( + prop.get())) + return &test->t; + } + return nullptr; + } + /** @} */ + + /** Set a property + If the property already exists, + it is replaced. + */ + /** @{ */ + void + set(std::unique_ptr p) + { + for (auto& prop : props_.list) + { + if (prop->assignable(p.get())) + { + prop = std::move(p); + return; + } + } + props_.list.emplace_back(std::move(p)); + } + + template + void + set(Args&&... args) + { + set(std::make_unique< + prop_type>( + std::forward ( + args)...)); + } + /** @} */ + +private: + struct prop_list + { + prop_list() = default; + + prop_list(prop_list const& src) + { + for (auto const& prop : src.list) + list.emplace_back(prop->clone()); + } + + prop_list& operator=(prop_list const& src) + { + if (this != &src) + { + list.clear(); + for (auto const& prop : src.list) + list.emplace_back(prop->clone()); + } + return *this; + } + +#if defined(_MSC_VER) && _MSC_VER <= 1800 + prop_list(prop_list&& src) + : list(std::move(src.list)) + { + } + + prop_list& operator=(prop_list&& src) + { + list = std::move(src.list); + return *this; + } +#else + prop_list(prop_list&& src) = default; + prop_list& operator=(prop_list&& src) = default; +#endif + + std::vector> list; + }; + + prop_list props_; }; } // jtx diff --git a/src/ripple/test/jtx/basic_prop.h b/src/ripple/test/jtx/basic_prop.h new file mode 100644 index 0000000000..bc994c5768 --- /dev/null +++ b/src/ripple/test/jtx/basic_prop.h @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +/* + 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_BASIC_PROP_H_INCLUDED +#define RIPPLE_TEST_JTX_BASIC_PROP_H_INCLUDED + +namespace ripple { +namespace test { +namespace jtx { + +struct basic_prop +{ + virtual ~basic_prop() = default; + virtual std::unique_ptr< + basic_prop> clone() const = 0; + virtual bool assignable( + basic_prop const*) const = 0; +}; + +template +struct prop_type : basic_prop +{ + T t; + + template + prop_type(Args&&... args) + : t(std::forward (args)...) + { + } + + std::unique_ptr< + basic_prop> clone() const override + { + return std::make_unique< + prop_type>(t); + } + + bool assignable( + basic_prop const* src) const override + { + return dynamic_cast< + prop_type const*>( + src); + } +}; + +} // jtx +} // test +} // ripple + +#endif diff --git a/src/ripple/test/jtx/impl/Env.cpp b/src/ripple/test/jtx/impl/Env.cpp index a4f5df61c5..5740edca42 100644 --- a/src/ripple/test/jtx/impl/Env.cpp +++ b/src/ripple/test/jtx/impl/Env.cpp @@ -239,7 +239,7 @@ Env::autofill_sig (JTx& jt) auto const account = lookup(jv[jss::Account].asString()); auto const ar = le(account); - if (ar->isFieldPresent(sfRegularKey)) + if (ar && ar->isFieldPresent(sfRegularKey)) jtx::sign(jv, lookup( ar->getFieldAccount160(sfRegularKey))); else diff --git a/src/ripple/test/jtx/impl/Env_test.cpp b/src/ripple/test/jtx/impl/Env_test.cpp index def29388be..98ed35ac13 100644 --- a/src/ripple/test/jtx/impl/Env_test.cpp +++ b/src/ripple/test/jtx/impl/Env_test.cpp @@ -414,6 +414,106 @@ public: Env env(*this); } + void testJTxProperties() + { + using namespace jtx; + JTx jt1; + // Test a straightforward + // property + expect(!jt1.get()); + jt1.set(7); + expect(jt1.get()); + expect(*jt1.get() == 7); + expect(!jt1.get()); + + // Test that the property is + // replaced if it exists. + jt1.set(17); + expect(jt1.get()); + expect(*jt1.get() == 17); + expect(!jt1.get()); + + // Test that modifying the + // returned prop is saved + *jt1.get() = 42; + expect(jt1.get()); + expect(*jt1.get() == 42); + expect(!jt1.get()); + + // Test get() const + auto const& jt2 = jt1; + expect(jt2.get()); + expect(*jt2.get() == 42); + expect(!jt2.get()); + } + + void testProp() + { + using namespace jtx; + Env env(*this); + env.memoize("alice"); + + auto jt1 = env.jt(noop("alice")); + expect(!jt1.get()); + + auto jt2 = env.jt(noop("alice"), + prop(-1)); + expect(jt2.get()); + expect(*jt2.get() == + 65535); + + auto jt3 = env.jt(noop("alice"), + prop( + "Hello, world!"), + prop(false)); + expect(jt3.get()); + expect(*jt3.get() == + "Hello, world!"); + expect(jt3.get()); + expect(!*jt3.get()); + } + + void testJTxCopy() + { + using namespace jtx; + JTx jt1; + jt1.set(7); + expect(jt1.get()); + expect(*jt1.get() == 7); + expect(!jt1.get()); + JTx jt2(jt1); + expect(jt2.get()); + expect(*jt2.get() == 7); + expect(!jt2.get()); + JTx jt3; + jt3 = jt1; + expect(jt3.get()); + expect(*jt3.get() == 7); + expect(!jt3.get()); + } + + void testJTxMove() + { + using namespace jtx; + JTx jt1; + jt1.set(7); + expect(jt1.get()); + expect(*jt1.get() == 7); + expect(!jt1.get()); + JTx jt2(std::move(jt1)); + expect(!jt1.get()); + expect(!jt1.get()); + expect(jt2.get()); + expect(*jt2.get() == 7); + expect(!jt2.get()); + jt1 = std::move(jt2); + expect(!jt2.get()); + expect(!jt2.get()); + expect(jt1.get()); + expect(*jt1.get() == 7); + expect(!jt1.get()); + } + void testMemo() { @@ -447,6 +547,10 @@ public: testMultiSign(); testMultiSign2(); testTicket(); + testJTxProperties(); + testProp(); + testJTxCopy(); + testJTxMove(); testMemo(); } }; diff --git a/src/ripple/test/jtx/impl/utility.cpp b/src/ripple/test/jtx/impl/utility.cpp index 722700951a..321571cc34 100644 --- a/src/ripple/test/jtx/impl/utility.cpp +++ b/src/ripple/test/jtx/impl/utility.cpp @@ -76,6 +76,9 @@ fill_seq (Json::Value& jv, auto const ar = ledger.fetch( getAccountRootIndex(ra.getAccountID())); + if (!ar) + return; + jv[jss::Sequence] = ar->getFieldU32(sfSequence); } diff --git a/src/ripple/test/jtx/prop.h b/src/ripple/test/jtx/prop.h new file mode 100644 index 0000000000..f5a7384e71 --- /dev/null +++ b/src/ripple/test/jtx/prop.h @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +/* + 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_PROP_H_INCLUDED +#define RIPPLE_TEST_JTX_PROP_H_INCLUDED + +#include +#include // + +namespace ripple { +namespace test { +namespace jtx { + +/** Set a property on a JTx. */ +template +struct prop +{ + std::unique_ptr p_; + + template + prop(Args&&... args) + : p_(std::make_unique< + prop_type>( + std::forward ( + args)...)) + { + } + + void + operator()(Env const& env, JTx& jt) const + { + jt.set(p_->clone()); + } +}; + +} // jtx +} // test +} // ripple + +#endif