Improvements to jtx framework:

This adds "require" functionality which allows invariants
to be checked after processing transactions using a simple,
terse interface. Also adds more comprehensive test coverage
for the framework itself, verifying that the more sophisticated
language constructs work in all ways.

All functions and classes have been split up into individual
files which may be included a-la carte, or accessed through
a single convenience header <ripple/test/jtx.h>

* Move, rename all sources
* Put everything in the jtx namespace
* Add sendmax funclet
* Rename funclet to paths
* Correctly set input issue and destination amount in path
* Conditionally invoke funclets using is_call_possible
* Add any() function means "any currency they will accept"
* Add None, none modifiers on amounts to mean "no amount"
* Add require conditions to JTx
* Add Env::require variadic condition checker
* Add le, rename some items for consistency
* Add require functors, balance, flags, nflags
* Add require functors lines, owners, offers, tickets
* Add ticket example of extending the system
* Add noripple modifier for funding accounst
* Add Env::st to parse Json into STTx
* Add tests to ensure correctness of fund()
* Add virtual Env member hooks
* Add Env::balance
* Add Env::seq
* Add PrettyAmount
* Add all container Account support
* IOU and XRP return PrettyAmount amounts
* IOUs print the issuer's name instead of base58
* Fix int and double conversions to XRP
* Fix autofill of Env::fund with noripple
This commit is contained in:
Vinnie Falco
2015-06-09 14:56:21 -07:00
committed by Nik Bougalis
parent 4f34724c5a
commit 189592938a
59 changed files with 4822 additions and 1791 deletions

View File

@@ -559,6 +559,8 @@
</ClInclude>
<ClInclude Include="..\..\src\beast\beast\intrusive\LockFreeStack.h">
</ClInclude>
<ClInclude Include="..\..\src\beast\beast\is_call_possible.h">
</ClInclude>
<ClInclude Include="..\..\src\beast\beast\Memory.h">
</ClInclude>
<ClCompile Include="..\..\src\beast\beast\module\asio\asio.unity.cpp">
@@ -1714,28 +1716,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\paths\Types.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tests\Common.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\tests\Common.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tests\Env.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\tests\Env.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tests\Env_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\tests\JTx.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\tests\JTx.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\BookTip.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -3345,6 +3325,144 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\shamap\TreeNodeCache.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\Account.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\amount.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\balance.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\Env.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\fee.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\flags.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Account.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\amount.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\balance.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Env.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Env_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\fee.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\flags.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\multisign.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\offer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\owners.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\paths.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\pay.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\rate.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\regkey.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\sendmax.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\seq.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\sig.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\ticket.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\trust.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\txflags.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\utility.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\test\jtx\JTx.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\multisign.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\noop.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\offer.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\owners.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\paths.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\pay.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\rate.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\regkey.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\require.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\requires.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\sendmax.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\seq.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\sig.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\tags.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\ter.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\ticket.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\trust.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\txflags.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\utility.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\unity\app_ledger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
@@ -3361,10 +3479,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\app_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\app_tx.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
@@ -3463,6 +3577,10 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release|x64'">..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\validators.cpp">
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\websocket02.cpp">

View File

@@ -274,9 +274,6 @@
<Filter Include="ripple\app\paths\tests">
<UniqueIdentifier>{1025719B-6A8F-D9FB-A6BA-02B93756DE09}</UniqueIdentifier>
</Filter>
<Filter Include="ripple\app\tests">
<UniqueIdentifier>{2E791662-6ED0-D1E1-03A4-0CB35473EC56}</UniqueIdentifier>
</Filter>
<Filter Include="ripple\app\tx">
<UniqueIdentifier>{50FDCDC1-EC9C-9F3B-34C9-EF4137E132B4}</UniqueIdentifier>
</Filter>
@@ -412,6 +409,15 @@
<Filter Include="ripple\shamap\tests">
<UniqueIdentifier>{F0AEA72D-7030-C8C7-1E34-1029BBD56886}</UniqueIdentifier>
</Filter>
<Filter Include="ripple\test">
<UniqueIdentifier>{B25F5854-84AE-1CBD-DFFC-6515DD055652}</UniqueIdentifier>
</Filter>
<Filter Include="ripple\test\jtx">
<UniqueIdentifier>{A21A3B94-5C44-3746-4F10-6FF8FF990CE3}</UniqueIdentifier>
</Filter>
<Filter Include="ripple\test\jtx\impl">
<UniqueIdentifier>{27D70888-7145-691C-0E0A-E511EB3A80A2}</UniqueIdentifier>
</Filter>
<Filter Include="ripple\unity">
<UniqueIdentifier>{5DB3CD0B-B361-B301-9562-697CA8A52B68}</UniqueIdentifier>
</Filter>
@@ -1056,6 +1062,9 @@
<ClInclude Include="..\..\src\beast\beast\intrusive\LockFreeStack.h">
<Filter>beast\intrusive</Filter>
</ClInclude>
<ClInclude Include="..\..\src\beast\beast\is_call_possible.h">
<Filter>beast</Filter>
</ClInclude>
<ClInclude Include="..\..\src\beast\beast\Memory.h">
<Filter>beast</Filter>
</ClInclude>
@@ -2427,27 +2436,6 @@
<ClInclude Include="..\..\src\ripple\app\paths\Types.h">
<Filter>ripple\app\paths</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tests\Common.cpp">
<Filter>ripple\app\tests</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\tests\Common.h">
<Filter>ripple\app\tests</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tests\Env.cpp">
<Filter>ripple\app\tests</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\tests\Env.h">
<Filter>ripple\app\tests</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tests\Env_test.cpp">
<Filter>ripple\app\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\app\tests\JTx.cpp">
<Filter>ripple\app\tests</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\tests\JTx.h">
<Filter>ripple\app\tests</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\tx\impl\BookTip.cpp">
<Filter>ripple\app\tx\impl</Filter>
</ClCompile>
@@ -4065,6 +4053,150 @@
<ClInclude Include="..\..\src\ripple\shamap\TreeNodeCache.h">
<Filter>ripple\shamap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx.h">
<Filter>ripple\test</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\Account.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\amount.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\balance.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\Env.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\fee.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\flags.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Account.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\amount.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\balance.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Env.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\Env_test.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\fee.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\flags.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\multisign.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\offer.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\owners.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\paths.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\pay.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\rate.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\regkey.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\sendmax.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\seq.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\sig.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\ticket.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\trust.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\txflags.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\test\jtx\impl\utility.cpp">
<Filter>ripple\test\jtx\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\test\jtx\JTx.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\multisign.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\noop.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\offer.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\owners.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\paths.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\pay.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\rate.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\regkey.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\require.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\requires.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\sendmax.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\seq.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\sig.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\tags.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\ter.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\ticket.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\trust.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\txflags.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\test\jtx\utility.h">
<Filter>ripple\test\jtx</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\unity\app_ledger.cpp">
<Filter>ripple\unity</Filter>
</ClCompile>
@@ -4077,9 +4209,6 @@
<ClCompile Include="..\..\src\ripple\unity\app_paths.cpp">
<Filter>ripple\unity</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\app_tests.cpp">
<Filter>ripple\unity</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\app_tx.cpp">
<Filter>ripple\unity</Filter>
</ClCompile>
@@ -4161,6 +4290,9 @@
<ClCompile Include="..\..\src\ripple\unity\soci_ripple.cpp">
<Filter>ripple\unity</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\test.cpp">
<Filter>ripple\unity</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\validators.cpp">
<Filter>ripple\unity</Filter>
</ClCompile>

View File

@@ -664,6 +664,7 @@ def get_classic_sources():
append_sources(result, *list_sources('src/ripple/peerfinder', '.cpp'))
append_sources(result, *list_sources('src/ripple/protocol', '.cpp'))
append_sources(result, *list_sources('src/ripple/shamap', '.cpp'))
append_sources(result, *list_sources('src/ripple/test', '.cpp'))
append_sources(
result,
*list_sources('src/ripple/nodestore', '.cpp'),
@@ -685,7 +686,6 @@ def get_unity_sources():
'src/ripple/unity/app_main.cpp',
'src/ripple/unity/app_misc.cpp',
'src/ripple/unity/app_paths.cpp',
'src/ripple/unity/app_tests.cpp',
'src/ripple/unity/app_tx.cpp',
'src/ripple/unity/core.cpp',
'src/ripple/unity/basics.cpp',
@@ -696,6 +696,7 @@ def get_unity_sources():
'src/ripple/unity/json.cpp',
'src/ripple/unity/protocol.cpp',
'src/ripple/unity/shamap.cpp',
'src/ripple/unity/test.cpp',
)
result += get_soci_sources('unity')

View File

@@ -1,107 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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 <BeastConfig.h>
#include <ripple/app/tests/Common.h>
#include <ripple/protocol/SystemParameters.h>
namespace ripple {
namespace test {
namespace detail {
STAmount
XRP_t::operator()(double v) const
{
if (v < 0)
return STAmount(std::uint64_t(
-v * SYSTEM_CURRENCY_PARTS), true);
return STAmount(std::uint64_t(
v * SYSTEM_CURRENCY_PARTS), false);
}
} // detail
detail::XRP_t XRP;
STAmount
IOU::operator()(double v) const
{
return amountFromString(issue_,
std::to_string(v));
}
//------------------------------------------------------------------------------
#ifdef _MSC_VER
Account::Account (Account&& other)
: name_(std::move(other.name_))
, pk_(std::move(other.pk_))
, sk_(std::move(other.sk_))
, id_(std::move(other.id_))
, human_(std::move(other.human_))
{
}
Account&
Account::operator= (Account&& rhs)
{
name_ = std::move(rhs.name_);
pk_ = std::move(rhs.pk_);
sk_ = std::move(rhs.sk_);
id_ = std::move(rhs.id_);
human_ = std::move(rhs.human_);
return *this;
}
#endif
Account::Account(
std::string name, KeyPair&& keys)
: name_(std::move(name))
{
pk_ = std::move(keys.publicKey);
sk_ = std::move(keys.secretKey);
id_ = pk_.getAccountID();
human_ = pk_.humanAccountID();
}
Account::Account (std::string name,
KeyType type)
#ifndef _MSC_VER
: Account(name,
#else
// Fails on Clang and possibly gcc
: Account(std::move(name),
#endif
generateKeysFromSeed(type,
RippleAddress::createSeedGeneric(
name)))
{
}
IOU
Account::operator[](std::string const& s) const
{
auto const currency = to_currency(s);
assert(currency != noCurrency());
return IOU(Issue(currency, id()));
}
} // test
} // ripple

View File

@@ -1,217 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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 <BeastConfig.h>
#include <ripple/app/tests/Env.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/app/tx/TransactionEngine.h>
#include <ripple/basics/Slice.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/protocol/LedgerFormats.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/STParsedJSON.h>
#include <ripple/protocol/SystemParameters.h>
#include <ripple/protocol/TER.h>
#include <ripple/protocol/TxFlags.h>
// VFALCO TODO Use AnyPublicKey, AnySecretKey, AccountID
namespace ripple {
namespace test {
STAmount
AccountInfo::balance(
Issue const& issue) const
{
if (! root_)
return STAmount(issue, 0, 0);
if (isXRP(issue))
return root_->getFieldAmount(sfBalance);
auto amount = ledger_->fetch(getRippleStateIndex(
account_, issue.account,
issue.currency))->getFieldAmount(sfBalance);
amount.setIssuer(issue.account);
if (account_.id() > issue.account)
amount.negate();
return amount;
}
std::uint32_t
AccountInfo::seq() const
{
return root_->getFieldU32(sfSequence);
}
std::uint32_t
AccountInfo::flags() const
{
return root_->getFieldU32(sfFlags);
}
//------------------------------------------------------------------------------
Env::Env (beast::unit_test::suite& test_)
: test(test_)
, master("master", generateKeysFromSeed(
KeyType::secp256k1, RippleAddress::createSeedGeneric(
"masterpassphrase")))
{
memoize(master);
initializePathfinding();
ledger = std::make_shared<Ledger>(
master.pk(), SYSTEM_CURRENCY_START);
}
void
Env::memoize (Account const& account)
{
map_.emplace(account.id(), account);
}
Account const&
Env::lookup (std::string const& base58ID) const
{
RippleAddress ra;
if (! ra.setAccountID(base58ID))
throw std::runtime_error(
"Env::lookup: invalid account ID");
return lookup(ra.getAccountID());
}
Account const&
Env::lookup (ripple::Account const& id) const
{
auto const iter = map_.find(id);
if (iter == map_.end())
throw std::runtime_error(
"Env::lookup:: unknown account ID");
return iter->second;
}
void
Env::fund (STAmount const& amount,
Account const& account)
{
using namespace jtx;
memoize(account);
apply(pay(master, account, amount),
seq(jtx::autofill),
fee(jtx::autofill),
sig(jtx::autofill));
}
void
Env::trust (STAmount const& amount,
Account const& account)
{
using namespace jtx;
apply(jtx::trust(account, amount),
seq(jtx::autofill),
fee(jtx::autofill),
sig(jtx::autofill));
}
void
Env::submit (JTx const& tx)
{
boost::optional<STTx> stx;
{
// The parse must succeed, since we
// generated the JSON ourselves.
boost::optional<STObject> st;
try
{
st = jtx::parse(tx.jv);
}
catch(jtx::parse_error const&)
{
test.log << pretty(tx.jv);
throw;
}
try
{
stx.emplace(std::move(*st));
}
catch(...)
{
}
}
TER ter;
bool didApply;
if (stx)
{
TransactionEngine txe (ledger,
tx_enable_test);
std::tie(ter, didApply) = txe.applyTransaction(
*stx, tapOPEN_LEDGER |
(true ? tapNONE : tapNO_CHECK_SIGN));
}
else
{
// Convert the exception into a TER so that
// callers can expect it using ter(temMALFORMED)
ter = temMALFORMED;
didApply = false;
}
if (! test.expect(ter == tx.ter,
"apply: " + transToken(ter) +
" (" + transHuman(ter) + ")"))
test.log << pretty(tx.jv);
}
void
Env::autofill (JTx& jt)
{
auto& jv = jt.jv;
auto const should = [](boost::tribool v, bool b)
{
if (boost::indeterminate(v))
return b;
return bool(v);
};
if(should(jt.fill_fee, fill_fee_))
jtx::fill_fee(jv, *ledger);
if(should(jt.fill_seq, fill_seq_))
jtx::fill_seq(jv, *ledger);
// Must come last
if (jt.signer)
jt.signer(*this, jt);
else if(should(jt.fill_sig, fill_sig_))
{
auto const account =
lookup(jv[jss::Account].asString());
auto const ar =
ledger->fetch(getAccountRootIndex(account));
if (ar->isFieldPresent(sfRegularKey))
jtx::sign(jv, lookup(
ar->getFieldAccount160(sfRegularKey)));
else
jtx::sign(jv, account);
}
}
} // test
} // ripple

View File

@@ -1,258 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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_ENV_H_INCLUDED
#define RIPPLE_APP_TESTS_ENV_H_INCLUDED
#include <ripple/app/tests/Common.h>
#include <ripple/app/tests/JTx.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/json/json_value.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/STTx.h>
#include <beast/unit_test/suite.h>
#include <boost/logic/tribool.hpp>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <utility>
#include <unordered_map>
namespace ripple {
namespace test {
/** A view to an account's account root. */
class AccountInfo
{
private:
Account account_;
std::shared_ptr<Ledger> ledger_;
std::shared_ptr<SLE const> root_;
public:
AccountInfo(Account const& account,
std::shared_ptr<Ledger> ledger)
: account_(account)
, ledger_(std::move(ledger))
, root_(ledger_->fetch(
getAccountRootIndex(account.id())))
{
}
STAmount
balance (Issue const& issue) const;
std::uint32_t
seq() const;
std::uint32_t
flags() const;
};
//------------------------------------------------------------------------------
/** A transaction testing environment. */
class Env
{
public:
beast::unit_test::suite& test;
/** The master account. */
Account const master;
/** The open ledger. */
std::shared_ptr<Ledger> ledger;
public:
Env (beast::unit_test::suite& test_);
/** Associate AccountID with account. */
void
memoize (Account const& account);
/** Returns the Account given the AccountID. */
/** @{ */
Account const&
lookup (std::string const& base58ID) const;
Account const&
lookup (ripple::Account const& id) const;
/** @} */
/** Returns info on an Account. */
/** @{ */
AccountInfo
info (Account const& account) const
{
return AccountInfo(account, ledger);
}
AccountInfo
operator[](Account const& account) const
{
return info(account);
}
/** @} */
void auto_fee (bool value)
{
fill_fee_ = value;
}
void auto_seq (bool value)
{
fill_seq_ = value;
}
void auto_sig (bool value)
{
fill_sig_ = value;
}
/** Create a JTx from parameters. */
template <class JsonValue,
class... FN>
JTx
tx (JsonValue&& jv, FN const&... fN)
{
JTx jt(std::forward<JsonValue>(jv));
invoke(jt, fN...);
autofill(jt);
return jt;
}
/** Create JSON from parameters.
This will apply funclets and autofill.
*/
template <class JsonValue,
class... FN>
Json::Value
json (JsonValue&&jv, FN const&... fN)
{
auto jt = tx(
std::forward<JsonValue>(jv),
fN...);
return std::move(jt.jv);
}
/** Submit an existing JTx. */
void
submit (JTx const& tx);
/** Apply funclets and submit. */
/** @{ */
template <class JsonValue, class... FN>
void
apply (JsonValue&& jv, FN const&... fN)
{
submit(tx(std::forward<
JsonValue>(jv), fN...));
}
template <class JsonValue,
class... FN>
void
operator()(JsonValue&& jv,
FN const&... fN)
{
apply(std::forward<
JsonValue>(jv), fN...);
}
/** @} */
/** Create a new account with some XRP.
These convenience functions are for easy set-up
of the environment, they bypass fee, seq, and sig
settings. The XRP is transferred from the master
account.
@param amount The amount of XRP to transfer.
*/
/** @{ */
void
fund (STAmount const& amount, Account const& account);
template<class... Accounts>
void
fund (STAmount const& amount, Account const& account0,
Account const& account1, Accounts const&... accountN)
{
fund(amount, account0);
fund(amount, account1, accountN...);
}
/** @} */
/** Establish trust lines.
These convenience functions are for easy set-up
of the environment, they bypass fee, seq, and sig
settings.
*/
/** @{ */
void
trust (STAmount const& amount,
Account const& account);
template<class... Accounts>
void
trust (STAmount const& amount, Account const& to0,
Account const& to1, Accounts const&... toN)
{
trust(amount, to0);
trust(amount, to1, toN...);
}
/** @} */
private:
void
autofill (JTx& jt);
inline
void
invoke (JTx&)
{
}
// Invoke funclets on tx
template <class F, class... FN>
void
invoke (JTx& tx, F const& f,
FN const&... fN)
{
f(*this, tx);
invoke(tx, fN...);
}
// Map of account IDs to Account
std::unordered_map<
ripple::Account, Account> map_;
bool fill_fee_ = true;
bool fill_seq_ = true;
bool fill_sig_ = true;
};
} // test
} // ripple
#endif

View File

@@ -1,212 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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 <BeastConfig.h>
#include <ripple/app/tests/Env.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/TxFlags.h>
#include <beast/unit_test/suite.h>
namespace ripple {
namespace test {
class Env_test : public beast::unit_test::suite
{
public:
void
testAutofill()
{
using namespace jtx;
Env env(*this);
env.fund(XRP(10000), "alice", "bob");
env(noop("alice"));
env(noop("alice"), seq(none), fee(10), ter(temMALFORMED));
env(noop("alice"), fee(none), ter(temMALFORMED));
}
// Signing with secp256k1 and ed25519 keys
void
testKeyType()
{
using namespace jtx;
Env env(*this);
Account const alice("alice", KeyType::ed25519);
Account const bob("bob", KeyType::secp256k1);
Account const carol("carol");
env.fund(XRP(10000), alice, bob);
// Master key only
env(noop(alice));
env(noop(bob));
env(noop(alice), sig("alice"), ter(tefBAD_AUTH_MASTER));
env(noop(alice), sig(Account("alice",
KeyType::secp256k1)), ter(tefBAD_AUTH_MASTER));
env(noop(bob), sig(Account("bob",
KeyType::ed25519)), ter(tefBAD_AUTH_MASTER));
env(noop(alice), sig(carol), ter(tefBAD_AUTH_MASTER));
// Master and Regular key
env(regkey(alice, bob));
env(noop(alice));
env(noop(alice), sig(bob));
env(noop(alice), sig(alice));
// Regular key only
env(set(alice, asfDisableMaster), sig(alice));
env(noop(alice));
env(noop(alice), sig(bob));
env(noop(alice), sig(alice), ter(tefMASTER_DISABLED));
env(clear(alice, asfDisableMaster), sig(alice), ter(tefMASTER_DISABLED));
env(clear(alice, asfDisableMaster), sig(bob));
env(noop(alice), sig(alice));
}
// Multi-sign basics
void
testMultiSign()
{
using namespace jtx;
Env env(*this);
env.fund(XRP(10000), "alice");
env(signers("alice", 1,
{ { "alice", 1 }, { "bob", 2 } }), ter(temBAD_SIGNER));
env(signers("alice", 1,
{ { "bob", 1 }, { "carol", 2 } }));
env(noop("alice"));
env(noop("alice"), msig("bob"));
env(noop("alice"), msig("carol"));
env(noop("alice"), msig("bob", "carol"));
env(noop("alice"), msig("bob", "carol", "dilbert"), ter(tefBAD_SIGNATURE));
}
// Two level Multi-sign
void
testMultiSign2()
{
using namespace jtx;
Env env(*this);
env.fund(XRP(10000), "alice", "bob", "carol");
env.fund(XRP(10000), "david", "eric", "frank", "greg");
env(signers("alice", 2, { { "bob", 1 }, { "carol", 1 } }));
env(signers("bob", 1, { { "david", 1 }, { "eric", 1 } }));
env(signers("carol", 1, { { "frank", 1 }, { "greg", 1 } }));
env(noop("alice"), msig2(
{ { "bob", "david" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "bob", "david" }, { "bob", "eric" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "carol", "frank" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "carol", "frank" }, { "carol", "greg" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "bob", "david" }, { "carol", "frank" } }));
env(noop("alice"), msig2(
{ { "bob", "david" }, { "bob", "eric" },
{ "carol", "frank" }, { "carol", "greg" } }));
}
// Payment basics
void
testPayments()
{
using namespace jtx;
Env env(*this);
auto const gw = Account("gateway");
auto const USD = gw["USD"];
env(pay(env.master, "alice", XRP(1000)), fee(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), fee(1), ter(telINSUF_FEE_P));
env(pay(env.master, "alice", XRP(1000)), seq(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), seq(2), ter(terPRE_SEQ));
env(pay(env.master, "alice", XRP(1000)), sig(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), sig("bob"), ter(tefBAD_AUTH_MASTER));
env(pay(env.master, "dilbert", XRP(1000)), sig(env.master));
env.fund(XRP(10000), "alice", "bob", "carol", gw);
expect(env["alice"].balance(XRP) == XRP(10000));
expect(env["bob"].balance(XRP) == XRP(10000));
expect(env["carol"].balance(XRP) == XRP(10000));
expect(env[gw].balance(XRP) == XRP(10000));
env.trust(USD(100), "alice", "bob", "carol");
env(rate(gw, 1.05));
env(pay(gw, "carol", USD(50)));
expect(env["carol"].balance(USD) == USD(50));
expect(env[gw].balance(Account("carol")["USD"]) == USD(-50));
env(offer("carol", XRP(50), USD(50)));
env(pay("alice", "bob", USD(10)), ter(tecPATH_DRY));
env(pay("alice", "bob", USD(10)), path(XRP(10)), ter(tecPATH_PARTIAL));
env(pay("alice", "bob", USD(10)), path(XRP(20)));
expect(env["bob"].balance(USD) == USD(10));
expect(env["carol"].balance(USD) == USD(39.5));
env.memoize("eric");
env(regkey("alice", "eric"));
env(noop("alice"));
env(noop("alice"), sig("alice"));
env(noop("alice"), sig("eric"));
env(noop("alice"), sig("bob"), ter(tefBAD_AUTH));
env(set("alice", asfDisableMaster), ter(tecNEED_MASTER_KEY));
env(set("alice", asfDisableMaster), sig("eric"), ter(tecNEED_MASTER_KEY));
expect(! (env["alice"].flags() & lsfDisableMaster));
env(set("alice", asfDisableMaster), sig("alice"));
expect(env["alice"].flags() & lsfDisableMaster);
env(regkey("alice", disabled), ter(tecMASTER_DISABLED));
env(noop("alice"));
env(noop("alice"), sig("alice"), ter(tefMASTER_DISABLED));
env(noop("alice"), sig("eric"));
env(noop("alice"), sig("bob"), ter(tefBAD_AUTH));
env(clear("alice", asfDisableMaster), sig("bob"), ter(tefBAD_AUTH));
env(clear("alice", asfDisableMaster), sig("alice"), ter(tefMASTER_DISABLED));
env(clear("alice", asfDisableMaster));
expect(! (env["alice"].flags() & lsfDisableMaster));
env(regkey("alice", disabled));
env(noop("alice"), sig("eric"), ter(tefBAD_AUTH_MASTER));
env(noop("alice"));
}
void
run()
{
testAutofill();
testKeyType();
testMultiSign();
testMultiSign2();
testPayments();
}
};
BEAST_DEFINE_TESTSUITE(Env,app,ripple)
} // test
} // ripple

View File

@@ -1,393 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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 <BeastConfig.h>
#include <ripple/app/tests/JTx.h>
#include <ripple/app/tests/Env.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/basics/Slice.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/protocol/STParsedJSON.h>
#include <ripple/protocol/TxFlags.h>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
pay (Account const& account,
Account const& to, STAmount const& amount)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::Amount] = amount.getJson(0);
jv[jss::Destination] = to.human();
jv[jss::TransactionType] = "Payment";
jv[jss::Flags] = tfUniversal;
return jv;
}
Json::Value
offer (Account const& account,
STAmount const& in, STAmount const& out)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TakerPays] = in.getJson(0);
jv[jss::TakerGets] = out.getJson(0);
jv[jss::TransactionType] = "OfferCreate";
return jv;
}
Json::Value
rate (Account const& account, double multiplier)
{
if (multiplier > 4)
throw std::runtime_error(
"rate multiplier out of range");
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransferRate] = std::uint32_t(
1000000000 * multiplier);
jv[jss::TransactionType] = "AccountSet";
return jv;
}
Json::Value
regkey (Account const& account,
disabled_t)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "SetRegularKey";
return jv;
}
Json::Value
regkey (Account const& account,
Account const& signer)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv["RegularKey"] = to_string(signer.id());
jv[jss::TransactionType] = "SetRegularKey";
return jv;
}
Json::Value
set (Account const& account,
std::uint32_t on, std::uint32_t off)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "AccountSet";
if (on != 0)
jv[jss::SetFlag] = on;
if (off != 0)
jv[jss::ClearFlag] = off;
return jv;
}
Json::Value
signers (Account const& account,
std::uint32_t quorum,
std::vector<signer> const& v)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "SignerListSet";
jv["SignerQuorum"] = quorum;
auto& ja = jv["SignerEntries"];
ja.resize(v.size());
for(std::size_t i = 0; i < v.size(); ++i)
{
auto const& e = v[i];
auto& je = ja[i]["SignerEntry"];
je[jss::Account] = e.account.human();
je["SignerWeight"] = e.weight;
}
return jv;
}
Json::Value
signers (Account const& account, none_t)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "SignerListSet";
return jv;
}
Json::Value
trust (Account const& account,
STAmount const& amount)
{
if (isXRP(amount))
throw std::runtime_error(
"trust() requires IOU");
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::LimitAmount] = amount.getJson(0);
jv[jss::TransactionType] = "TrustSet";
jv[jss::Flags] = 0; // tfClearNoRipple;
return jv;
}
void
fill_fee (Json::Value& jv,
Ledger const& ledger)
{
if (jv.isMember(jss::Fee))
return;
jv[jss::Fee] = std::to_string(
ledger.getBaseFee());
}
void
fill_seq (Json::Value& jv,
Ledger const& ledger)
{
if (jv.isMember(jss::Sequence))
return;
RippleAddress ra;
ra.setAccountID(jv[jss::Account].asString());
auto const ar = ledger.fetch(
getAccountRootIndex(ra.getAccountID()));
jv[jss::Sequence] =
ar->getFieldU32(sfSequence);
}
void
sign (Json::Value& jv,
Account const& account)
{
jv[jss::SigningPubKey] =
strHex(make_Slice(
account.pk().getAccountPublic()));
Serializer ss;
ss.add32 (HashPrefix::txSign);
parse(jv).add(ss);
jv[jss::TxnSignature] = strHex(make_Slice(
account.sk().accountPrivateSign(
ss.getData())));
}
STObject
parse (Json::Value const& jv)
{
STParsedJSONObject p("tx_json", jv);
if (! p.object)
throw parse_error(
rpcErrorString(p.error));
return std::move(*p.object);
}
void
fee::operator()(Env const&, JTx& tx) const
{
if (boost::indeterminate(b_))
tx[jss::Fee] =
v_.getJson(0);
else
tx.fill_fee = b_;
}
void
flags::operator()(Env const&, JTx& tx) const
{
tx[jss::Flags] =
v_ /*| tfUniversal*/;
}
void
path::operator()(Env const& env, JTx& jtx) const
{
auto& jv = jtx.jv;
auto const from = env.lookup(
jv[jss::Account].asString());
auto const to = env.lookup(
jv[jss::Destination].asString());
jv[jss::SendMax] = sendmax_.getJson(0);
STPath fp;
STPathSet ps;
auto const found = findPathsForOneIssuer(
std::make_shared<RippleLineCache>(
env.ledger), from, to,
sendmax_.issue(), sendmax_,
depth_, limit_,
ps, fp);
// VFALCO TODO API to allow caller to examine the STPathSet
// VFALCO isDefault should be renamed to empty()
if (found && ! ps.isDefault())
jv[jss::Paths] = ps.getJson(0);
}
void
msig::operator()(Env const& env, JTx& tx) const
{
// VFALCO Inefficient pre-C++14
auto accounts = accounts_;
std::sort(accounts.begin(), accounts.end(),
[](Account const& lhs, Account const& rhs)
{
return lhs.id() < rhs.id();
});
tx.signer = [accounts, &env](Env&, JTx& jt)
{
jt["SigningPubKey"] = "";
boost::optional<STObject> st;
try
{
st = parse(jt.jv);
}
catch(parse_error const&)
{
env.test.log << pretty(jt.jv);
throw;
}
auto const signingForID = [](Json::Value const& jv)
{
RippleAddress ra;
ra.setAccountID(jv[jss::Account].asString());
return ra.getAccountID();
}(jt.jv);
auto& jv = jt["MultiSigners"][0u]["SigningFor"];
jv[jss::Account] = jt[jss::Account];
auto& js = jv["SigningAccounts"];
js.resize(accounts.size());
for(std::size_t i = 0; i < accounts.size(); ++i)
{
auto const& e = accounts[i];
auto& jo = js[i]["SigningAccount"];
jo[jss::Account] = e.human();
jo[jss::SigningPubKey] = strHex(make_Slice(
e.pk().getAccountPublic()));
Serializer ss;
ss.add32 (HashPrefix::txMultiSign);
st->addWithoutSigningFields(ss);
ss.add160(signingForID);
ss.add160(e.id());
jo["MultiSignature"] = strHex(make_Slice(
e.sk().accountPrivateSign(ss.getData())));
}
};
}
msig2_t::msig2_t (std::vector<std::pair<
Account, Account>> sigs)
{
for (auto& sig : sigs)
{
auto result = sigs_.emplace(
std::piecewise_construct,
std::make_tuple(std::move(sig.first)),
std::make_tuple());
result.first->second.emplace(
std::move(sig.second));
}
}
void
msig2_t::operator()(Env const& env, JTx& tx) const
{
// VFALCO Inefficient pre-C++14
auto const sigs = sigs_;
tx.signer = [sigs, &env](Env&, JTx& jt)
{
jt["SigningPubKey"] = "";
boost::optional<STObject> st;
try
{
st = parse(jt.jv);
}
catch(parse_error const&)
{
env.test.log << pretty(jt.jv);
throw;
}
auto& ja = jt["MultiSigners"];
ja.resize(sigs.size());
for (auto i = std::make_pair(0, sigs.begin());
i.first < sigs.size(); ++i.first, ++i.second)
{
auto const& sign_for = i.second->first;
auto const& list = i.second->second;
auto& ji = ja[i.first]["SigningFor"];
ji[jss::Account] = sign_for.human();
auto& js = ji["SigningAccounts"];
js.resize(list.size());
for (auto j = std::make_pair(0, list.begin());
j.first < list.size(); ++j.first, ++j.second)
{
auto& jj = js[j.first]["SigningAccount"];
jj[jss::Account] = j.second->human();
jj[jss::SigningPubKey] = strHex(make_Slice(
j.second->pk().getAccountPublic()));
Serializer ss;
ss.add32 (HashPrefix::txMultiSign);
st->addWithoutSigningFields(ss);
ss.add160(sign_for.id());
ss.add160(j.second->id());
jj["MultiSignature"] = strHex(make_Slice(
j.second->sk().accountPrivateSign(
ss.getData())));
}
}
};
}
void
seq::operator()(Env const&, JTx& tx) const
{
if (boost::indeterminate(b_))
tx[jss::Sequence] = v_;
else
tx.fill_seq = b_;
}
void
sig::operator()(Env const&, JTx& tx) const
{
if(boost::indeterminate(b_))
{
// VFALCO Inefficient pre-C++14
auto const account = account_;
tx.signer = [account](Env&, JTx& jt)
{
jtx::sign(jt.jv, account);
};
}
else
{
tx.fill_sig = b_;
}
}
} // jtx
} // test
} // ripple

View File

@@ -1,453 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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_JTX_H_INCLUDED
#define RIPPLE_APP_TESTS_JTX_H_INCLUDED
#include <ripple/app/tests/Common.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/STTx.h>
#include <beast/unit_test/suite.h>
#include <boost/logic/tribool.hpp>
#include <map>
#include <set>
#include <utility>
#include <unordered_map>
#include <vector>
namespace ripple {
namespace test {
class Env;
BOOST_TRIBOOL_THIRD_STATE(use_default)
/** Execution context for applying a JSON transaction.
This augments the transaction with various settings.
*/
struct JTx
{
Json::Value jv;
boost::tribool fill_fee = boost::logic::indeterminate;
boost::tribool fill_seq = boost::logic::indeterminate;
boost::tribool fill_sig = boost::logic::indeterminate;
std::function<void(Env&, JTx&)> signer;
TER ter = tesSUCCESS;
JTx() = default;
JTx (Json::Value&& jv_)
: jv(std::move(jv_))
{
}
JTx (Json::Value const& jv_)
: jv(jv_)
{
}
template <class Key>
Json::Value&
operator[](Key const& key)
{
return jv[key];
}
};
//------------------------------------------------------------------------------
namespace jtx {
struct none_t { none_t() { } };
static none_t const none;
struct autofill_t { autofill_t() { } };
static autofill_t const autofill;
struct disabled_t { disabled_t() { } };
static disabled_t const disabled;
//
// JSON generators
//
/** Create a payment. */
Json::Value
pay (Account const& account,
Account const& to, STAmount const& amount);
/** Create an offer. */
Json::Value
offer (Account const& account,
STAmount const& in, STAmount const& out);
/** Set a transfer rate. */
Json::Value
rate (Account const& account,
double multiplier);
/** Disable the regular key. */
Json::Value
regkey (Account const& account,
disabled_t);
/** Set a regular key. */
Json::Value
regkey (Account const& account,
Account const& signer);
/** Add and/or remove flag. */
Json::Value
set (Account const& account,
std::uint32_t on, std::uint32_t off = 0);
/** Remove account flag. */
inline
Json::Value
clear (Account const& account,
std::uint32_t off)
{
return set(account, 0, off);
}
/** The null transaction. */
inline
Json::Value
noop (Account const& account)
{
return set(account, 0);
}
struct signer
{
std::uint32_t weight;
Account account;
signer (Account account_,
std::uint32_t weight_ = 1)
: weight(weight_)
, account(std::move(account_))
{
}
};
Json::Value
signers (Account const& account,
std::uint32_t quorum,
std::vector<signer> const& v);
/** Remove a signer list. */
Json::Value
signers (Account const& account, none_t);
/** Modify a trust line. */
Json::Value
trust (Account const& account,
STAmount const& amount);
/** Set the fee automatically. */
void
fill_fee (Json::Value& jv,
Ledger const& ledger);
/** Set the sequence number automatically. */
void
fill_seq (Json::Value& jv,
Ledger const& ledger);
/** Sign automatically.
@note This only works on accounts with multi-signing off.
*/
void
sign (Json::Value& jv,
Account const& account);
/** Thrown when parse fails. */
struct parse_error : std::logic_error
{
template <class String>
explicit
parse_error (String const& s)
: logic_error(s)
{
}
};
/** Convert JSON to STObject.
This throws on failure, the JSON must be correct.
@note Testing malformed JSON is beyond the scope of
this set of unit test routines.
*/
STObject
parse (Json::Value const& jv);
//
// Funclets
//
/** Set the fee on a JTx. */
class fee
{
private:
STAmount v_;
boost::tribool b_ =
boost::logic::indeterminate;
public:
explicit
fee (autofill_t)
: b_(true)
{
}
explicit
fee (none_t)
: b_(false)
{
}
explicit
fee (STAmount const& v)
: v_(v)
{
if (! isXRP(v_))
throw std::runtime_error(
"fee: not XRP");
}
void
operator()(Env const&, JTx& tx) const;
};
/** Set the flags on a JTx. */
class flags
{
private:
std::uint32_t v_;
public:
explicit
flags (std::uint32_t v)
: v_(v)
{
}
void
operator()(Env const&, JTx& tx) const;
};
/** Set Paths, SendMax on a JTx. */
class path
{
private:
int depth_;
unsigned int limit_;
STAmount sendmax_;
public:
path (STAmount const& sendmax, int depth = 7,
unsigned int limit = 4)
: depth_(depth)
, limit_(limit)
, sendmax_(sendmax)
{
}
void
operator()(Env const&, JTx& jtx) const;
};
/** Set a multisignature on a JTx. */
class msig
{
private:
std::vector<Account> accounts_;
public:
msig (std::vector<Account> accounts)
: accounts_(std::move(accounts))
{
}
template <class AccountType, class... Accounts>
msig (AccountType&& a0, Accounts&&... aN)
: msig(make_vector(
std::forward<AccountType>(a0),
std::forward<Accounts>(aN)...))
{
}
void
operator()(Env const&, JTx& tx) const;
private:
template <class AccountType>
static
void
helper (std::vector<Account>& v,
AccountType&& account)
{
v.emplace_back(std::forward<
Account>(account));
}
template <class AccountType, class... Accounts>
static
void
helper (std::vector<Account>& v,
AccountType&& a0, Accounts&&... aN)
{
helper(v, std::forward<AccountType>(a0));
helper(v, std::forward<Accounts>(aN)...);
}
template <class... Accounts>
static
std::vector<Account>
make_vector(Accounts&&... accounts)
{
std::vector<Account> v;
v.reserve(sizeof...(accounts));
helper(v, std::forward<
Accounts>(accounts)...);
return v;
}
};
/** Set a multisignature on a JTx. */
class msig2_t
{
private:
std::map<Account,
std::set<Account>> sigs_;
public:
msig2_t (std::vector<std::pair<
Account, Account>> sigs);
void
operator()(Env const&, JTx& tx) const;
};
inline
msig2_t
msig2 (std::vector<std::pair<
Account, Account>> sigs)
{
return msig2_t(std::move(sigs));
}
/** Set the sequence number on a JTx. */
struct seq
{
private:
std::uint32_t v_;
boost::tribool b_ =
boost::logic::indeterminate;
public:
explicit
seq (autofill_t)
: b_(true)
{
}
explicit
seq (none_t)
: b_(false)
{
}
explicit
seq (std::uint32_t v)
: v_(v)
{
}
void
operator()(Env const&, JTx& tx) const;
};
/** Set the regular signature on a JTx.
@note For multisign, use msig.
*/
class sig
{
private:
Account account_;
boost::tribool b_ =
boost::logic::indeterminate;
public:
explicit
sig (autofill_t)
: b_(true)
{
}
explicit
sig (none_t)
: b_(false)
{
}
explicit
sig (Account const& account)
: account_(account)
{
}
void
operator()(Env const&, JTx& tx) const;
};
/** Set the expected result code for a JTx
The test will fail if the code doesn't match.
*/
class ter
{
private:
TER v_;
public:
explicit
ter (TER v)
: v_(v)
{
}
void
operator()(Env const&, JTx& tx) const
{
tx.ter = v_;
}
};
} // jtx
} // test
} // ripple
#endif

View File

@@ -1542,6 +1542,7 @@ class MultiSign_test : public beast::unit_test::suite
}
}
#if RIPPLE_ENABLE_TICKETS
#if 0
// Multi-sign a ttTICKET_CREATE and cancel it using ttTICKET_CANCEL.
{
uint256 ticketIndex {7}; // Any non-zero value so we see it change.
@@ -1588,6 +1589,7 @@ class MultiSign_test : public beast::unit_test::suite
expect (tickets.size() == 0);
}
}
#endif
#endif // RIPPLE_ENABLE_TICKETS
}

53
src/ripple/test/jtx.h Normal file
View File

@@ -0,0 +1,53 @@
//------------------------------------------------------------------------------
/*
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_H_INCLUDED
#define RIPPLE_TEST_JTX_H_INCLUDED
// Convenience header that includes everything
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/amount.h>
#include <ripple/test/jtx/balance.h>
#include <ripple/test/jtx/Env.h>
#include <ripple/test/jtx/fee.h>
#include <ripple/test/jtx/flags.h>
#include <ripple/test/jtx/JTx.h>
#include <ripple/test/jtx/multisign.h>
#include <ripple/test/jtx/noop.h>
#include <ripple/test/jtx/offer.h>
#include <ripple/test/jtx/owners.h>
#include <ripple/test/jtx/paths.h>
#include <ripple/test/jtx/pay.h>
#include <ripple/test/jtx/rate.h>
#include <ripple/test/jtx/regkey.h>
#include <ripple/test/jtx/require.h>
#include <ripple/test/jtx/requires.h>
#include <ripple/test/jtx/sendmax.h>
#include <ripple/test/jtx/seq.h>
#include <ripple/test/jtx/sig.h>
#include <ripple/test/jtx/tags.h>
#include <ripple/test/jtx/ter.h>
#include <ripple/test/jtx/ticket.h>
#include <ripple/test/jtx/trust.h>
#include <ripple/test/jtx/txflags.h>
#include <ripple/test/jtx/utility.h>
#endif

View File

@@ -17,100 +17,20 @@
*/
//==============================================================================
#ifndef RIPPLE_APP_TESTS_COMMON_H_INCLUDED
#define RIPPLE_APP_TESTS_COMMON_H_INCLUDED
#ifndef RIPPLE_TEST_JTX_ACCOUNT_H_INCLUDED
#define RIPPLE_TEST_JTX_ACCOUNT_H_INCLUDED
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/UintTypes.h>
#include <ripple/crypto/KeyType.h>
#include <cstdint>
#include <beast/utility/noexcept.h>
#include <string>
namespace ripple {
namespace test {
namespace jtx {
namespace detail {
struct XRP_t
{
XRP_t() = default;
/** Implicit conversion to Issue.
This allows passing XRP where
an Issue is expected.
*/
operator Issue() const
{
return xrpIssue();
}
/** Returns an amount of XRP as STAmount
@param v The number of XRP (not drops)
*/
STAmount operator()(double v) const;
};
} // detail
/** Converts to XRP Issue or STAmount.
Examples:
XRP Converts to the XRP Issue
XRP(10) Returns STAmount of 10 XRP
*/
extern detail::XRP_t XRP;
/** Returns an XRP STAmount.
Example:
drops(10) Returns STAmount of 10 drops
*/
inline
STAmount
drops (std::uint64_t v)
{
return STAmount(v, false);
}
/** Converts to IOU Issue or STAmount.
Examples:
IOU Converts to the underlying Issue
IOU(10) Returns STAmount of 10 of
the underlying Issue.
*/
class IOU
{
private:
Issue issue_;
public:
IOU(Issue const& issue)
: issue_(issue)
{
}
/** Implicit conversion to Issue.
This allows passing an IOU
value where an Issue is expected.
*/
operator Issue() const
{
return issue_;
}
STAmount operator()(double v) const;
// VFALCO TODO
// STAmount operator()(char const* s) const;
};
//------------------------------------------------------------------------------
class IOU;
/** Immutable cryptographic account descriptor. */
class Account
@@ -151,6 +71,13 @@ public:
}
/** @} */
/** Return the name */
std::string const&
name() const
{
return name_;
}
/** Return the public key. */
RippleAddress const&
pk() const
@@ -195,16 +122,33 @@ public:
/** Returns an IOU for the specified gateway currency. */
IOU
operator[](std::string const& s) const;
/** Meet the requirements of StrictWeakOrdering. */
friend
bool
operator< (Account const& lhs, Account const& rhs)
{
return lhs.id() < rhs.id();
}
};
inline
bool
operator== (Account const& lhs,
Account const& rhs) noexcept
{
return lhs.id() == rhs.id();
}
template <class Hasher>
void
hash_append (Hasher& h,
Account const& v) noexcept
{
hash_append(h, v.id());
}
inline
bool
operator< (Account const& lhs,
Account const& rhs) noexcept
{
return lhs.id() < rhs.id();
}
} // jtx
} // test
} // ripple

481
src/ripple/test/jtx/Env.h Normal file
View File

@@ -0,0 +1,481 @@
//------------------------------------------------------------------------------
/*
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_ENV_H_INCLUDED
#define RIPPLE_TEST_JTX_ENV_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/amount.h>
#include <ripple/test/jtx/JTx.h>
#include <ripple/test/jtx/require.h>
#include <ripple/test/jtx/tags.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/json/json_value.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/STObject.h>
#include <ripple/protocol/STTx.h>
#include <beast/is_call_possible.h>
#include <beast/unit_test/suite.h>
#include <boost/logic/tribool.hpp>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <beast/cxx14/utility.h> // <utility>
#include <functional>
#include <tuple>
#include <utility>
#include <unordered_map>
namespace ripple {
namespace test {
namespace jtx {
/** A view to an account's account root. */
class AccountInfo
{
private:
Account account_;
std::shared_ptr<Ledger> ledger_;
std::shared_ptr<SLE const> root_;
public:
AccountInfo(Account const& account,
std::shared_ptr<Ledger> ledger)
: account_(account)
, ledger_(std::move(ledger))
, root_(ledger_->fetch(
getAccountRootIndex(account.id())))
{
}
STAmount
balance (Issue const& issue) const;
std::uint32_t
seq() const;
std::uint32_t
flags() const;
};
//------------------------------------------------------------------------------
namespace detail {
#ifdef _MSC_VER
// Workaround for C2797:
// list initialization inside member initializer
// list or non-static data member initializer is
// not implemented
//
template <std::size_t N>
struct noripple_helper
{
std::array<Account, N> args;
template <class T, class ...Args>
std::array<Account, sizeof...(Args)>
flatten (Args&& ...args)
{
return std::array<T,
sizeof...(Args)> {
std::forward<Args>(args)...};
}
template <class... Args>
explicit
noripple_helper(Args const&... args_)
: args(flatten<Account>(args_...))
{
}
};
#else
template <std::size_t N>
struct noripple_helper
{
std::array<Account, N> args;
template <class... Args>
explicit
noripple_helper(Args const&... args_)
: args { { args_... } }
{
}
};
#endif
} // detail
/** Designate accounts as no-ripple in Env::fund */
template <class... Args>
detail::noripple_helper<1 + sizeof...(Args)>
noripple (Account const& account,
Args const&... args)
{
return detail::noripple_helper<
1 + sizeof...(Args)>(
account, args...);
}
//------------------------------------------------------------------------------
/** A transaction testing environment. */
class Env
{
public:
beast::unit_test::suite& test;
/** The master account. */
Account const master;
/** The open ledger. */
std::shared_ptr<Ledger> ledger;
public:
Env (beast::unit_test::suite& test_);
/** Associate AccountID with account. */
void
memoize (Account const& account);
/** Returns the Account given the AccountID. */
/** @{ */
Account const&
lookup (std::string const& base58ID) const;
Account const&
lookup (ripple::Account const& id) const;
/** @} */
/** Returns the XRP balance on an account.
Returns 0 if the account does not exist.
*/
PrettyAmount
balance (Account const& account) const;
/** Returns the next sequence number on account.
Exceptions:
Throws if the account does not exist
*/
std::uint32_t
seq (Account const& account) const;
/** Return the balance on an account.
Returns 0 if the trust line does not exist.
*/
// VFALCO NOTE This should return a unit-less amount
PrettyAmount
balance (Account const& account,
Issue const& issue) const;
/** Return an account root.
@return empty if the account does not exist.
*/
std::shared_ptr<SLE const>
le (Account const& account) const;
/** Return a ledger entry.
@return empty if the ledger entry does not exist
*/
// VFALCO NOTE Use Keylet here
std::shared_ptr<SLE const>
le (uint256 const& key) const;
/** Set the fee autofill setting. */
void auto_fee (bool value)
{
fill_fee_ = value;
}
/** Set the sequence number autofill setting. */
void auto_seq (bool value)
{
fill_seq_ = value;
}
/** Set the signature autofill setting.
@note autofill multisigning is not supported
*/
void auto_sig (bool value)
{
fill_sig_ = value;
}
/** Create a JTx from parameters. */
template <class JsonValue,
class... FN>
JTx
jt (JsonValue&& jv, FN const&... fN)
{
JTx jt(std::forward<JsonValue>(jv));
invoke(jt, fN...);
autofill(jt);
return jt;
}
/** Create JSON from parameters.
This will apply funclets and autofill.
*/
template <class JsonValue,
class... FN>
Json::Value
json (JsonValue&&jv, FN const&... fN)
{
auto tj = jt(
std::forward<JsonValue>(jv),
fN...);
return std::move(tj.jv);
}
/** Check a set of requirements.
The requirements are formed
from condition functors.
*/
template <class... Args>
void
require (Args const&... args) const
{
jtx::required(args...)(*this);
}
/** Submit an existing JTx.
This calls postconditions.
*/
virtual
void
submit (JTx const& jt);
/** Apply funclets and submit. */
/** @{ */
template <class JsonValue, class... FN>
void
apply (JsonValue&& jv, FN const&... fN)
{
submit(jt(std::forward<
JsonValue>(jv), fN...));
}
template <class JsonValue,
class... FN>
void
operator()(JsonValue&& jv,
FN const&... fN)
{
apply(std::forward<
JsonValue>(jv), fN...);
}
/** @} */
private:
void
fund (bool setDefaultRipple,
STAmount const& amount,
Account const& account);
// If you get an error here it means
// you're calling fund with no accounts
inline
void
fund (STAmount const&)
{
}
void
fund_arg (STAmount const& amount,
Account const& account)
{
fund (true, amount, account);
}
template <std::size_t N>
void
fund_arg (STAmount const& amount,
detail::noripple_helper<N> const& list)
{
for (auto const& account : list.args)
fund (false, amount, account);
}
public:
/** Create a new account with some XRP.
These convenience functions are for easy set-up
of the environment, they bypass fee, seq, and sig
settings. The XRP is transferred from the master
account.
Preconditions:
The account must not already exist
Effects:
The asfDefaultRipple on the account is set,
and the sequence number is incremented, unless
the account is wrapped with a call to noripple.
The account's XRP balance is set to amount.
Generates a test that the balance is set.
@param amount The amount of XRP to transfer to
each account.
@param args A heterogeneous list of accounts to fund
or calls to noripple with lists of accounts
to fund.
*/
template<class Arg, class... Args>
void
fund (STAmount const& amount,
Arg const& arg, Args const&... args)
{
fund_arg (amount, arg);
fund (amount, args...);
}
/** Establish trust lines.
These convenience functions are for easy set-up
of the environment, they bypass fee, seq, and sig
settings.
*/
/** @{ */
void
trust (STAmount const& amount,
Account const& account);
template<class... Accounts>
void
trust (STAmount const& amount, Account const& to0,
Account const& to1, Accounts const&... toN)
{
trust(amount, to0);
trust(amount, to1, toN...);
}
/** @} */
protected:
void
autofill_sig (JTx& jt);
virtual
void
autofill (JTx& jt);
/** Create a STTx from a JTx
The framework requires that JSON is valid.
On a parse error, the JSON is logged and
an exception thrown.
Throws:
parse_error
*/
// VFALCO NOTE This should be <STTx const>
std::shared_ptr<STTx>
st (JTx const& jt);
inline
void
invoke (STTx& stx)
{
}
template <class F>
inline
void
maybe_invoke (STTx& stx, F const& f,
std::false_type)
{
}
template <class F>
void
maybe_invoke (STTx& stx, F const& f,
std::true_type)
{
f(*this, stx);
}
// Invoke funclets on stx
// Note: The STTx may not be modified
template <class F, class... FN>
void
invoke (STTx& stx, F const& f,
FN const&... fN)
{
maybe_invoke(stx, f,
beast::is_call_possible<F,
void(Env&, STTx const&)>());
invoke(stx, fN...);
}
inline
void
invoke (JTx&)
{
}
template <class F>
inline
void
maybe_invoke (JTx& jt, F const& f,
std::false_type)
{
}
template <class F>
void
maybe_invoke (JTx& jt, F const& f,
std::true_type)
{
f(*this, jt);
}
// Invoke funclets on jt
template <class F, class... FN>
void
invoke (JTx& jt, F const& f,
FN const&... fN)
{
maybe_invoke(jt, f,
beast::is_call_possible<F,
void(Env&, JTx&)>());
invoke(jt, fN...);
}
// Map of account IDs to Account
std::unordered_map<
ripple::Account, Account> map_;
bool fill_fee_ = true;
bool fill_seq_ = true;
bool fill_sig_ = true;
};
} // jtx
} // test
} // ripple
#endif

74
src/ripple/test/jtx/JTx.h Normal file
View File

@@ -0,0 +1,74 @@
//------------------------------------------------------------------------------
/*
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_JTX_H_INCLUDED
#define RIPPLE_TEST_JTX_JTX_H_INCLUDED
#include <ripple/test/jtx/requires.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/TER.h>
#include <boost/logic/tribool.hpp>
#include <functional>
namespace ripple {
namespace test {
namespace jtx {
class Env;
BOOST_TRIBOOL_THIRD_STATE(use_default)
/** Execution context for applying a JSON transaction.
This augments the transaction with various settings.
*/
struct JTx
{
Json::Value jv;
boost::tribool fill_fee = boost::logic::indeterminate;
boost::tribool fill_seq = boost::logic::indeterminate;
boost::tribool fill_sig = boost::logic::indeterminate;
std::function<void(Env&, JTx&)> signer;
requires_t requires;
TER ter = tesSUCCESS;
JTx() = default;
JTx (Json::Value&& jv_)
: jv(std::move(jv_))
{
}
JTx (Json::Value const& jv_)
: jv(jv_)
{
}
template <class Key>
Json::Value&
operator[](Key const& key)
{
return jv[key];
}
};
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,385 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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_AMOUNT_H_INCLUDED
#define RIPPLE_TEST_JTX_AMOUNT_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/amount.h>
#include <ripple/test/jtx/tags.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/STAmount.h>
#include <cstdint>
#include <ostream>
#include <string>
#include <beast/cxx14/type_traits.h> // <type_traits>
namespace ripple {
namespace test {
namespace jtx {
/*
The decision was made to accept amounts of drops and XRP
using an int type, since the range of XRP is 100 billion
and having both signed and unsigned overloads creates
tricky code leading to overload resolution ambiguities.
*/
struct AnyAmount;
// Represents "no amount" of a currency
// This is distinct from zero or a balance.
// For example, no USD means the trust line
// doesn't even exist. Using this in an
// inappropriate context will generate a
// compile error.
//
struct None
{
Issue issue;
};
//------------------------------------------------------------------------------
template <class T>
struct dropsPerXRP
{
static T const value = 1000000;
};
/** Represents an XRP or IOU quantity
This customizes the string conversion and supports
XRP conversions from integer and floating point.
*/
struct PrettyAmount
{
private:
// VFALCO TODO should be Amount
STAmount amount_;
std::string name_;
public:
PrettyAmount() = default;
PrettyAmount (PrettyAmount const&) = default;
PrettyAmount& operator=(PrettyAmount const&) = default;
PrettyAmount (STAmount const& amount,
std::string const& name)
: amount_(amount)
, name_(name)
{
}
/** drops */
template <class T>
PrettyAmount (T v, std::enable_if_t<
sizeof(T) >= sizeof(int) &&
std::is_integral<T>::value &&
std::is_signed<T>::value>* = nullptr)
: amount_((v > 0) ?
v : -v, v < 0)
{
}
/** drops */
template <class T>
PrettyAmount (T v, std::enable_if_t<
sizeof(T) >= sizeof(int) &&
std::is_integral<T>::value &&
std::is_unsigned<T>::value>* = nullptr)
: amount_(v)
{
}
std::string const&
name() const
{
return name_;
}
STAmount const&
value() const
{
return amount_;
}
operator STAmount const&() const
{
return amount_;
}
operator AnyAmount() const;
};
inline
bool
operator== (PrettyAmount const& lhs,
PrettyAmount const& rhs)
{
return lhs.value() == rhs.value();
}
std::ostream&
operator<< (std::ostream& os,
PrettyAmount const& amount);
//------------------------------------------------------------------------------
namespace detail {
struct XRP_t
{
/** Implicit conversion to Issue.
This allows passing XRP where
an Issue is expected.
*/
operator Issue() const
{
return xrpIssue();
}
/** Returns an amount of XRP as STAmount
@param v The number of XRP (not drops)
*/
/** @{ */
template <class T, class = std::enable_if_t<
std::is_integral<T>::value>>
PrettyAmount
operator()(T v) const
{
return { v *
dropsPerXRP<T>::value };
}
PrettyAmount
operator()(double v) const
{
auto const c =
dropsPerXRP<int>::value;
if (v >= 0)
{
auto const d = std::uint64_t(
std::round(v * c));
if (double(d) / c != v)
throw std::domain_error(
"unrepresentable");
return { d };
}
auto const d = std::int64_t(
std::round(v * c));
if (double(d) / c != v)
throw std::domain_error(
"unrepresentable");
return { d };
}
/** @} */
/** Returns None-of-XRP */
None
operator()(none_t) const
{
return { xrpIssue() };
}
};
} // detail
/** Converts to XRP Issue or STAmount.
Examples:
XRP Converts to the XRP Issue
XRP(10) Returns STAmount of 10 XRP
*/
extern detail::XRP_t const XRP;
/** Returns an XRP STAmount.
Example:
drops(10) Returns STAmount of 10 drops
*/
template <class Integer,
class = std::enable_if_t<
std::is_integral<Integer>::value>>
PrettyAmount
drops (Integer i)
{
return { i };
}
//------------------------------------------------------------------------------
namespace detail {
struct epsilon_multiple
{
std::size_t n;
};
} // detail
// The smallest possible IOU STAmount
struct epsilon_t
{
epsilon_t()
{
}
detail::epsilon_multiple
operator()(std::size_t n) const
{
return { n };
}
};
static epsilon_t const epsilon;
/** Converts to IOU Issue or STAmount.
Examples:
IOU Converts to the underlying Issue
IOU(10) Returns STAmount of 10 of
the underlying Issue.
*/
class IOU
{
private:
Account account_;
ripple::Currency currency_;
public:
IOU(Account const& account,
ripple::Currency const& currency)
: account_(account)
, currency_(currency)
{
}
Account
account() const
{
return account_;
}
Issue
issue() const
{
return { currency_, account_.id() };
}
/** Implicit conversion to Issue.
This allows passing an IOU
value where an Issue is expected.
*/
operator Issue() const
{
return issue();
}
template <class T, class = std::enable_if_t<
sizeof(T) >= sizeof(int) &&
std::is_arithmetic<T>::value>>
PrettyAmount operator()(T v) const
{
// VFALCO NOTE Should throw if the
// representation of v is not exact.
return { amountFromString(issue(),
std::to_string(v)), account_.name() };
}
PrettyAmount operator()(epsilon_t) const;
PrettyAmount operator()(detail::epsilon_multiple) const;
// VFALCO TODO
// STAmount operator()(char const* s) const;
/** Returns None-of-Issue */
None operator()(none_t) const
{
return { issue() };
}
};
std::ostream&
operator<<(std::ostream& os,
IOU const& iou);
//------------------------------------------------------------------------------
struct any_t
{
inline
AnyAmount
operator()(STAmount const& sta) const;
};
/** Amount specifier with an option for any issuer. */
struct AnyAmount
{
bool is_any;
STAmount value;
AnyAmount() = delete;
AnyAmount (AnyAmount const&) = default;
AnyAmount& operator= (AnyAmount const&) = default;
AnyAmount (STAmount const& amount)
: is_any(false)
, value(amount)
{
}
AnyAmount (STAmount const& amount,
any_t const*)
: is_any(true)
, value(amount)
{
}
// Reset the issue to a specific account
void
to (ripple::Account const& id)
{
if (! is_any)
return;
value.setIssuer(id);
}
};
inline
AnyAmount
any_t::operator()(STAmount const& sta) const
{
return AnyAmount(sta, this);
}
/** Returns an amount representing "any issuer"
@note With respect to what the recipient will accept
*/
extern any_t const any;
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,78 @@
//------------------------------------------------------------------------------
/*
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_BALANCE_H_INCLUDED
#define RIPPLE_TEST_JTX_BALANCE_H_INCLUDED
#include <ripple/test/jtx/tags.h>
#include <ripple/test/jtx/Env.h>
namespace ripple {
namespace test {
namespace jtx {
/** A balance matches.
This allows "none" which means either the account
doesn't exist (no XRP) or the trust line does not
exist. If an amount is specified, the SLE must
exist even if the amount is 0, or else the test
fails.
*/
class balance
{
private:
bool none_;
Account account_;
STAmount value_;
public:
balance (Account const& account,
none_t)
: none_(true)
, account_(account)
, value_(XRP)
{
}
balance (Account const& account,
None const& value)
: none_(true)
, account_(account)
, value_(value.issue)
{
}
balance (Account const& account,
STAmount const& value)
: none_(false)
, account_(account)
, value_(value)
{
}
void
operator()(Env const&) const;
};
} // jtx
} // test
} // ripple
#endif

70
src/ripple/test/jtx/fee.h Normal file
View File

@@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
/*
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_FEE_H_INCLUDED
#define RIPPLE_TEST_JTX_FEE_H_INCLUDED
#include <ripple/test/jtx/Env.h>
#include <ripple/test/jtx/tags.h>
#include <ripple/protocol/STAmount.h>
#include <boost/logic/tribool.hpp>
namespace ripple {
namespace test {
namespace jtx {
/** Set the fee on a JTx. */
class fee
{
private:
STAmount v_;
boost::tribool b_ =
boost::logic::indeterminate;
public:
explicit
fee (autofill_t)
: b_(true)
{
}
explicit
fee (none_t)
: b_(false)
{
}
explicit
fee (STAmount const& v)
: v_(v)
{
if (! isXRP(v_))
throw std::runtime_error(
"fee: not XRP");
}
void
operator()(Env const&, JTx& jt) const;
};
} // jtx
} // test
} // ripple
#endif

142
src/ripple/test/jtx/flags.h Normal file
View File

@@ -0,0 +1,142 @@
//------------------------------------------------------------------------------
/*
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_FLAGS_H_INCLUDED
#define RIPPLE_TEST_JTX_FLAGS_H_INCLUDED
#include <ripple/test/jtx/Env.h>
#include <ripple/protocol/LedgerFormats.h>
#include <ripple/protocol/TxFlags.h>
namespace ripple {
namespace test {
namespace jtx {
// JSON generators
/** Add and/or remove flag. */
Json::Value
fset (Account const& account,
std::uint32_t on, std::uint32_t off = 0);
/** Remove account flag. */
inline
Json::Value
fclear (Account const& account,
std::uint32_t off)
{
return fset(account, 0, off);
}
namespace detail {
class flags_helper
{
protected:
std::uint32_t mask_;
private:
inline
void
set_args()
{
}
void
set_args (std::uint32_t flag)
{
switch(flag)
{
case asfRequireDest: mask_ |= lsfRequireDestTag; break;
case asfRequireAuth: mask_ |= lsfRequireAuth; break;
case asfDisallowXRP: mask_ |= lsfDisallowXRP; break;
case asfDisableMaster: mask_ |= lsfDisableMaster; break;
//case asfAccountTxnID: // ???
case asfNoFreeze: mask_ |= lsfNoFreeze; break;
case asfGlobalFreeze: mask_ |= lsfGlobalFreeze; break;
case asfDefaultRipple: mask_ |= lsfDefaultRipple; break;
default:
throw std::runtime_error(
"unknown flag");
}
}
template <class Flag,
class... Args>
void
set_args (std::uint32_t flag,
Args... args)
{
set_args(flag, args...);
}
protected:
template <class... Args>
flags_helper (Args... args)
: mask_(0)
{
set_args(args...);
}
};
} // detail
/** Match set account flags */
class flags : private detail::flags_helper
{
private:
Account account_;
public:
template <class... Args>
flags (Account const& account,
Args... args)
: flags_helper(args...)
, account_(account)
{
}
void
operator()(Env const& env) const;
};
/** Match clear account flags */
class nflags : private detail::flags_helper
{
private:
Account account_;
public:
template <class... Args>
nflags (Account const& account,
Args... args)
: flags_helper(args...)
, account_(account)
{
}
void
operator()(Env const& env) const;
};
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/amount.h>
namespace ripple {
namespace test {
namespace jtx {
#ifdef _MSC_VER
Account::Account (Account&& other)
: name_(std::move(other.name_))
, pk_(std::move(other.pk_))
, sk_(std::move(other.sk_))
, id_(std::move(other.id_))
, human_(std::move(other.human_))
{
}
Account&
Account::operator= (Account&& rhs)
{
name_ = std::move(rhs.name_);
pk_ = std::move(rhs.pk_);
sk_ = std::move(rhs.sk_);
id_ = std::move(rhs.id_);
human_ = std::move(rhs.human_);
return *this;
}
#endif
Account::Account(
std::string name, KeyPair&& keys)
: name_(std::move(name))
{
pk_ = std::move(keys.publicKey);
sk_ = std::move(keys.secretKey);
id_ = pk_.getAccountID();
human_ = pk_.humanAccountID();
}
Account::Account (std::string name,
KeyType type)
#ifndef _MSC_VER
: Account(name,
#else
// Fails on Clang and possibly gcc
: Account(std::move(name),
#endif
generateKeysFromSeed(type,
RippleAddress::createSeedGeneric(
name)))
{
}
IOU
Account::operator[](std::string const& s) const
{
auto const currency = to_currency(s);
assert(currency != noCurrency());
return IOU(*this, currency);
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,308 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/balance.h>
#include <ripple/test/jtx/Env.h>
#include <ripple/test/jtx/fee.h>
#include <ripple/test/jtx/flags.h>
#include <ripple/test/jtx/pay.h>
#include <ripple/test/jtx/trust.h>
#include <ripple/test/jtx/require.h>
#include <ripple/test/jtx/seq.h>
#include <ripple/test/jtx/sig.h>
#include <ripple/test/jtx/utility.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/app/tx/TransactionEngine.h>
#include <ripple/basics/Slice.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/protocol/LedgerFormats.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/SystemParameters.h>
#include <ripple/protocol/TER.h>
#include <ripple/protocol/TxFlags.h>
#include <memory>
// VFALCO TODO Use AnyPublicKey, AnySecretKey, AccountID
namespace ripple {
namespace test {
namespace jtx {
Env::Env (beast::unit_test::suite& test_)
: test(test_)
, master("master", generateKeysFromSeed(
KeyType::secp256k1, RippleAddress::createSeedGeneric(
"masterpassphrase")))
{
memoize(master);
initializePathfinding();
ledger = std::make_shared<Ledger>(
master.pk(), SYSTEM_CURRENCY_START);
}
void
Env::memoize (Account const& account)
{
map_.emplace(account.id(), account);
}
Account const&
Env::lookup (std::string const& base58ID) const
{
RippleAddress ra;
if (! ra.setAccountID(base58ID))
throw std::runtime_error(
"Env::lookup: invalid account ID");
return lookup(ra.getAccountID());
}
Account const&
Env::lookup (ripple::Account const& id) const
{
auto const iter = map_.find(id);
if (iter == map_.end())
throw std::runtime_error(
"Env::lookup:: unknown account ID");
return iter->second;
}
PrettyAmount
Env::balance (Account const& account) const
{
auto const sle = le(account);
if (! sle)
return XRP(0);
return {
sle->getFieldAmount(sfBalance),
"" };
}
PrettyAmount
Env::balance (Account const& account,
Issue const& issue) const
{
if (isXRP(issue.currency))
return balance(account);
auto const sle = le(getRippleStateIndex(
account.id(), issue));
if (! sle)
return { STAmount( issue, 0 ),
account.name() };
auto amount = sle->getFieldAmount(sfBalance);
amount.setIssuer(issue.account);
if (account.id() > issue.account)
amount.negate();
return { amount,
lookup(issue.account).name() };
}
std::uint32_t
Env::seq (Account const& account) const
{
auto const sle = le(account);
if (! sle)
throw std::runtime_error(
"missing account root");
return sle->getFieldU32(sfSequence);
}
std::shared_ptr<SLE const>
Env::le (Account const& account) const
{
// VFALCO NOTE This hack should be removed
// when fetch returns shared_ptr again
auto const st = ledger->fetch(
getAccountRootIndex(account.id()));
if (! st)
return nullptr;
return std::make_shared<SLE const>(*st);
}
std::shared_ptr<SLE const>
Env::le (uint256 const& key) const
{
// VFALCO NOTE This hack should be removed
// when fetch returns shared_ptr again
auto const st = ledger->fetch(key);
if (! st)
return nullptr;
return std::make_shared<SLE const>(*st);
}
void
Env::fund (bool setDefaultRipple,
STAmount const& amount,
Account const& account)
{
memoize(account);
if (setDefaultRipple)
{
// VFALCO NOTE Is the fee formula correct?
apply(pay(master, account, amount +
drops(ledger->getBaseFee())),
jtx::seq(jtx::autofill),
fee(jtx::autofill),
sig(jtx::autofill));
apply(fset(account, asfDefaultRipple),
jtx::seq(jtx::autofill),
fee(jtx::autofill),
sig(jtx::autofill));
require(flags(account, asfDefaultRipple));
}
else
{
apply(pay(master, account, amount),
jtx::seq(jtx::autofill),
fee(jtx::autofill),
sig(jtx::autofill));
require(nflags(account, asfDefaultRipple));
}
require(jtx::balance(account, amount));
}
void
Env::trust (STAmount const& amount,
Account const& account)
{
apply(jtx::trust(account, amount),
jtx::seq(jtx::autofill),
fee(jtx::autofill),
sig(jtx::autofill));
}
void
Env::submit (JTx const& jt)
{
auto const stx = st(jt);
TER ter;
bool didApply;
if (stx)
{
TransactionEngine txe (ledger,
tx_enable_test);
std::tie(ter, didApply) = txe.applyTransaction(
*stx, tapOPEN_LEDGER |
(true ? tapNONE : tapNO_CHECK_SIGN));
}
else
{
// Convert the exception into a TER so that
// callers can expect it using ter(temMALFORMED)
ter = temMALFORMED;
didApply = false;
}
if (! test.expect(ter == jt.ter,
"apply: " + transToken(ter) +
" (" + transHuman(ter) + ")"))
{
test.log << pretty(jt.jv);
// Don't check postconditions if
// we didn't get the expected result.
return;
}
for (auto const& f : jt.requires)
f(*this);
}
void
Env::autofill_sig (JTx& jt)
{
auto& jv = jt.jv;
auto const should = [](boost::tribool v, bool b)
{
if (boost::indeterminate(v))
return b;
return bool(v);
};
if (jt.signer)
jt.signer(*this, jt);
else if(should(jt.fill_sig, fill_sig_))
{
auto const account =
lookup(jv[jss::Account].asString());
auto const ar =
ledger->fetch(getAccountRootIndex(account));
if (ar->isFieldPresent(sfRegularKey))
jtx::sign(jv, lookup(
ar->getFieldAccount160(sfRegularKey)));
else
jtx::sign(jv, account);
}
}
void
Env::autofill (JTx& jt)
{
auto& jv = jt.jv;
auto const should = [](boost::tribool v, bool b)
{
if (boost::indeterminate(v))
return b;
return bool(v);
};
if(should(jt.fill_fee, fill_fee_))
jtx::fill_fee(jv, *ledger);
if(should(jt.fill_seq, fill_seq_))
jtx::fill_seq(jv, *ledger);
// Must come last
autofill_sig(jt);
}
std::shared_ptr<STTx>
Env::st (JTx const& jt)
{
// The parse must succeed, since we
// generated the JSON ourselves.
boost::optional<STObject> obj;
try
{
obj = jtx::parse(jt.jv);
}
catch(jtx::parse_error const&)
{
test.log <<
"Exception: parse_error\n" <<
pretty(jt.jv);
throw;
}
try
{
return std::make_shared<STTx>(
std::move(*obj));
}
catch(...)
{
}
return nullptr;
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,456 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/basics/Log.h>
#include <ripple/test/jtx.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/TxFlags.h>
#include <beast/hash/uhash.h>
#include <beast/unit_test/suite.h>
#include <boost/lexical_cast.hpp>
#include <utility>
namespace ripple {
namespace test {
class Env_test : public beast::unit_test::suite
{
public:
template <class T>
static
std::string
to_string (T const& t)
{
return boost::lexical_cast<
std::string>(t);
}
// Declarations in Account.h
void
testAccount()
{
using namespace jtx;
{
Account a;
Account b(a);
a = b;
a = std::move(b);
Account c(std::move(a));
}
Account("alice");
Account("alice", KeyType::secp256k1);
Account("alice", KeyType::ed25519);
auto const gw = Account("gw");
[](ripple::Account){}(gw);
auto const USD = gw["USD"];
void(Account("alice") < gw);
std::set<Account>().emplace(gw);
std::unordered_set<Account,
beast::uhash<>>().emplace("alice");
}
// Declarations in amount.h
void
testAmount()
{
using namespace jtx;
PrettyAmount(0);
PrettyAmount(1);
PrettyAmount(0u);
PrettyAmount(1u);
PrettyAmount(-1);
static_assert(! std::is_constructible<
PrettyAmount, char>::value, "");
static_assert(! std::is_constructible<
PrettyAmount, unsigned char>::value, "");
static_assert(! std::is_constructible<
PrettyAmount, short>::value, "");
static_assert(! std::is_constructible<
PrettyAmount, unsigned short>::value, "");
try
{
XRP(0.0000001);
fail("missing exception");
}
catch(std::domain_error const&)
{
pass();
}
XRP(-0.000001);
try
{
XRP(-0.0000009);
fail("missing exception");
}
catch(std::domain_error const&)
{
pass();
}
expect(to_string(XRP(5)) == "5 XRP");
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(drops(10)) == "10 drops");
expect(to_string(drops(123400000)) == "123.4 XRP");
expect(to_string(XRP(-5)) == "-5 XRP");
expect(to_string(XRP(-.99)) == "-0.99 XRP");
expect(to_string(XRP(-.005)) == "-5000 drops");
expect(to_string(XRP(-0.1)) == "-0.1 XRP");
expect(to_string(drops(-10)) == "-10 drops");
expect(to_string(drops(-123400000)) == "-123.4 XRP");
expect(XRP(1) == drops(1000000));
expect(XRP(1) == STAmount(1000000));
expect(STAmount(1000000) == XRP(1));
auto const gw = Account("gw");
auto const USD = gw["USD"];
expect(to_string(USD(0)) == "0/USD(gw)");
expect(to_string(USD(10)) == "10/USD(gw)");
expect(to_string(USD(-10)) == "-10/USD(gw)");
expect(USD(0) == STAmount(USD, 0));
expect(USD(1) == STAmount(USD, 1));
expect(USD(-1) == STAmount(USD, -1));
auto const get = [](AnyAmount a){ return a; };
expect(! get(USD(10)).is_any);
expect(get(any(USD(10))).is_any);
}
// Test Env
void
testEnv()
{
using namespace jtx;
auto const n = XRP(10000);
auto const gw = Account("gw");
auto const USD = gw["USD"];
auto const alice = Account("alice");
// fund
{
Env env(*this);
// variadics
env.fund(n, "alice");
env.fund(n, "bob", "carol");
env.fund(n, "dave", noripple("eric"));
env.fund(n, "fred", noripple("gary", "hank"));
env.fund(n, noripple("irene"));
env.fund(n, noripple("jim"), "karen");
env.fund(n, noripple("lisa", "mary"));
// flags
env.fund(n, noripple("xavier"));
env.require(nflags("xavier", asfDefaultRipple));
env.fund(n, "yana");
env.require(flags("yana", asfDefaultRipple));
// fund always autofills
env.auto_fee(false);
env.auto_seq(false);
env.auto_sig(false);
env.fund(n, "zeke");
env.require(balance("zeke", n));
}
// trust
{
Env env(*this);
env.fund(n, "alice", "bob", gw);
env(trust("alice", USD(100)), require(lines("alice", 1)));
// trust always autofills
env.auto_fee(false);
env.auto_seq(false);
env.auto_sig(false);
env.trust(USD(100), "bob");
env.require(lines("bob", 1));
}
// balance
{
Env env(*this);
expect(env.balance(alice) == 0);
expect(env.balance(alice, USD) != 0);
expect(env.balance(alice, USD) == USD(0));
env.fund(n, alice, gw);
expect(env.balance(alice) == n);
expect(env.balance(gw) == n);
env.trust(USD(1000), alice);
env(pay(gw, alice, USD(10)));
expect(to_string(env.balance("alice", USD)) == "10/USD(gw)");
expect(to_string(env.balance(gw, alice["USD"])) == "-10/USD(alice)");
}
// seq
{
Env env(*this);
env.fund(n, noripple("alice", gw));
expect(env.seq("alice") == 1);
expect(env.seq(gw) == 1);
}
// autofill
{
Env env(*this);
env.fund(n, "alice");
env.auto_fee(false);
env.require(balance("alice", n));
env(noop("alice"), fee(1), ter(telINSUF_FEE_P));
env(noop("alice"), seq(none), ter(temMALFORMED));
env(noop("alice"), seq(none), fee(10), ter(temMALFORMED));
env(noop("alice"), fee(none), ter(temMALFORMED));
env(noop("alice"), sig(none), ter(temMALFORMED));
env(noop("alice"), fee(autofill));
env.auto_seq(false);
env(noop("alice"), fee(autofill), seq(autofill));
env.auto_sig(false);
env(noop("alice"), fee(autofill), seq(autofill), sig(autofill));
}
}
// Env::require
void
testRequire()
{
using namespace jtx;
Env env(*this);
auto const gw = Account("gw");
auto const USD = gw["USD"];
env.require(balance("alice", none));
env.require(balance("alice", XRP(none)));
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", USD(0)));
env(pay(gw, "alice", USD(10)), require(balance("alice", USD(10))));
env.require(nflags("alice", asfRequireDest));
env(fset("alice", asfRequireDest), require(flags("alice", asfRequireDest)));
env(fclear("alice", asfRequireDest), require(nflags("alice", asfRequireDest)));
}
// Signing with secp256k1 and ed25519 keys
void
testKeyType()
{
using namespace jtx;
Env env(*this);
Account const alice("alice", KeyType::ed25519);
Account const bob("bob", KeyType::secp256k1);
Account const carol("carol");
env.fund(XRP(10000), alice, bob);
// Master key only
env(noop(alice));
env(noop(bob));
env(noop(alice), sig("alice"), ter(tefBAD_AUTH_MASTER));
env(noop(alice), sig(Account("alice",
KeyType::secp256k1)), ter(tefBAD_AUTH_MASTER));
env(noop(bob), sig(Account("bob",
KeyType::ed25519)), ter(tefBAD_AUTH_MASTER));
env(noop(alice), sig(carol), ter(tefBAD_AUTH_MASTER));
// Master and Regular key
env(regkey(alice, bob));
env(noop(alice));
env(noop(alice), sig(bob));
env(noop(alice), sig(alice));
// Regular key only
env(fset(alice, asfDisableMaster), sig(alice));
env(noop(alice));
env(noop(alice), sig(bob));
env(noop(alice), sig(alice), ter(tefMASTER_DISABLED));
env(fclear(alice, asfDisableMaster), sig(alice), ter(tefMASTER_DISABLED));
env(fclear(alice, asfDisableMaster), sig(bob));
env(noop(alice), sig(alice));
}
// Payment basics
void
testPayments()
{
using namespace jtx;
Env env(*this);
auto const gw = Account("gateway");
auto const USD = gw["USD"];
env(pay(env.master, "alice", XRP(1000)), fee(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), fee(1), ter(telINSUF_FEE_P));
env(pay(env.master, "alice", XRP(1000)), seq(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), seq(2), ter(terPRE_SEQ));
env(pay(env.master, "alice", XRP(1000)), sig(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), sig("bob"), ter(tefBAD_AUTH_MASTER));
env(pay(env.master, "dilbert", XRP(1000)), sig(env.master));
env.fund(XRP(10000), "alice", "bob", "carol", gw);
env.require(balance("alice", XRP(10000)));
env.require(balance("bob", XRP(10000)));
env.require(balance("carol", XRP(10000)));
env.require(balance(gw, XRP(10000)));
env.trust(USD(100), "alice", "bob", "carol");
env.require(owners("alice", 1), lines("alice", 1));
env(rate(gw, 1.05));
env(pay(gw, "carol", USD(50)));
env.require(balance("carol", USD(50)));
env.require(balance(gw, Account("carol")["USD"](-50)));
env(offer("carol", XRP(50), USD(50)), require(owners("carol", 2)));
env(pay("alice", "bob", any(USD(10))), ter(tecPATH_DRY));
env(pay("alice", "bob", any(USD(10))),
paths(XRP), sendmax(XRP(10)), ter(tecPATH_PARTIAL));
env(pay("alice", "bob", any(USD(10))), paths(XRP),
sendmax(XRP(20)));
env.require(balance("bob", USD(10)));
env.require(balance("carol", USD(39.5)));
env.memoize("eric");
env(regkey("alice", "eric"));
env(noop("alice"));
env(noop("alice"), sig("alice"));
env(noop("alice"), sig("eric"));
env(noop("alice"), sig("bob"), ter(tefBAD_AUTH));
env(fset("alice", asfDisableMaster), ter(tecNEED_MASTER_KEY));
env(fset("alice", asfDisableMaster), sig("eric"), ter(tecNEED_MASTER_KEY));
env.require(nflags("alice", asfDisableMaster));
env(fset("alice", asfDisableMaster), sig("alice"));
env.require(flags("alice", asfDisableMaster));
env(regkey("alice", disabled), ter(tecMASTER_DISABLED));
env(noop("alice"));
env(noop("alice"), sig("alice"), ter(tefMASTER_DISABLED));
env(noop("alice"), sig("eric"));
env(noop("alice"), sig("bob"), ter(tefBAD_AUTH));
env(fclear("alice", asfDisableMaster), sig("bob"), ter(tefBAD_AUTH));
env(fclear("alice", asfDisableMaster), sig("alice"), ter(tefMASTER_DISABLED));
env(fclear("alice", asfDisableMaster));
env.require(nflags("alice", asfDisableMaster));
env(regkey("alice", disabled));
env(noop("alice"), sig("eric"), ter(tefBAD_AUTH_MASTER));
env(noop("alice"));
}
// Multi-sign basics
void
testMultiSign()
{
using namespace jtx;
Env env(*this);
env.fund(XRP(10000), "alice");
env(signers("alice", 1,
{ { "alice", 1 }, { "bob", 2 } }), ter(temBAD_SIGNER));
env(signers("alice", 1,
{ { "bob", 1 }, { "carol", 2 } }));
env(noop("alice"));
env(noop("alice"), msig("bob"));
env(noop("alice"), msig("carol"));
env(noop("alice"), msig("bob", "carol"));
env(noop("alice"), msig("bob", "carol", "dilbert"), ter(tefBAD_SIGNATURE));
}
// Two level Multi-sign
void
testMultiSign2()
{
using namespace jtx;
Env env(*this);
env.fund(XRP(10000), "alice", "bob", "carol");
env.fund(XRP(10000), "david", "eric", "frank", "greg");
env(signers("alice", 2, { { "bob", 1 }, { "carol", 1 } }));
env(signers("bob", 1, { { "david", 1 }, { "eric", 1 } }));
env(signers("carol", 1, { { "frank", 1 }, { "greg", 1 } }));
env(noop("alice"), msig2(
{ { "bob", "david" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "bob", "david" }, { "bob", "eric" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "carol", "frank" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "carol", "frank" }, { "carol", "greg" } }), ter(tefBAD_QUORUM));
env(noop("alice"), msig2(
{ { "bob", "david" }, { "carol", "frank" } }));
env(noop("alice"), msig2(
{ { "bob", "david" }, { "bob", "eric" },
{ "carol", "frank" }, { "carol", "greg" } }));
}
void
testTicket()
{
using namespace jtx;
// create syntax
ticket::create("alice", "bob");
ticket::create("alice", 60);
ticket::create("alice", "bob", 60);
ticket::create("alice", 60, "bob");
{
Env env(*this);
env.fund(XRP(10000), "alice");
env(noop("alice"), require(owners("alice", 0), tickets("alice", 0)));
env(ticket::create("alice"), require(owners("alice", 1), tickets("alice", 1)));
env(ticket::create("alice"), require(owners("alice", 2), tickets("alice", 2)));
}
Env env(*this);
}
void
run()
{
// Hack to silence logging
deprecatedLogs().severity(
beast::Journal::Severity::kNone);
testAccount();
testAmount();
testEnv();
testRequire();
testKeyType();
testPayments();
testMultiSign();
testMultiSign2();
testTicket();
}
};
BEAST_DEFINE_TESTSUITE(Env,app,ripple)
} // test
} // ripple

View File

@@ -0,0 +1,124 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012-2015 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 <BeastConfig.h>
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/amount.h>
#include <cassert>
#include <cmath>
#include <iomanip>
namespace ripple {
namespace test {
namespace jtx {
#if 0
std::ostream&
operator<<(std::ostream&& os,
AnyAmount const& amount)
{
if (amount.is_any)
{
os << amount.value.getText() << "/" <<
to_string(amount.value.issue().currency) <<
"*";
return os;
}
os << amount.value.getText() << "/" <<
to_string(amount.value.issue().currency) <<
"(" << amount.name() << ")";
return os;
}
#endif
PrettyAmount::operator AnyAmount() const
{
return { amount_ };
}
std::ostream&
operator<< (std::ostream& os,
PrettyAmount const& amount)
{
if (amount.value().native())
{
// measure in hundredths
auto const c =
dropsPerXRP<int>::value / 100;
auto const n = amount.value().mantissa();
if(n < c)
{
if (amount.value().negative())
os << "-" << n << " drops";
else
os << n << " drops";
return os;
}
auto const d = double(n) /
dropsPerXRP<int>::value;
os.precision(6);
if (amount.value().negative())
os << "-" << d << " XRP";
else
os << d << " XRP";
}
else
{
os <<
amount.value().getText() << "/" <<
to_string(amount.value().issue().currency) <<
"(" << amount.name() << ")";
}
return os;
}
//------------------------------------------------------------------------------
detail::XRP_t const XRP { };
PrettyAmount
IOU::operator()(epsilon_t) const
{
return { STAmount(issue(), 1, -81),
account_.name() };
}
PrettyAmount
IOU::operator()(detail::epsilon_multiple m) const
{
return { STAmount(issue(),
static_cast<std::uint64_t>(m.n), -81),
account_.name() };
}
std::ostream&
operator<<(std::ostream& os,
IOU const& iou)
{
os <<
to_string(iou.issue().currency) <<
"(" << iou.account().name() << ")";
return os;
}
any_t const any { };
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,68 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/balance.h>
namespace ripple {
namespace test {
namespace jtx {
void
balance::operator()(Env const& env) const
{
if (isXRP(value_.issue()))
{
auto const sle = env.le(account_);
if (none_)
{
env.test.expect(! sle);
}
else if (env.test.expect(sle))
{
env.test.expect(sle->getFieldAmount(
sfBalance) == value_);
}
}
else
{
auto const sle = env.le(
getRippleStateIndex(account_.id(),
value_.issue()));
if (none_)
{
env.test.expect(! sle);
}
else if (env.test.expect(sle))
{
auto amount =
sle->getFieldAmount(sfBalance);
amount.setIssuer(
value_.issue().account);
if (account_.id() >
value_.issue().account)
amount.negate();
env.test.expect(amount == value_);
}
}
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/fee.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
void
fee::operator()(Env const&, JTx& jt) const
{
if (boost::indeterminate(b_))
jt[jss::Fee] =
v_.getJson(0);
else
jt.fill_fee = b_;
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/flags.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
fset (Account const& account,
std::uint32_t on, std::uint32_t off)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "AccountSet";
if (on != 0)
jv[jss::SetFlag] = on;
if (off != 0)
jv[jss::ClearFlag] = off;
return jv;
}
void
flags::operator()(Env const& env) const
{
auto const sle = env.le(account_);
if (sle->isFieldPresent(sfFlags))
env.test.expect((sle->getFieldU32(sfFlags) &
mask_) == mask_);
else
env.test.expect(mask_ == 0);
}
void
nflags::operator()(Env const& env) const
{
auto const sle = env.le(account_);
if (sle->isFieldPresent(sfFlags))
env.test.expect((sle->getFieldU32(sfFlags) &
mask_) == 0);
else
env.test.pass();
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,181 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/multisign.h>
#include <ripple/test/jtx/utility.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
signers (Account const& account,
std::uint32_t quorum,
std::vector<signer> const& v)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "SignerListSet";
jv["SignerQuorum"] = quorum;
auto& ja = jv["SignerEntries"];
ja.resize(v.size());
for(std::size_t i = 0; i < v.size(); ++i)
{
auto const& e = v[i];
auto& je = ja[i]["SignerEntry"];
je[jss::Account] = e.account.human();
je["SignerWeight"] = e.weight;
}
return jv;
}
Json::Value
signers (Account const& account, none_t)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "SignerListSet";
return jv;
}
//------------------------------------------------------------------------------
void
msig::operator()(Env const& env, JTx& jt) const
{
// VFALCO Inefficient pre-C++14
auto accounts = accounts_;
std::sort(accounts.begin(), accounts.end(),
[](Account const& lhs, Account const& rhs)
{
return lhs.id() < rhs.id();
});
jt.signer = [accounts, &env](Env&, JTx& jt)
{
jt["SigningPubKey"] = "";
boost::optional<STObject> st;
try
{
st = parse(jt.jv);
}
catch(parse_error const&)
{
env.test.log << pretty(jt.jv);
throw;
}
auto const signingForID = [](Json::Value const& jv)
{
RippleAddress ra;
ra.setAccountID(jv[jss::Account].asString());
return ra.getAccountID();
}(jt.jv);
auto& jv = jt["MultiSigners"][0u]["SigningFor"];
jv[jss::Account] = jt[jss::Account];
auto& js = jv["SigningAccounts"];
js.resize(accounts.size());
for(std::size_t i = 0; i < accounts.size(); ++i)
{
auto const& e = accounts[i];
auto& jo = js[i]["SigningAccount"];
jo[jss::Account] = e.human();
jo[jss::SigningPubKey] = strHex(make_Slice(
e.pk().getAccountPublic()));
Serializer ss;
ss.add32 (HashPrefix::txMultiSign);
st->addWithoutSigningFields(ss);
ss.add160(signingForID);
ss.add160(e.id());
jo["MultiSignature"] = strHex(make_Slice(
e.sk().accountPrivateSign(ss.getData())));
}
};
}
msig2_t::msig2_t (std::vector<std::pair<
Account, Account>> sigs)
{
for (auto& sig : sigs)
{
auto result = sigs_.emplace(
std::piecewise_construct,
std::make_tuple(std::move(sig.first)),
std::make_tuple());
result.first->second.emplace(
std::move(sig.second));
}
}
void
msig2_t::operator()(Env const& env, JTx& jt) const
{
// VFALCO Inefficient pre-C++14
auto const sigs = sigs_;
jt.signer = [sigs, &env](Env&, JTx& jt)
{
jt["SigningPubKey"] = "";
boost::optional<STObject> st;
try
{
st = parse(jt.jv);
}
catch(parse_error const&)
{
env.test.log << pretty(jt.jv);
throw;
}
auto& ja = jt["MultiSigners"];
ja.resize(sigs.size());
for (auto i = std::make_pair(0, sigs.begin());
i.first < sigs.size(); ++i.first, ++i.second)
{
auto const& sign_for = i.second->first;
auto const& list = i.second->second;
auto& ji = ja[i.first]["SigningFor"];
ji[jss::Account] = sign_for.human();
auto& js = ji["SigningAccounts"];
js.resize(list.size());
for (auto j = std::make_pair(0, list.begin());
j.first < list.size(); ++j.first, ++j.second)
{
auto& jj = js[j.first]["SigningAccount"];
jj[jss::Account] = j.second->human();
jj[jss::SigningPubKey] = strHex(make_Slice(
j.second->pk().getAccountPublic()));
Serializer ss;
ss.add32 (HashPrefix::txMultiSign);
st->addWithoutSigningFields(ss);
ss.add160(sign_for.id());
ss.add160(j.second->id());
jj["MultiSignature"] = strHex(make_Slice(
j.second->sk().accountPrivateSign(
ss.getData())));
}
}
};
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,42 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/offer.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
offer (Account const& account,
STAmount const& in, STAmount const& out)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TakerPays] = in.getJson(0);
jv[jss::TakerGets] = out.getJson(0);
jv[jss::TransactionType] = "OfferCreate";
return jv;
}
} // jtx
} // test
} // ripple

View File

@@ -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.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/test/jtx/owners.h>
namespace ripple {
namespace test {
namespace jtx {
namespace detail {
std::uint32_t
owned_count_of(Ledger const& ledger,
ripple::Account const& id,
LedgerEntryType type)
{
std::uint32_t count = 0;
forEachItem(ledger, id, getApp().getSLECache(),
[&count, type](std::shared_ptr<SLE const> const& sle)
{
if (sle->getType() == type)
++count;
});
return count;
}
void
owned_count_helper(Env const& env,
ripple::Account const& id,
LedgerEntryType type,
std::uint32_t value)
{
env.test.expect(owned_count_of(
*env.ledger, id, type) == value);
}
} // detail
void
owners::operator()(Env const& env) const
{
env.test.expect(env.le(
account_)->getFieldU32(sfOwnerCount) ==
value_);
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/paths.h>
#include <ripple/app/paths/FindPaths.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
void
paths::operator()(Env const& env, JTx& jt) const
{
auto& jv = jt.jv;
auto const from = env.lookup(
jv[jss::Account].asString());
auto const to = env.lookup(
jv[jss::Destination].asString());
auto const amount = amountFromJson(
sfAmount, jv[jss::Amount]);
STPath fp;
STPathSet ps;
auto const found = findPathsForOneIssuer(
std::make_shared<RippleLineCache>(
env.ledger), from, to,
in_, amount,
depth_, limit_, ps, fp);
// VFALCO TODO API to allow caller to examine the STPathSet
// VFALCO isDefault should be renamed to empty()
if (found && ! ps.isDefault())
jv[jss::Paths] = ps.getJson(0);
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/pay.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/protocol/TxFlags.h>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
pay (Account const& account,
Account const& to,
AnyAmount amount)
{
amount.to(to);
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::Amount] = amount.value.getJson(0);
jv[jss::Destination] = to.human();
jv[jss::TransactionType] = "Payment";
jv[jss::Flags] = tfUniversal;
return jv;
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,45 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/rate.h>
#include <ripple/protocol/JsonFields.h>
#include <stdexcept>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
rate (Account const& account, double multiplier)
{
if (multiplier > 4)
throw std::runtime_error(
"rate multiplier out of range");
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransferRate] = std::uint32_t(
1000000000 * multiplier);
jv[jss::TransactionType] = "AccountSet";
return jv;
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/regkey.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
regkey (Account const& account,
disabled_t)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "SetRegularKey";
return jv;
}
Json::Value
regkey (Account const& account,
Account const& signer)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv["RegularKey"] = to_string(signer.id());
jv[jss::TransactionType] = "SetRegularKey";
return jv;
}
} // jtx
} // test
} // ripple

View File

@@ -18,9 +18,19 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/test/jtx/sendmax.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/app/tests/Common.cpp>
#include <ripple/app/tests/Env.cpp>
#include <ripple/app/tests/JTx.cpp>
namespace ripple {
namespace test {
namespace jtx {
#include <ripple/app/tests/Env_test.cpp>
void
sendmax::operator()(Env const& env, JTx& jt) const
{
jt.jv[jss::SendMax] = amount_.getJson(0);
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,39 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/seq.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
void
seq::operator()(Env const&, JTx& jt) const
{
if (boost::indeterminate(b_))
jt[jss::Sequence] = v_;
else
jt.fill_seq = b_;
}
} // jtx
} // test
} // ripple

View File

@@ -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.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/test/jtx/sig.h>
#include <ripple/test/jtx/utility.h>
namespace ripple {
namespace test {
namespace jtx {
void
sig::operator()(Env const&, JTx& jt) const
{
if(boost::indeterminate(b_))
{
// VFALCO Inefficient pre-C++14
auto const account = account_;
jt.signer = [account](Env&, JTx& jt)
{
jtx::sign(jt.jv, account);
};
}
else
{
jt.fill_sig = b_;
}
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,53 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/ticket.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
namespace ticket {
namespace detail {
Json::Value
create (Account const& account,
boost::optional<Account> const& target,
boost::optional<std::uint32_t> const& expire)
{
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::TransactionType] = "TicketCreate";
if (expire)
jv["Expiration"] = *expire;
if (target)
jv["Target"] = target->human();
return jv;
}
} // detail
} // ticket
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/trust.h>
#include <ripple/protocol/JsonFields.h>
#include <stdexcept>
namespace ripple {
namespace test {
namespace jtx {
Json::Value
trust (Account const& account,
STAmount const& amount)
{
if (isXRP(amount))
throw std::runtime_error(
"trust() requires IOU");
Json::Value jv;
jv[jss::Account] = account.human();
jv[jss::LimitAmount] = amount.getJson(0);
jv[jss::TransactionType] = "TrustSet";
jv[jss::Flags] = 0; // tfClearNoRipple;
return jv;
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/txflags.h>
#include <ripple/protocol/JsonFields.h>
namespace ripple {
namespace test {
namespace jtx {
void
txflags::operator()(Env const&, JTx& jt) const
{
jt[jss::Flags] =
v_ /*| tfUniversal*/;
}
} // jtx
} // test
} // ripple

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/utility.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/protocol/STParsedJSON.h>
#include <cstring>
namespace ripple {
namespace test {
namespace jtx {
STObject
parse (Json::Value const& jv)
{
STParsedJSONObject p("tx_json", jv);
if (! p.object)
throw parse_error(
rpcErrorString(p.error));
return std::move(*p.object);
}
void
sign (Json::Value& jv,
Account const& account)
{
jv[jss::SigningPubKey] =
strHex(make_Slice(
account.pk().getAccountPublic()));
Serializer ss;
ss.add32 (HashPrefix::txSign);
parse(jv).add(ss);
jv[jss::TxnSignature] = strHex(make_Slice(
account.sk().accountPrivateSign(
ss.getData())));
}
void
fill_fee (Json::Value& jv,
Ledger const& ledger)
{
if (jv.isMember(jss::Fee))
return;
jv[jss::Fee] = std::to_string(
ledger.getBaseFee());
}
void
fill_seq (Json::Value& jv,
Ledger const& ledger)
{
if (jv.isMember(jss::Sequence))
return;
RippleAddress ra;
ra.setAccountID(jv[jss::Account].asString());
auto const ar = ledger.fetch(
getAccountRootIndex(ra.getAccountID()));
jv[jss::Sequence] =
ar->getFieldU32(sfSequence);
}
} // jtx
} // test
} // ripple

View File

@@ -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.
*/
//==============================================================================
#ifndef RIPPLE_TEST_JTX_MULTISIGN_H_INCLUDED
#define RIPPLE_TEST_JTX_MULTISIGN_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/amount.h>
#include <ripple/test/jtx/owners.h>
#include <ripple/test/jtx/tags.h>
#include <cstdint>
namespace ripple {
namespace test {
namespace jtx {
/** A signer in a SignerList */
struct signer
{
std::uint32_t weight;
Account account;
signer (Account account_,
std::uint32_t weight_ = 1)
: weight(weight_)
, account(std::move(account_))
{
}
};
Json::Value
signers (Account const& account,
std::uint32_t quorum,
std::vector<signer> const& v);
/** Remove a signer list. */
Json::Value
signers (Account const& account, none_t);
//------------------------------------------------------------------------------
/** Set a multisignature on a JTx. */
class msig
{
private:
std::vector<Account> accounts_;
public:
msig (std::vector<Account> accounts)
: accounts_(std::move(accounts))
{
}
template <class AccountType, class... Accounts>
msig (AccountType&& a0, Accounts&&... aN)
: msig(make_vector(
std::forward<AccountType>(a0),
std::forward<Accounts>(aN)...))
{
}
void
operator()(Env const&, JTx& jt) const;
private:
template <class AccountType>
static
void
helper (std::vector<Account>& v,
AccountType&& account)
{
v.emplace_back(std::forward<
Account>(account));
}
template <class AccountType, class... Accounts>
static
void
helper (std::vector<Account>& v,
AccountType&& a0, Accounts&&... aN)
{
helper(v, std::forward<AccountType>(a0));
helper(v, std::forward<Accounts>(aN)...);
}
template <class... Accounts>
static
std::vector<Account>
make_vector(Accounts&&... accounts)
{
std::vector<Account> v;
v.reserve(sizeof...(accounts));
helper(v, std::forward<
Accounts>(accounts)...);
return v;
}
};
//------------------------------------------------------------------------------
/** Set a multisignature on a JTx. */
class msig2_t
{
private:
std::map<Account,
std::set<Account>> sigs_;
public:
msig2_t (std::vector<std::pair<
Account, Account>> sigs);
void
operator()(Env const&, JTx& jt) const;
};
inline
msig2_t
msig2 (std::vector<std::pair<
Account, Account>> sigs)
{
return msig2_t(std::move(sigs));
}
//------------------------------------------------------------------------------
/** The number of signer lists matches. */
using siglists = owner_count<ltSIGNER_LIST>;
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,41 @@
//------------------------------------------------------------------------------
/*
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_NOOP_H_INCLUDED
#define RIPPLE_TEST_JTX_NOOP_H_INCLUDED
#include <ripple/test/jtx/flags.h>
namespace ripple {
namespace test {
namespace jtx {
/** The null transaction. */
inline
Json::Value
noop (Account const& account)
{
return fset(account, 0);
}
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
/*
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_OFFER_H_INCLUDED
#define RIPPLE_TEST_JTX_OFFER_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/STAmount.h>
namespace ripple {
namespace test {
namespace jtx {
/** Create an offer. */
Json::Value
offer (Account const& account,
STAmount const& in, STAmount const& out);
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,100 @@
//------------------------------------------------------------------------------
/*
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_OWNERS_H_INCLUDED
#define RIPPLE_TEST_JTX_OWNERS_H_INCLUDED
#include <ripple/test/jtx/Env.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/protocol/LedgerFormats.h>
#include <ripple/protocol/UintTypes.h>
#include <cstdint>
namespace ripple {
namespace test {
namespace jtx {
namespace detail {
std::uint32_t
owned_count_of (Ledger const& ledger,
ripple::Account const& id,
LedgerEntryType type);
void
owned_count_helper(Env const& env,
ripple::Account const& id,
LedgerEntryType type,
std::uint32_t value);
} // detail
// Helper for aliases
template <LedgerEntryType Type>
class owner_count
{
private:
Account account_;
std::uint32_t value_;
public:
owner_count (Account const& account,
std::uint32_t value)
: account_(account)
, value_(value)
{
}
void
operator()(Env const& env) const
{
detail::owned_count_helper(
env, account_.id(), Type, value_);
}
};
/** Match the number of items in the account's owner directory */
class owners
{
private:
Account account_;
std::uint32_t value_;
public:
owners (Account const& account,
std::uint32_t value)
: account_(account)
, value_(value)
{
}
void
operator()(Env const& env) const;
};
/** Match the number of trust lines in the account's owner directory */
using lines = owner_count<ltRIPPLE_STATE>;
/** Match the number of offers in the account's owner directory */
using offers = owner_count<ltOFFER>;
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,55 @@
//------------------------------------------------------------------------------
/*
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_PATHS_H_INCLUDED
#define RIPPLE_TEST_JTX_PATHS_H_INCLUDED
#include <ripple/test/jtx/Env.h>
#include <ripple/protocol/Issue.h>
namespace ripple {
namespace test {
namespace jtx {
/** Set Paths, SendMax on a JTx. */
class paths
{
private:
Issue in_;
int depth_;
unsigned int limit_;
public:
paths (Issue const& in,
int depth = 7, unsigned int limit = 4)
: in_(in)
, depth_(depth)
, limit_(limit)
{
}
void
operator()(Env const&, JTx& jtx) const;
};
} // jtx
} // test
} // ripple
#endif

41
src/ripple/test/jtx/pay.h Normal file
View File

@@ -0,0 +1,41 @@
//------------------------------------------------------------------------------
/*
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_PAY_H_INCLUDED
#define RIPPLE_TEST_JTX_PAY_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/amount.h>
#include <ripple/json/json_value.h>
namespace ripple {
namespace test {
namespace jtx {
/** Create a payment. */
Json::Value
pay (Account const& account,
Account const& to,
AnyAmount amount);
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,39 @@
//------------------------------------------------------------------------------
/*
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_RATE_H_INCLUDED
#define RIPPLE_TEST_JTX_RATE_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/json/json_value.h>
namespace ripple {
namespace test {
namespace jtx {
/** Set a transfer rate. */
Json::Value
rate (Account const& account,
double multiplier);
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,45 @@
//------------------------------------------------------------------------------
/*
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_REGKEY_H_INCLUDED
#define RIPPLE_TEST_JTX_REGKEY_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/tags.h>
#include <ripple/json/json_value.h>
namespace ripple {
namespace test {
namespace jtx {
/** Disable the regular key. */
Json::Value
regkey (Account const& account,
disabled_t);
/** Set a regular key. */
Json::Value
regkey (Account const& account,
Account const& signer);
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,94 @@
//------------------------------------------------------------------------------
/*
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_REQUIRE_H_INCLUDED
#define RIPPLE_TEST_JTX_REQUIRE_H_INCLUDED
#include <ripple/test/jtx/requires.h>
#include <functional>
#include <vector>
namespace ripple {
namespace test {
namespace jtx {
namespace detail {
inline
void
require_args (requires_t& vec)
{
}
template <class Cond, class... Args>
inline
void
require_args (requires_t& vec,
Cond const& cond, Args const&... args)
{
vec.push_back(cond);
require_args(vec, args...);
}
} // detail
/** Compose many condition functors into one */
template <class...Args>
require_t
required (Args const&... args)
{
requires_t vec;
detail::require_args(vec, args...);
return [vec](Env const& env)
{
for(auto const& f : vec)
f(env);
};
}
/** Check a set of conditions.
The conditions are checked after a JTx is
applied, and only if the resulting TER
matches the expected TER.
*/
class require
{
private:
require_t cond_;
public:
template<class... Args>
require(Args const&... args)
: cond_(required(args...))
{
}
void
operator()(Env const&, JTx& jt) const
{
jt.requires.emplace_back(cond_);
}
};
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,39 @@
//------------------------------------------------------------------------------
/*
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_REQUIRES_H_INCLUDED
#define RIPPLE_TEST_JTX_REQUIRES_H_INCLUDED
#include <functional>
#include <vector>
namespace ripple {
namespace test {
namespace jtx {
class Env;
using require_t = std::function<void(Env const&)>;
using requires_t = std::vector<require_t>;
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
/*
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_SENDMAX_H_INCLUDED
#define RIPPLE_TEST_JTX_SENDMAX_H_INCLUDED
#include <ripple/test/jtx/Env.h>
#include <ripple/protocol/STAmount.h>
namespace ripple {
namespace test {
namespace jtx {
/** Sets the SendMax on a JTx. */
class sendmax
{
private:
STAmount amount_;
public:
sendmax (STAmount const& amount)
: amount_(amount)
{
}
void
operator()(Env const&, JTx& jtx) const;
};
} // jtx
} // test
} // ripple
#endif

66
src/ripple/test/jtx/seq.h Normal file
View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
/*
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_SEQ_H_INCLUDED
#define RIPPLE_TEST_JTX_SEQ_H_INCLUDED
#include <ripple/test/jtx/Env.h>
#include <ripple/test/jtx/tags.h>
#include <boost/logic/tribool.hpp>
namespace ripple {
namespace test {
namespace jtx {
/** Set the sequence number on a JTx. */
struct seq
{
private:
std::uint32_t v_;
boost::tribool b_ =
boost::logic::indeterminate;
public:
explicit
seq (autofill_t)
: b_(true)
{
}
explicit
seq (none_t)
: b_(false)
{
}
explicit
seq (std::uint32_t v)
: v_(v)
{
}
void
operator()(Env const&, JTx& jt) const;
};
} // jtx
} // test
} // ripple
#endif

66
src/ripple/test/jtx/sig.h Normal file
View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
/*
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_SIG_H_INCLUDED
#define RIPPLE_TEST_JTX_SIG_H_INCLUDED
#include <ripple/test/jtx/Env.h>
namespace ripple {
namespace test {
namespace jtx {
/** Set the regular signature on a JTx.
@note For multisign, use msig.
*/
class sig
{
private:
Account account_;
boost::tribool b_ =
boost::logic::indeterminate;
public:
explicit
sig (autofill_t)
: b_(true)
{
}
explicit
sig (none_t)
: b_(false)
{
}
explicit
sig (Account const& account)
: account_(account)
{
}
void
operator()(Env const&, JTx& jt) const;
};
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,42 @@
//------------------------------------------------------------------------------
/*
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_TAGS_H_INCLUDED
#define RIPPLE_TEST_JTX_TAGS_H_INCLUDED
namespace ripple {
namespace test {
namespace jtx {
struct none_t { none_t() { } };
static none_t const none;
struct autofill_t { autofill_t() { } };
static autofill_t const autofill;
struct disabled_t { disabled_t() { } };
static disabled_t const disabled;
} // jtx
} // test
} // ripple
#endif

55
src/ripple/test/jtx/ter.h Normal file
View File

@@ -0,0 +1,55 @@
//------------------------------------------------------------------------------
/*
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_TER_H_INCLUDED
#define RIPPLE_TEST_JTX_TER_H_INCLUDED
#include <ripple/test/jtx/Env.h>
namespace ripple {
namespace test {
namespace jtx {
/** Set the expected result code for a JTx
The test will fail if the code doesn't match.
*/
class ter
{
private:
TER v_;
public:
explicit
ter (TER v)
: v_(v)
{
}
void
operator()(Env const&, JTx& jt) const
{
jt.ter = v_;
}
};
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,113 @@
//------------------------------------------------------------------------------
/*
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_TICKET_H_INCLUDED
#define RIPPLE_TEST_JTX_TICKET_H_INCLUDED
#include <ripple/test/jtx/Env.h>
#include <ripple/test/jtx/Account.h>
#include <ripple/test/jtx/owners.h>
#include <boost/optional.hpp>
#include <cstdint>
namespace ripple {
namespace test {
namespace jtx {
/*
This shows how the jtx system may be extended to other
generators, funclets, conditions, and operations,
without changing the base declarations.
*/
/** Ticket operations */
namespace ticket {
namespace detail {
Json::Value
create (Account const& account,
boost::optional<Account> const& target,
boost::optional<std::uint32_t> const& expire);
inline
void
create_arg (boost::optional<Account>& opt,
boost::optional<std::uint32_t>&,
Account const& value)
{
opt = value;
}
inline
void
create_arg (boost::optional<Account>&,
boost::optional<std::uint32_t>& opt,
std::uint32_t value)
{
opt = value;
}
inline
void
create_args (boost::optional<Account>&,
boost::optional<std::uint32_t>&)
{
}
template<class Arg, class... Args>
void
create_args(boost::optional<Account>& account_opt,
boost::optional<std::uint32_t>& expire_opt,
Arg const& arg, Args const&... args)
{
create_arg(account_opt, expire_opt, arg);
create_args(account_opt, expire_opt, args...);
}
} // detail
/** Create a ticket */
template <class... Args>
Json::Value
create (Account const& account,
Args const&... args)
{
boost::optional<Account> target;
boost::optional<std::uint32_t> expire;
detail::create_args(target, expire, args...);
return detail::create(
account, target, expire);
}
/** Cancel a ticket */
//Json::Value
//cancel (Account const& account,
} // ticket
/** Match the number of tickets on the account. */
using tickets = owner_count<ltTICKET>;
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
/*
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_TRUST_H_INCLUDED
#define RIPPLE_TEST_JTX_TRUST_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/STAmount.h>
namespace ripple {
namespace test {
namespace jtx {
/** Modify a trust line. */
Json::Value
trust (Account const& account,
STAmount const& amount);
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
/*
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_TXFLAGS_H_INCLUDED
#define RIPPLE_TEST_JTX_TXFLAGS_H_INCLUDED
#include <ripple/test/jtx/Env.h>
namespace ripple {
namespace test {
namespace jtx {
/** Set the flags on a JTx. */
class txflags
{
private:
std::uint32_t v_;
public:
explicit
txflags (std::uint32_t v)
: v_(v)
{
}
void
operator()(Env const&, JTx& jt) const;
};
} // jtx
} // test
} // ripple
#endif

View File

@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
/*
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_UTILITY_H_INCLUDED
#define RIPPLE_TEST_JTX_UTILITY_H_INCLUDED
#include <ripple/test/jtx/Account.h>
#include <ripple/json/json_value.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/protocol/STObject.h>
#include <stdexcept>
namespace ripple {
namespace test {
namespace jtx {
/** Thrown when parse fails. */
struct parse_error : std::logic_error
{
template <class String>
explicit
parse_error (String const& s)
: logic_error(s)
{
}
};
/** Convert JSON to STObject.
This throws on failure, the JSON must be correct.
@note Testing malformed JSON is beyond the scope of
this set of unit test routines.
*/
STObject
parse (Json::Value const& jv);
/** Sign automatically.
@note This only works on accounts with multi-signing off.
*/
void
sign (Json::Value& jv,
Account const& account);
/** Set the fee automatically. */
void
fill_fee (Json::Value& jv,
Ledger const& ledger);
/** Set the sequence number automatically. */
void
fill_seq (Json::Value& jv,
Ledger const& ledger);
} // jtx
} // test
} // ripple
#endif

43
src/ripple/unity/test.cpp Normal file
View File

@@ -0,0 +1,43 @@
//------------------------------------------------------------------------------
/*
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 <BeastConfig.h>
#include <ripple/test/jtx/impl/Account.cpp>
#include <ripple/test/jtx/impl/amount.cpp>
#include <ripple/test/jtx/impl/balance.cpp>
#include <ripple/test/jtx/impl/Env.cpp>
#include <ripple/test/jtx/impl/fee.cpp>
#include <ripple/test/jtx/impl/flags.cpp>
#include <ripple/test/jtx/impl/multisign.cpp>
#include <ripple/test/jtx/impl/offer.cpp>
#include <ripple/test/jtx/impl/owners.cpp>
#include <ripple/test/jtx/impl/paths.cpp>
#include <ripple/test/jtx/impl/pay.cpp>
#include <ripple/test/jtx/impl/rate.cpp>
#include <ripple/test/jtx/impl/regkey.cpp>
#include <ripple/test/jtx/impl/sendmax.cpp>
#include <ripple/test/jtx/impl/seq.cpp>
#include <ripple/test/jtx/impl/sig.cpp>
#include <ripple/test/jtx/impl/ticket.cpp>
#include <ripple/test/jtx/impl/trust.cpp>
#include <ripple/test/jtx/impl/txflags.cpp>
#include <ripple/test/jtx/impl/utility.cpp>
#include <ripple/test/jtx/impl/Env_test.cpp>