mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Don't include unit test sources in code coverage (RIPD-1132):
Most files containing unit test code are moved to src/test. JTx and the test client code are not yet moved.
This commit is contained in:
107
src/test/protocol/BuildInfo_test.cpp
Normal file
107
src/test/protocol/BuildInfo_test.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/protocol/BuildInfo.h>
|
||||
#include <ripple/beast/core/SemanticVersion.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class BuildInfo_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
ProtocolVersion
|
||||
from_version (std::uint16_t major, std::uint16_t minor)
|
||||
{
|
||||
return ProtocolVersion (major, minor);
|
||||
}
|
||||
|
||||
void testValues ()
|
||||
{
|
||||
testcase ("comparison");
|
||||
|
||||
BEAST_EXPECT(from_version (1,2) == from_version (1,2));
|
||||
BEAST_EXPECT(from_version (3,4) >= from_version (3,4));
|
||||
BEAST_EXPECT(from_version (5,6) <= from_version (5,6));
|
||||
BEAST_EXPECT(from_version (7,8) > from_version (6,7));
|
||||
BEAST_EXPECT(from_version (7,8) < from_version (8,9));
|
||||
BEAST_EXPECT(from_version (65535,0) < from_version (65535,65535));
|
||||
BEAST_EXPECT(from_version (65535,65535) >= from_version (65535,65535));
|
||||
}
|
||||
|
||||
void testStringVersion ()
|
||||
{
|
||||
testcase ("string version");
|
||||
|
||||
for (std::uint16_t major = 0; major < 8; major++)
|
||||
{
|
||||
for (std::uint16_t minor = 0; minor < 8; minor++)
|
||||
{
|
||||
BEAST_EXPECT(to_string (from_version (major, minor)) ==
|
||||
std::to_string (major) + "." + std::to_string (minor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testVersionPacking ()
|
||||
{
|
||||
testcase ("version packing");
|
||||
|
||||
BEAST_EXPECT(to_packed (from_version (0, 0)) == 0);
|
||||
BEAST_EXPECT(to_packed (from_version (0, 1)) == 1);
|
||||
BEAST_EXPECT(to_packed (from_version (0, 255)) == 255);
|
||||
BEAST_EXPECT(to_packed (from_version (0, 65535)) == 65535);
|
||||
|
||||
BEAST_EXPECT(to_packed (from_version (1, 0)) == 65536);
|
||||
BEAST_EXPECT(to_packed (from_version (1, 1)) == 65537);
|
||||
BEAST_EXPECT(to_packed (from_version (1, 255)) == 65791);
|
||||
BEAST_EXPECT(to_packed (from_version (1, 65535)) == 131071);
|
||||
|
||||
BEAST_EXPECT(to_packed (from_version (255, 0)) == 16711680);
|
||||
BEAST_EXPECT(to_packed (from_version (255, 1)) == 16711681);
|
||||
BEAST_EXPECT(to_packed (from_version (255, 255)) == 16711935);
|
||||
BEAST_EXPECT(to_packed (from_version (255, 65535)) == 16777215);
|
||||
|
||||
BEAST_EXPECT(to_packed (from_version (65535, 0)) == 4294901760);
|
||||
BEAST_EXPECT(to_packed (from_version (65535, 1)) == 4294901761);
|
||||
BEAST_EXPECT(to_packed (from_version (65535, 255)) == 4294902015);
|
||||
BEAST_EXPECT(to_packed (from_version (65535, 65535)) == 4294967295);
|
||||
}
|
||||
|
||||
void run ()
|
||||
{
|
||||
testValues ();
|
||||
testStringVersion ();
|
||||
testVersionPacking ();
|
||||
|
||||
auto const current_protocol = BuildInfo::getCurrentProtocol ();
|
||||
auto const minimum_protocol = BuildInfo::getMinimumProtocol ();
|
||||
|
||||
BEAST_EXPECT(current_protocol >= minimum_protocol);
|
||||
|
||||
log <<
|
||||
" Ripple Version: " << BuildInfo::getVersionString() << '\n' <<
|
||||
" Protocol Version: " << to_string (current_protocol) << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(BuildInfo,ripple_data,ripple);
|
||||
|
||||
} // ripple
|
||||
263
src/test/protocol/IOUAmount_test.cpp
Normal file
263
src/test/protocol/IOUAmount_test.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/IOUAmount.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class IOUAmount_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void testZero ()
|
||||
{
|
||||
testcase ("zero");
|
||||
|
||||
IOUAmount const z (0, 0);
|
||||
|
||||
BEAST_EXPECT(z.mantissa () == 0);
|
||||
BEAST_EXPECT(z.exponent () == -100);
|
||||
BEAST_EXPECT(!z);
|
||||
BEAST_EXPECT(z.signum () == 0);
|
||||
BEAST_EXPECT(z == zero);
|
||||
|
||||
BEAST_EXPECT((z + z) == z);
|
||||
BEAST_EXPECT((z - z) == z);
|
||||
BEAST_EXPECT(z == -z);
|
||||
|
||||
IOUAmount const zz (zero);
|
||||
BEAST_EXPECT(z == zz);
|
||||
}
|
||||
|
||||
void testSigNum ()
|
||||
{
|
||||
testcase ("signum");
|
||||
|
||||
IOUAmount const neg (-1, 0);
|
||||
BEAST_EXPECT(neg.signum () < 0);
|
||||
|
||||
IOUAmount const zer (0, 0);
|
||||
BEAST_EXPECT(zer.signum () == 0);
|
||||
|
||||
IOUAmount const pos (1, 0);
|
||||
BEAST_EXPECT(pos.signum () > 0);
|
||||
}
|
||||
|
||||
void testBeastZero ()
|
||||
{
|
||||
testcase ("beast::Zero Comparisons");
|
||||
|
||||
{
|
||||
IOUAmount z (zero);
|
||||
BEAST_EXPECT(z == zero);
|
||||
BEAST_EXPECT(z >= zero);
|
||||
BEAST_EXPECT(z <= zero);
|
||||
unexpected (z != zero);
|
||||
unexpected (z > zero);
|
||||
unexpected (z < zero);
|
||||
}
|
||||
|
||||
{
|
||||
IOUAmount const neg (-2, 0);
|
||||
BEAST_EXPECT(neg < zero);
|
||||
BEAST_EXPECT(neg <= zero);
|
||||
BEAST_EXPECT(neg != zero);
|
||||
unexpected (neg == zero);
|
||||
}
|
||||
|
||||
{
|
||||
IOUAmount const pos (2, 0);
|
||||
BEAST_EXPECT(pos > zero);
|
||||
BEAST_EXPECT(pos >= zero);
|
||||
BEAST_EXPECT(pos != zero);
|
||||
unexpected (pos == zero);
|
||||
}
|
||||
}
|
||||
|
||||
void testComparisons ()
|
||||
{
|
||||
testcase ("IOU Comparisons");
|
||||
|
||||
IOUAmount const n (-2, 0);
|
||||
IOUAmount const z (0, 0);
|
||||
IOUAmount const p (2, 0);
|
||||
|
||||
BEAST_EXPECT(z == z);
|
||||
BEAST_EXPECT(z >= z);
|
||||
BEAST_EXPECT(z <= z);
|
||||
BEAST_EXPECT(z == -z);
|
||||
unexpected (z > z);
|
||||
unexpected (z < z);
|
||||
unexpected (z != z);
|
||||
unexpected (z != -z);
|
||||
|
||||
BEAST_EXPECT(n < z);
|
||||
BEAST_EXPECT(n <= z);
|
||||
BEAST_EXPECT(n != z);
|
||||
unexpected (n > z);
|
||||
unexpected (n >= z);
|
||||
unexpected (n == z);
|
||||
|
||||
BEAST_EXPECT(p > z);
|
||||
BEAST_EXPECT(p >= z);
|
||||
BEAST_EXPECT(p != z);
|
||||
unexpected (p < z);
|
||||
unexpected (p <= z);
|
||||
unexpected (p == z);
|
||||
|
||||
BEAST_EXPECT(n < p);
|
||||
BEAST_EXPECT(n <= p);
|
||||
BEAST_EXPECT(n != p);
|
||||
unexpected (n > p);
|
||||
unexpected (n >= p);
|
||||
unexpected (n == p);
|
||||
|
||||
BEAST_EXPECT(p > n);
|
||||
BEAST_EXPECT(p >= n);
|
||||
BEAST_EXPECT(p != n);
|
||||
unexpected (p < n);
|
||||
unexpected (p <= n);
|
||||
unexpected (p == n);
|
||||
|
||||
BEAST_EXPECT(p > -p);
|
||||
BEAST_EXPECT(p >= -p);
|
||||
BEAST_EXPECT(p != -p);
|
||||
|
||||
BEAST_EXPECT(n < -n);
|
||||
BEAST_EXPECT(n <= -n);
|
||||
BEAST_EXPECT(n != -n);
|
||||
}
|
||||
|
||||
void testToString()
|
||||
{
|
||||
testcase("IOU strings");
|
||||
|
||||
BEAST_EXPECT(to_string(IOUAmount (-2, 0)) == "-2");
|
||||
BEAST_EXPECT(to_string(IOUAmount (0, 0)) == "0");
|
||||
BEAST_EXPECT(to_string(IOUAmount (2, 0)) == "2");
|
||||
BEAST_EXPECT(to_string(IOUAmount (25, -3)) == "0.025");
|
||||
BEAST_EXPECT(to_string(IOUAmount (-25, -3)) == "-0.025");
|
||||
BEAST_EXPECT(to_string(IOUAmount (25, 1)) == "250");
|
||||
BEAST_EXPECT(to_string(IOUAmount (-25, 1)) == "-250");
|
||||
BEAST_EXPECT(to_string(IOUAmount (2, 20)) == "2000000000000000e5");
|
||||
BEAST_EXPECT(to_string(IOUAmount (-2, -20)) == "-2000000000000000e-35");
|
||||
}
|
||||
|
||||
void testMulRatio()
|
||||
{
|
||||
testcase ("mulRatio");
|
||||
|
||||
/* The range for the mantissa when normalized */
|
||||
constexpr std::int64_t minMantissa = 1000000000000000ull;
|
||||
constexpr std::int64_t maxMantissa = 9999999999999999ull;
|
||||
// log(2,maxMantissa) ~ 53.15
|
||||
/* The range for the exponent when normalized */
|
||||
constexpr int minExponent = -96;
|
||||
constexpr int maxExponent = 80;
|
||||
constexpr auto maxUInt = std::numeric_limits<std::uint32_t>::max ();
|
||||
|
||||
{
|
||||
// multiply by a number that would overflow the mantissa, then
|
||||
// divide by the same number, and check we didn't lose any value
|
||||
IOUAmount bigMan (maxMantissa, 0);
|
||||
BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, true));
|
||||
// rounding mode shouldn't matter as the result is exact
|
||||
BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, false));
|
||||
}
|
||||
{
|
||||
// Similar test as above, but for negative values
|
||||
IOUAmount bigMan (-maxMantissa, 0);
|
||||
BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, true));
|
||||
// rounding mode shouldn't matter as the result is exact
|
||||
BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, false));
|
||||
}
|
||||
|
||||
{
|
||||
// small amounts
|
||||
IOUAmount tiny (minMantissa, minExponent);
|
||||
// Round up should give the smallest allowable number
|
||||
BEAST_EXPECT(tiny == mulRatio (tiny, 1, maxUInt, true));
|
||||
BEAST_EXPECT(tiny == mulRatio (tiny, maxUInt - 1, maxUInt, true));
|
||||
// rounding down should be zero
|
||||
BEAST_EXPECT(beast::zero == mulRatio (tiny, 1, maxUInt, false));
|
||||
BEAST_EXPECT(beast::zero == mulRatio (tiny, maxUInt - 1, maxUInt, false));
|
||||
|
||||
// tiny negative numbers
|
||||
IOUAmount tinyNeg (-minMantissa, minExponent);
|
||||
// Round up should give zero
|
||||
BEAST_EXPECT(zero == mulRatio (tinyNeg, 1, maxUInt, true));
|
||||
BEAST_EXPECT(zero == mulRatio (tinyNeg, maxUInt - 1, maxUInt, true));
|
||||
// rounding down should be tiny
|
||||
BEAST_EXPECT(tinyNeg == mulRatio (tinyNeg, 1, maxUInt, false));
|
||||
BEAST_EXPECT(tinyNeg == mulRatio (tinyNeg, maxUInt - 1, maxUInt, false));
|
||||
}
|
||||
|
||||
{
|
||||
// rounding
|
||||
{
|
||||
IOUAmount one (1, 0);
|
||||
auto const rup = mulRatio (one, maxUInt - 1, maxUInt, true);
|
||||
auto const rdown = mulRatio (one, maxUInt - 1, maxUInt, false);
|
||||
BEAST_EXPECT(rup.mantissa () - rdown.mantissa () == 1);
|
||||
}
|
||||
{
|
||||
IOUAmount big (maxMantissa, maxExponent);
|
||||
auto const rup = mulRatio (big, maxUInt - 1, maxUInt, true);
|
||||
auto const rdown = mulRatio (big, maxUInt - 1, maxUInt, false);
|
||||
BEAST_EXPECT(rup.mantissa () - rdown.mantissa () == 1);
|
||||
}
|
||||
|
||||
{
|
||||
IOUAmount negOne (-1, 0);
|
||||
auto const rup = mulRatio (negOne, maxUInt - 1, maxUInt, true);
|
||||
auto const rdown = mulRatio (negOne, maxUInt - 1, maxUInt, false);
|
||||
BEAST_EXPECT(rup.mantissa () - rdown.mantissa () == 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// division by zero
|
||||
IOUAmount one (1, 0);
|
||||
except ([&] {mulRatio (one, 1, 0, true);});
|
||||
}
|
||||
|
||||
{
|
||||
// overflow
|
||||
IOUAmount big (maxMantissa, maxExponent);
|
||||
except ([&] {mulRatio (big, 2, 0, true);});
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run ()
|
||||
{
|
||||
testZero ();
|
||||
testSigNum ();
|
||||
testBeastZero ();
|
||||
testComparisons ();
|
||||
testToString ();
|
||||
testMulRatio ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(IOUAmount,protocol,ripple);
|
||||
|
||||
} // ripple
|
||||
205
src/test/protocol/InnerObjectFormats_test.cpp
Normal file
205
src/test/protocol/InnerObjectFormats_test.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/contract.h>
|
||||
#include <ripple/protocol/InnerObjectFormats.h>
|
||||
#include <ripple/protocol/ErrorCodes.h> // RPC::containsError
|
||||
#include <ripple/json/json_reader.h> // Json::Reader
|
||||
#include <ripple/protocol/STParsedJSON.h> // STParsedJSONObject
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace InnerObjectFormatsUnitTestDetail
|
||||
{
|
||||
|
||||
struct TestJSONTxt
|
||||
{
|
||||
std::string const txt;
|
||||
bool const expectFail;
|
||||
};
|
||||
|
||||
static TestJSONTxt const testArray[] =
|
||||
{
|
||||
|
||||
// Valid SignerEntry
|
||||
{R"({
|
||||
"Account" : "rDg53Haik2475DJx8bjMDSDPj4VX7htaMd",
|
||||
"SignerEntries" :
|
||||
[
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"SignerWeight" : 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Account" : "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
|
||||
"SignerWeight" : 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum" : 7,
|
||||
"TransactionType" : "SignerListSet"
|
||||
})", false
|
||||
},
|
||||
|
||||
// SignerEntry missing Account
|
||||
{R"({
|
||||
"Account" : "rDg53Haik2475DJx8bjMDSDPj4VX7htaMd",
|
||||
"SignerEntries" :
|
||||
[
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"SignerWeight" : 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"SignerWeight" : 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum" : 7,
|
||||
"TransactionType" : "SignerListSet"
|
||||
})", true
|
||||
},
|
||||
|
||||
// SignerEntry missing SignerWeight
|
||||
{R"({
|
||||
"Account" : "rDg53Haik2475DJx8bjMDSDPj4VX7htaMd",
|
||||
"SignerEntries" :
|
||||
[
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"SignerWeight" : 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Account" : "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum" : 7,
|
||||
"TransactionType" : "SignerListSet"
|
||||
})", true
|
||||
},
|
||||
|
||||
// SignerEntry with unexpected Amount
|
||||
{R"({
|
||||
"Account" : "rDg53Haik2475DJx8bjMDSDPj4VX7htaMd",
|
||||
"SignerEntries" :
|
||||
[
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"SignerWeight" : 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Amount" : "1000000",
|
||||
"Account" : "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux",
|
||||
"SignerWeight" : 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum" : 7,
|
||||
"TransactionType" : "SignerListSet"
|
||||
})", true
|
||||
},
|
||||
|
||||
// SignerEntry with no Account and unexpected Amount
|
||||
{R"({
|
||||
"Account" : "rDg53Haik2475DJx8bjMDSDPj4VX7htaMd",
|
||||
"SignerEntries" :
|
||||
[
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Account" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
|
||||
"SignerWeight" : 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry" :
|
||||
{
|
||||
"Amount" : "10000000",
|
||||
"SignerWeight" : 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerQuorum" : 7,
|
||||
"TransactionType" : "SignerListSet"
|
||||
})", true
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
} // namespace InnerObjectFormatsUnitTestDetail
|
||||
|
||||
|
||||
class InnerObjectFormatsParsedJSON_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void run()
|
||||
{
|
||||
using namespace InnerObjectFormatsUnitTestDetail;
|
||||
|
||||
for (auto const& test : testArray)
|
||||
{
|
||||
Json::Value req;
|
||||
Json::Reader ().parse (test.txt, req);
|
||||
if (RPC::contains_error (req))
|
||||
{
|
||||
Throw<std::runtime_error> (
|
||||
"Internal InnerObjectFormatsParsedJSON error. Bad JSON.");
|
||||
}
|
||||
STParsedJSONObject parsed ("request", req);
|
||||
bool const noObj = parsed.object == boost::none;
|
||||
if ( noObj == test.expectFail )
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errStr ("Unexpected STParsedJSON result on:\n");
|
||||
errStr += test.txt;
|
||||
fail (errStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(InnerObjectFormatsParsedJSON,ripple_app,ripple);
|
||||
|
||||
} // ripple
|
||||
494
src/test/protocol/Issue_test.cpp
Normal file
494
src/test/protocol/Issue_test.cpp
Normal file
@@ -0,0 +1,494 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/UnorderedContainers.h>
|
||||
#include <ripple/protocol/Book.h>
|
||||
#include <ripple/protocol/Issue.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <typeinfo>
|
||||
#include <unordered_set>
|
||||
|
||||
#if BEAST_MSVC
|
||||
# define STL_SET_HAS_EMPLACE 1
|
||||
#else
|
||||
# define STL_SET_HAS_EMPLACE 0
|
||||
#endif
|
||||
|
||||
#ifndef RIPPLE_ASSETS_ENABLE_STD_HASH
|
||||
# if BEAST_MAC || BEAST_IOS
|
||||
# define RIPPLE_ASSETS_ENABLE_STD_HASH 0
|
||||
# else
|
||||
# define RIPPLE_ASSETS_ENABLE_STD_HASH 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Issue_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
// Comparison, hash tests for uint60 (via base_uint)
|
||||
template <typename Unsigned>
|
||||
void testUnsigned ()
|
||||
{
|
||||
Unsigned const u1 (1);
|
||||
Unsigned const u2 (2);
|
||||
Unsigned const u3 (3);
|
||||
|
||||
BEAST_EXPECT(u1 != u2);
|
||||
BEAST_EXPECT(u1 < u2);
|
||||
BEAST_EXPECT(u1 <= u2);
|
||||
BEAST_EXPECT(u2 <= u2);
|
||||
BEAST_EXPECT(u2 == u2);
|
||||
BEAST_EXPECT(u2 >= u2);
|
||||
BEAST_EXPECT(u3 >= u2);
|
||||
BEAST_EXPECT(u3 > u2);
|
||||
|
||||
std::hash <Unsigned> hash;
|
||||
|
||||
BEAST_EXPECT(hash (u1) == hash (u1));
|
||||
BEAST_EXPECT(hash (u2) == hash (u2));
|
||||
BEAST_EXPECT(hash (u3) == hash (u3));
|
||||
BEAST_EXPECT(hash (u1) != hash (u2));
|
||||
BEAST_EXPECT(hash (u1) != hash (u3));
|
||||
BEAST_EXPECT(hash (u2) != hash (u3));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Comparison, hash tests for Issue
|
||||
template <class Issue>
|
||||
void testIssue ()
|
||||
{
|
||||
Currency const c1 (1); AccountID const i1 (1);
|
||||
Currency const c2 (2); AccountID const i2 (2);
|
||||
Currency const c3 (3); AccountID const i3 (3);
|
||||
|
||||
BEAST_EXPECT(Issue (c1, i1) != Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c1, i1) < Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c1, i1) <= Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c2, i1) <= Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c2, i1) == Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c2, i1) >= Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c3, i1) >= Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c3, i1) > Issue (c2, i1));
|
||||
BEAST_EXPECT(Issue (c1, i1) != Issue (c1, i2));
|
||||
BEAST_EXPECT(Issue (c1, i1) < Issue (c1, i2));
|
||||
BEAST_EXPECT(Issue (c1, i1) <= Issue (c1, i2));
|
||||
BEAST_EXPECT(Issue (c1, i2) <= Issue (c1, i2));
|
||||
BEAST_EXPECT(Issue (c1, i2) == Issue (c1, i2));
|
||||
BEAST_EXPECT(Issue (c1, i2) >= Issue (c1, i2));
|
||||
BEAST_EXPECT(Issue (c1, i3) >= Issue (c1, i2));
|
||||
BEAST_EXPECT(Issue (c1, i3) > Issue (c1, i2));
|
||||
|
||||
std::hash <Issue> hash;
|
||||
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) == hash (Issue (c1, i1)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i2)) == hash (Issue (c1, i2)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i3)) == hash (Issue (c1, i3)));
|
||||
BEAST_EXPECT(hash (Issue (c2, i1)) == hash (Issue (c2, i1)));
|
||||
BEAST_EXPECT(hash (Issue (c2, i2)) == hash (Issue (c2, i2)));
|
||||
BEAST_EXPECT(hash (Issue (c2, i3)) == hash (Issue (c2, i3)));
|
||||
BEAST_EXPECT(hash (Issue (c3, i1)) == hash (Issue (c3, i1)));
|
||||
BEAST_EXPECT(hash (Issue (c3, i2)) == hash (Issue (c3, i2)));
|
||||
BEAST_EXPECT(hash (Issue (c3, i3)) == hash (Issue (c3, i3)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c1, i2)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c1, i3)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c2, i1)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c2, i2)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c2, i3)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c3, i1)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c3, i2)));
|
||||
BEAST_EXPECT(hash (Issue (c1, i1)) != hash (Issue (c3, i3)));
|
||||
}
|
||||
|
||||
template <class Set>
|
||||
void testIssueSet ()
|
||||
{
|
||||
Currency const c1 (1);
|
||||
AccountID const i1 (1);
|
||||
Currency const c2 (2);
|
||||
AccountID const i2 (2);
|
||||
Issue const a1 (c1, i1);
|
||||
Issue const a2 (c2, i2);
|
||||
|
||||
{
|
||||
Set c;
|
||||
|
||||
c.insert (a1);
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
c.insert (a2);
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i2)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c2, i2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
}
|
||||
|
||||
{
|
||||
Set c;
|
||||
|
||||
c.insert (a1);
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
c.insert (a2);
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i2)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c2, i2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
|
||||
#if STL_SET_HAS_EMPLACE
|
||||
c.emplace (c1, i1);
|
||||
if (! BEAST_EXPECT(c.size() == 1)) return;
|
||||
c.emplace (c2, i2);
|
||||
if (! BEAST_EXPECT(c.size() == 2)) return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <class Map>
|
||||
void testIssueMap ()
|
||||
{
|
||||
Currency const c1 (1);
|
||||
AccountID const i1 (1);
|
||||
Currency const c2 (2);
|
||||
AccountID const i2 (2);
|
||||
Issue const a1 (c1, i1);
|
||||
Issue const a2 (c2, i2);
|
||||
|
||||
{
|
||||
Map c;
|
||||
|
||||
c.insert (std::make_pair (a1, 1));
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
c.insert (std::make_pair (a2, 2));
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i2)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c2, i2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
}
|
||||
|
||||
{
|
||||
Map c;
|
||||
|
||||
c.insert (std::make_pair (a1, 1));
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
c.insert (std::make_pair (a2, 2));
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i2)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c1, i1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Issue (c2, i2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
}
|
||||
}
|
||||
|
||||
void testIssueSets ()
|
||||
{
|
||||
testcase ("std::set <Issue>");
|
||||
testIssueSet <std::set <Issue>> ();
|
||||
|
||||
testcase ("std::set <Issue>");
|
||||
testIssueSet <std::set <Issue>> ();
|
||||
|
||||
#if RIPPLE_ASSETS_ENABLE_STD_HASH
|
||||
testcase ("std::unordered_set <Issue>");
|
||||
testIssueSet <std::unordered_set <Issue>> ();
|
||||
|
||||
testcase ("std::unordered_set <Issue>");
|
||||
testIssueSet <std::unordered_set <Issue>> ();
|
||||
#endif
|
||||
|
||||
testcase ("hash_set <Issue>");
|
||||
testIssueSet <hash_set <Issue>> ();
|
||||
|
||||
testcase ("hash_set <Issue>");
|
||||
testIssueSet <hash_set <Issue>> ();
|
||||
}
|
||||
|
||||
void testIssueMaps ()
|
||||
{
|
||||
testcase ("std::map <Issue, int>");
|
||||
testIssueMap <std::map <Issue, int>> ();
|
||||
|
||||
testcase ("std::map <Issue, int>");
|
||||
testIssueMap <std::map <Issue, int>> ();
|
||||
|
||||
#if RIPPLE_ASSETS_ENABLE_STD_HASH
|
||||
testcase ("std::unordered_map <Issue, int>");
|
||||
testIssueMap <std::unordered_map <Issue, int>> ();
|
||||
|
||||
testcase ("std::unordered_map <Issue, int>");
|
||||
testIssueMap <std::unordered_map <Issue, int>> ();
|
||||
|
||||
testcase ("hash_map <Issue, int>");
|
||||
testIssueMap <hash_map <Issue, int>> ();
|
||||
|
||||
testcase ("hash_map <Issue, int>");
|
||||
testIssueMap <hash_map <Issue, int>> ();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Comparison, hash tests for Book
|
||||
template <class Book>
|
||||
void testBook ()
|
||||
{
|
||||
Currency const c1 (1); AccountID const i1 (1);
|
||||
Currency const c2 (2); AccountID const i2 (2);
|
||||
Currency const c3 (3); AccountID const i3 (3);
|
||||
|
||||
Issue a1 (c1, i1);
|
||||
Issue a2 (c1, i2);
|
||||
Issue a3 (c2, i2);
|
||||
Issue a4 (c3, i2);
|
||||
|
||||
BEAST_EXPECT(Book (a1, a2) != Book (a2, a3));
|
||||
BEAST_EXPECT(Book (a1, a2) < Book (a2, a3));
|
||||
BEAST_EXPECT(Book (a1, a2) <= Book (a2, a3));
|
||||
BEAST_EXPECT(Book (a2, a3) <= Book (a2, a3));
|
||||
BEAST_EXPECT(Book (a2, a3) == Book (a2, a3));
|
||||
BEAST_EXPECT(Book (a2, a3) >= Book (a2, a3));
|
||||
BEAST_EXPECT(Book (a3, a4) >= Book (a2, a3));
|
||||
BEAST_EXPECT(Book (a3, a4) > Book (a2, a3));
|
||||
|
||||
std::hash <Book> hash;
|
||||
|
||||
// log << std::hex << hash (Book (a1, a2));
|
||||
// log << std::hex << hash (Book (a1, a2));
|
||||
//
|
||||
// log << std::hex << hash (Book (a1, a3));
|
||||
// log << std::hex << hash (Book (a1, a3));
|
||||
//
|
||||
// log << std::hex << hash (Book (a1, a4));
|
||||
// log << std::hex << hash (Book (a1, a4));
|
||||
//
|
||||
// log << std::hex << hash (Book (a2, a3));
|
||||
// log << std::hex << hash (Book (a2, a3));
|
||||
//
|
||||
// log << std::hex << hash (Book (a2, a4));
|
||||
// log << std::hex << hash (Book (a2, a4));
|
||||
//
|
||||
// log << std::hex << hash (Book (a3, a4));
|
||||
// log << std::hex << hash (Book (a3, a4));
|
||||
|
||||
BEAST_EXPECT(hash (Book (a1, a2)) == hash (Book (a1, a2)));
|
||||
BEAST_EXPECT(hash (Book (a1, a3)) == hash (Book (a1, a3)));
|
||||
BEAST_EXPECT(hash (Book (a1, a4)) == hash (Book (a1, a4)));
|
||||
BEAST_EXPECT(hash (Book (a2, a3)) == hash (Book (a2, a3)));
|
||||
BEAST_EXPECT(hash (Book (a2, a4)) == hash (Book (a2, a4)));
|
||||
BEAST_EXPECT(hash (Book (a3, a4)) == hash (Book (a3, a4)));
|
||||
|
||||
BEAST_EXPECT(hash (Book (a1, a2)) != hash (Book (a1, a3)));
|
||||
BEAST_EXPECT(hash (Book (a1, a2)) != hash (Book (a1, a4)));
|
||||
BEAST_EXPECT(hash (Book (a1, a2)) != hash (Book (a2, a3)));
|
||||
BEAST_EXPECT(hash (Book (a1, a2)) != hash (Book (a2, a4)));
|
||||
BEAST_EXPECT(hash (Book (a1, a2)) != hash (Book (a3, a4)));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <class Set>
|
||||
void testBookSet ()
|
||||
{
|
||||
Currency const c1 (1);
|
||||
AccountID const i1 (1);
|
||||
Currency const c2 (2);
|
||||
AccountID const i2 (2);
|
||||
Issue const a1 (c1, i1);
|
||||
Issue const a2 (c2, i2);
|
||||
Book const b1 (a1, a2);
|
||||
Book const b2 (a2, a1);
|
||||
|
||||
{
|
||||
Set c;
|
||||
|
||||
c.insert (b1);
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
c.insert (b2);
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a1)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a2, a1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
}
|
||||
|
||||
{
|
||||
Set c;
|
||||
|
||||
c.insert (b1);
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
c.insert (b2);
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a1)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a2, a1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
|
||||
#if STL_SET_HAS_EMPLACE
|
||||
c.emplace (a1, a2);
|
||||
if (! BEAST_EXPECT(c.size() == 1)) return;
|
||||
c.emplace (a2, a1);
|
||||
if (! BEAST_EXPECT(c.size() == 2)) return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <class Map>
|
||||
void testBookMap ()
|
||||
{
|
||||
Currency const c1 (1);
|
||||
AccountID const i1 (1);
|
||||
Currency const c2 (2);
|
||||
AccountID const i2 (2);
|
||||
Issue const a1 (c1, i1);
|
||||
Issue const a2 (c2, i2);
|
||||
Book const b1 (a1, a2);
|
||||
Book const b2 (a2, a1);
|
||||
|
||||
//typename Map::value_type value_type;
|
||||
//std::pair <Book const, int> value_type;
|
||||
|
||||
{
|
||||
Map c;
|
||||
|
||||
//c.insert (value_type (b1, 1));
|
||||
c.insert (std::make_pair (b1, 1));
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
//c.insert (value_type (b2, 2));
|
||||
c.insert (std::make_pair (b2, 1));
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a1)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a2, a1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
}
|
||||
|
||||
{
|
||||
Map c;
|
||||
|
||||
//c.insert (value_type (b1, 1));
|
||||
c.insert (std::make_pair (b1, 1));
|
||||
if (! BEAST_EXPECT(c.size () == 1)) return;
|
||||
//c.insert (value_type (b2, 2));
|
||||
c.insert (std::make_pair (b2, 1));
|
||||
if (! BEAST_EXPECT(c.size () == 2)) return;
|
||||
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a1)) == 0)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a1, a2)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.erase (Book (a2, a1)) == 1)) return;
|
||||
if (! BEAST_EXPECT(c.empty ())) return;
|
||||
}
|
||||
}
|
||||
|
||||
void testBookSets ()
|
||||
{
|
||||
testcase ("std::set <Book>");
|
||||
testBookSet <std::set <Book>> ();
|
||||
|
||||
testcase ("std::set <Book>");
|
||||
testBookSet <std::set <Book>> ();
|
||||
|
||||
#if RIPPLE_ASSETS_ENABLE_STD_HASH
|
||||
testcase ("std::unordered_set <Book>");
|
||||
testBookSet <std::unordered_set <Book>> ();
|
||||
|
||||
testcase ("std::unordered_set <Book>");
|
||||
testBookSet <std::unordered_set <Book>> ();
|
||||
#endif
|
||||
|
||||
testcase ("hash_set <Book>");
|
||||
testBookSet <hash_set <Book>> ();
|
||||
|
||||
testcase ("hash_set <Book>");
|
||||
testBookSet <hash_set <Book>> ();
|
||||
}
|
||||
|
||||
void testBookMaps ()
|
||||
{
|
||||
testcase ("std::map <Book, int>");
|
||||
testBookMap <std::map <Book, int>> ();
|
||||
|
||||
testcase ("std::map <Book, int>");
|
||||
testBookMap <std::map <Book, int>> ();
|
||||
|
||||
#if RIPPLE_ASSETS_ENABLE_STD_HASH
|
||||
testcase ("std::unordered_map <Book, int>");
|
||||
testBookMap <std::unordered_map <Book, int>> ();
|
||||
|
||||
testcase ("std::unordered_map <Book, int>");
|
||||
testBookMap <std::unordered_map <Book, int>> ();
|
||||
|
||||
testcase ("hash_map <Book, int>");
|
||||
testBookMap <hash_map <Book, int>> ();
|
||||
|
||||
testcase ("hash_map <Book, int>");
|
||||
testBookMap <hash_map <Book, int>> ();
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run()
|
||||
{
|
||||
testcase ("Currency");
|
||||
testUnsigned <Currency> ();
|
||||
|
||||
testcase ("AccountID");
|
||||
testUnsigned <AccountID> ();
|
||||
|
||||
// ---
|
||||
|
||||
testcase ("Issue");
|
||||
testIssue <Issue> ();
|
||||
|
||||
testcase ("Issue");
|
||||
testIssue <Issue> ();
|
||||
|
||||
testIssueSets ();
|
||||
testIssueMaps ();
|
||||
|
||||
// ---
|
||||
|
||||
testcase ("Book");
|
||||
testBook <Book> ();
|
||||
|
||||
testcase ("Book");
|
||||
testBook <Book> ();
|
||||
|
||||
testBookSets ();
|
||||
testBookMaps ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Issue,protocol,ripple);
|
||||
|
||||
}
|
||||
395
src/test/protocol/PublicKey_test.cpp
Normal file
395
src/test/protocol/PublicKey_test.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/PublicKey.h>
|
||||
#include <ripple/protocol/SecretKey.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class PublicKey_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
using blob = std::vector<std::uint8_t>;
|
||||
|
||||
template <class FwdIter, class Container>
|
||||
static
|
||||
void
|
||||
hex_to_binary (FwdIter first, FwdIter last, Container& out)
|
||||
{
|
||||
struct Table
|
||||
{
|
||||
int val[256];
|
||||
Table ()
|
||||
{
|
||||
std::fill (val, val+256, 0);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
val ['0'+i] = i;
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
val ['A'+i] = 10 + i;
|
||||
val ['a'+i] = 10 + i;
|
||||
}
|
||||
}
|
||||
int operator[] (int i)
|
||||
{
|
||||
return val[i];
|
||||
}
|
||||
};
|
||||
|
||||
static Table lut;
|
||||
out.reserve (std::distance (first, last) / 2);
|
||||
while (first != last)
|
||||
{
|
||||
auto const hi (lut[(*first++)]);
|
||||
auto const lo (lut[(*first++)]);
|
||||
out.push_back ((hi*16)+lo);
|
||||
}
|
||||
}
|
||||
|
||||
blob
|
||||
sig (std::string const& hex)
|
||||
{
|
||||
blob b;
|
||||
hex_to_binary (hex.begin (), hex.end (), b);
|
||||
return b;
|
||||
}
|
||||
|
||||
bool
|
||||
check (boost::optional<ECDSACanonicality> answer,
|
||||
std::string const& s)
|
||||
{
|
||||
return ecdsaCanonicality(makeSlice(sig(s))) ==
|
||||
answer;
|
||||
}
|
||||
|
||||
void testCanonical()
|
||||
{
|
||||
testcase ("Canonical");
|
||||
|
||||
// Fully canonical
|
||||
BEAST_EXPECT(check(ECDSACanonicality::fullyCanonical,
|
||||
"3045"
|
||||
"022100FF478110D1D4294471EC76E0157540C2181F47DEBD25D7F9E7DDCCCD47EEE905"
|
||||
"0220078F07CDAE6C240855D084AD91D1479609533C147C93B0AEF19BC9724D003F28"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::fullyCanonical,
|
||||
"3045"
|
||||
"0221009218248292F1762D8A51BE80F8A7F2CD288D810CE781D5955700DA1684DF1D2D"
|
||||
"022041A1EE1746BFD72C9760CC93A7AAA8047D52C8833A03A20EAAE92EA19717B454"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::fullyCanonical,
|
||||
"3044"
|
||||
"02206A9E43775F73B6D1EC420E4DDD222A80D4C6DF5D1BEECC431A91B63C928B7581"
|
||||
"022023E9CC2D61DDA6F73EAA6BCB12688BEB0F434769276B3127E4044ED895C9D96B"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::fullyCanonical,
|
||||
"3044"
|
||||
"022056E720007221F3CD4EFBB6352741D8E5A0968D48D8D032C2FBC4F6304AD1D04E"
|
||||
"02201F39EB392C20D7801C3E8D81D487E742FA84A1665E923225BD6323847C71879F"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::fullyCanonical,
|
||||
"3045"
|
||||
"022100FDFD5AD05518CEA0017A2DCB5C4DF61E7C73B6D3A38E7AE93210A1564E8C2F12"
|
||||
"0220214FF061CCC123C81D0BB9D0EDEA04CD40D96BF1425D311DA62A7096BB18EA18"));
|
||||
|
||||
// Canonical but not fully canonical
|
||||
BEAST_EXPECT(check(ECDSACanonicality::canonical,
|
||||
"3046"
|
||||
"022100F477B3FA6F31C7CB3A0D1AD94A231FDD24B8D78862EE334CEA7CD08F6CBC0A1B"
|
||||
"022100928E6BCF1ED2684679730C5414AEC48FD62282B090041C41453C1D064AF597A1"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::canonical,
|
||||
"3045"
|
||||
"022063E7C7CA93CB2400E413A342C027D00665F8BAB9C22EF0A7B8AE3AAF092230B6"
|
||||
"0221008F2E8BB7D09521ABBC277717B14B93170AE6465C5A1B36561099319C4BEB254C"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::canonical,
|
||||
"3046"
|
||||
"02210099DCA1188663DDEA506A06A7B20C2B7D8C26AFF41DECE69D6C5F7C967D32625F"
|
||||
"022100897658A6B1F9EEE5D140D7A332DA0BD73BB98974EA53F6201B01C1B594F286EA"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::canonical,
|
||||
"3045"
|
||||
"02200855DE366E4E323AA2CE2A25674401A7D11F72EC432770D07F7B57DF7387AEC0"
|
||||
"022100DA4C6ADDEA14888858DE2AC5B91ED9050D6972BB388DEF582628CEE32869AE35"));
|
||||
|
||||
// valid
|
||||
BEAST_EXPECT(check(ECDSACanonicality::fullyCanonical,
|
||||
"3006"
|
||||
"020101"
|
||||
"020102"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::fullyCanonical,
|
||||
"3044"
|
||||
"02203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df0c"
|
||||
"022030b61dd36543125d56b9f9f3a1f53189e5af33cdda8d77a5209aec03978fa001"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::canonical,
|
||||
"3045"
|
||||
"0220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a"
|
||||
"0221008fffd599910eefe00bc803c688eca1d2ba7f6b180620eaa03488e6585db6ba01"));
|
||||
BEAST_EXPECT(check(ECDSACanonicality::canonical,
|
||||
"3046"
|
||||
"022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a"
|
||||
"0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba"));
|
||||
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3005"
|
||||
"0201FF"
|
||||
"0200"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3006"
|
||||
"020101"
|
||||
"020202"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3006"
|
||||
"020701"
|
||||
"020102"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3006"
|
||||
"020401"
|
||||
"020102"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3006"
|
||||
"020501"
|
||||
"020102"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3006"
|
||||
"020201"
|
||||
"020102"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3006"
|
||||
"020301"
|
||||
"020202"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3006"
|
||||
"020401"
|
||||
"020202"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3047"
|
||||
"0221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3144"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3045"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"301F"
|
||||
"01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3045"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed00"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3044"
|
||||
"01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3024"
|
||||
"0200"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3044"
|
||||
"02208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3045"
|
||||
"0221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"02202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3044"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105012"
|
||||
"02d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3024"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"0200"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3044"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"0220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
BEAST_EXPECT(check(boost::none,
|
||||
"3045"
|
||||
"02205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105"
|
||||
"0221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed"));
|
||||
}
|
||||
|
||||
void testBase58 (KeyType keyType)
|
||||
{
|
||||
// Try converting short, long and malformed data
|
||||
BEAST_EXPECT(!parseBase58<PublicKey> (TOKEN_NODE_PUBLIC, ""));
|
||||
BEAST_EXPECT(!parseBase58<PublicKey> (TOKEN_NODE_PUBLIC, " "));
|
||||
BEAST_EXPECT(!parseBase58<PublicKey> (TOKEN_NODE_PUBLIC, "!ty89234gh45"));
|
||||
|
||||
auto const good = toBase58 (
|
||||
TokenType::TOKEN_NODE_PUBLIC,
|
||||
derivePublicKey (
|
||||
keyType,
|
||||
randomSecretKey()));
|
||||
|
||||
// Short (non-empty) strings
|
||||
{
|
||||
auto s = good;
|
||||
|
||||
// Remove all characters from the string in random order:
|
||||
std::hash<std::string> r;
|
||||
|
||||
while (!s.empty())
|
||||
{
|
||||
s.erase (r(s) % s.size(), 1);
|
||||
BEAST_EXPECT(!parseBase58<PublicKey> (TOKEN_NODE_PUBLIC, s));
|
||||
}
|
||||
}
|
||||
|
||||
// Long strings
|
||||
for (std::size_t i = 1; i != 16; i++)
|
||||
{
|
||||
auto s = good;
|
||||
s.resize (s.size() + i, s[i % s.size()]);
|
||||
BEAST_EXPECT(!parseBase58<PublicKey> (TOKEN_NODE_PUBLIC, s));
|
||||
}
|
||||
|
||||
// Strings with invalid Base58 characters
|
||||
for (auto c : std::string ("0IOl"))
|
||||
{
|
||||
for (std::size_t i = 0; i != good.size(); ++i)
|
||||
{
|
||||
auto s = good;
|
||||
s[i % s.size()] = c;
|
||||
BEAST_EXPECT(!parseBase58<PublicKey> (TOKEN_NODE_PUBLIC, s));
|
||||
}
|
||||
}
|
||||
|
||||
// Strings with incorrect prefix
|
||||
{
|
||||
auto s = good;
|
||||
|
||||
for (auto c : std::string("apsrJqtv7"))
|
||||
{
|
||||
s[0] = c;
|
||||
BEAST_EXPECT(!parseBase58<PublicKey> (TOKEN_NODE_PUBLIC, s));
|
||||
}
|
||||
}
|
||||
|
||||
// Try some random secret keys
|
||||
std::array <PublicKey, 32> keys;
|
||||
|
||||
for (std::size_t i = 0; i != keys.size(); ++i)
|
||||
keys[i] = derivePublicKey (keyType, randomSecretKey());
|
||||
|
||||
for (std::size_t i = 0; i != keys.size(); ++i)
|
||||
{
|
||||
auto const si = toBase58 (
|
||||
TokenType::TOKEN_NODE_PUBLIC,
|
||||
keys[i]);
|
||||
BEAST_EXPECT(!si.empty());
|
||||
|
||||
auto const ski = parseBase58<PublicKey> (
|
||||
TOKEN_NODE_PUBLIC, si);
|
||||
BEAST_EXPECT(ski && (keys[i] == *ski));
|
||||
|
||||
for (std::size_t j = i; j != keys.size(); ++j)
|
||||
{
|
||||
BEAST_EXPECT((keys[i] == keys[j]) == (i == j));
|
||||
|
||||
auto const sj = toBase58 (
|
||||
TokenType::TOKEN_NODE_PUBLIC,
|
||||
keys[j]);
|
||||
|
||||
BEAST_EXPECT((si == sj) == (i == j));
|
||||
|
||||
auto const skj = parseBase58<PublicKey> (
|
||||
TOKEN_NODE_PUBLIC, sj);
|
||||
BEAST_EXPECT(skj && (keys[j] == *skj));
|
||||
|
||||
BEAST_EXPECT((*ski == *skj) == (i == j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testBase58 ()
|
||||
{
|
||||
testcase ("Base58: secp256k1");
|
||||
|
||||
{
|
||||
auto const pk1 = derivePublicKey (
|
||||
KeyType::secp256k1,
|
||||
generateSecretKey (
|
||||
KeyType::secp256k1,
|
||||
generateSeed ("masterpassphrase")));
|
||||
|
||||
auto const pk2 = parseBase58<PublicKey> (
|
||||
TOKEN_NODE_PUBLIC,
|
||||
"n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9");
|
||||
BEAST_EXPECT(pk2);
|
||||
|
||||
BEAST_EXPECT(pk1 == *pk2);
|
||||
}
|
||||
|
||||
testBase58 (KeyType::secp256k1);
|
||||
|
||||
testcase ("Base58: ed25519");
|
||||
|
||||
{
|
||||
auto const pk1 = derivePublicKey (
|
||||
KeyType::ed25519,
|
||||
generateSecretKey (
|
||||
KeyType::ed25519,
|
||||
generateSeed ("masterpassphrase")));
|
||||
|
||||
auto const pk2 = parseBase58<PublicKey> (
|
||||
TOKEN_NODE_PUBLIC,
|
||||
"nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf");
|
||||
BEAST_EXPECT(pk2);
|
||||
|
||||
BEAST_EXPECT(pk1 == *pk2);
|
||||
}
|
||||
|
||||
testBase58 (KeyType::ed25519);
|
||||
}
|
||||
|
||||
void testMiscOperations ()
|
||||
{
|
||||
testcase ("Miscellaneous operations");
|
||||
|
||||
auto const pk1 = derivePublicKey (
|
||||
KeyType::secp256k1,
|
||||
generateSecretKey (
|
||||
KeyType::secp256k1,
|
||||
generateSeed ("masterpassphrase")));
|
||||
|
||||
PublicKey pk2 (pk1);
|
||||
BEAST_EXPECT(pk1 == pk2);
|
||||
BEAST_EXPECT(pk2 == pk1);
|
||||
|
||||
PublicKey pk3;
|
||||
pk3 = pk2;
|
||||
BEAST_EXPECT(pk3 == pk2);
|
||||
BEAST_EXPECT(pk1 == pk3);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testBase58();
|
||||
testCanonical();
|
||||
testMiscOperations();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(PublicKey,protocol,ripple);
|
||||
|
||||
} // ripple
|
||||
328
src/test/protocol/Quality_test.cpp
Normal file
328
src/test/protocol/Quality_test.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/Quality.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Quality_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
// Create a raw, non-integral amount from mantissa and exponent
|
||||
STAmount
|
||||
static raw (std::uint64_t mantissa, int exponent)
|
||||
{
|
||||
return STAmount ({Currency(3), AccountID(3)}, mantissa, exponent);
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
static
|
||||
STAmount
|
||||
amount (Integer integer,
|
||||
std::enable_if_t <std::is_signed <Integer>::value>* = 0)
|
||||
{
|
||||
static_assert (std::is_integral <Integer>::value, "");
|
||||
return STAmount (integer, false);
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
static
|
||||
STAmount
|
||||
amount (Integer integer,
|
||||
std::enable_if_t <! std::is_signed <Integer>::value>* = 0)
|
||||
{
|
||||
static_assert (std::is_integral <Integer>::value, "");
|
||||
if (integer < 0)
|
||||
return STAmount (-integer, true);
|
||||
return STAmount (integer, false);
|
||||
}
|
||||
|
||||
template <class In, class Out>
|
||||
static
|
||||
Amounts
|
||||
amounts (In in, Out out)
|
||||
{
|
||||
return Amounts (amount(in), amount(out));
|
||||
}
|
||||
|
||||
template <class In1, class Out1, class Int, class In2, class Out2>
|
||||
void
|
||||
ceil_in (Quality const& q,
|
||||
In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
|
||||
{
|
||||
auto expect_result (amounts (in_expected, out_expected));
|
||||
auto actual_result (q.ceil_in (
|
||||
amounts (in, out), amount (limit)));
|
||||
|
||||
BEAST_EXPECT(actual_result == expect_result);
|
||||
}
|
||||
|
||||
template <class In1, class Out1, class Int, class In2, class Out2>
|
||||
void
|
||||
ceil_out (Quality const& q,
|
||||
In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
|
||||
{
|
||||
auto const expect_result (amounts (in_expected, out_expected));
|
||||
auto const actual_result (q.ceil_out (
|
||||
amounts (in, out), amount (limit)));
|
||||
|
||||
BEAST_EXPECT(actual_result == expect_result);
|
||||
}
|
||||
|
||||
void
|
||||
test_ceil_in ()
|
||||
{
|
||||
testcase ("ceil_in");
|
||||
|
||||
{
|
||||
// 1 in, 1 out:
|
||||
Quality q (Amounts (amount(1), amount(1)));
|
||||
|
||||
ceil_in (q,
|
||||
1, 1, // 1 in, 1 out
|
||||
1, // limit: 1
|
||||
1, 1); // 1 in, 1 out
|
||||
|
||||
ceil_in (q,
|
||||
10, 10, // 10 in, 10 out
|
||||
5, // limit: 5
|
||||
5, 5); // 5 in, 5 out
|
||||
|
||||
ceil_in (q,
|
||||
5, 5, // 5 in, 5 out
|
||||
10, // limit: 10
|
||||
5, 5); // 5 in, 5 out
|
||||
}
|
||||
|
||||
{
|
||||
// 1 in, 2 out:
|
||||
Quality q (Amounts (amount(1), amount(2)));
|
||||
|
||||
ceil_in (q,
|
||||
40, 80, // 40 in, 80 out
|
||||
40, // limit: 40
|
||||
40, 80); // 40 in, 20 out
|
||||
|
||||
ceil_in (q,
|
||||
40, 80, // 40 in, 80 out
|
||||
20, // limit: 20
|
||||
20, 40); // 20 in, 40 out
|
||||
|
||||
ceil_in (q,
|
||||
40, 80, // 40 in, 80 out
|
||||
60, // limit: 60
|
||||
40, 80); // 40 in, 80 out
|
||||
}
|
||||
|
||||
{
|
||||
// 2 in, 1 out:
|
||||
Quality q (Amounts (amount(2), amount(1)));
|
||||
|
||||
ceil_in (q,
|
||||
40, 20, // 40 in, 20 out
|
||||
20, // limit: 20
|
||||
20, 10); // 20 in, 10 out
|
||||
|
||||
ceil_in (q,
|
||||
40, 20, // 40 in, 20 out
|
||||
40, // limit: 40
|
||||
40, 20); // 40 in, 20 out
|
||||
|
||||
ceil_in (q,
|
||||
40, 20, // 40 in, 20 out
|
||||
50, // limit: 40
|
||||
40, 20); // 40 in, 20 out
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_ceil_out ()
|
||||
{
|
||||
testcase ("ceil_out");
|
||||
|
||||
{
|
||||
// 1 in, 1 out:
|
||||
Quality q (Amounts (amount(1),amount(1)));
|
||||
|
||||
ceil_out (q,
|
||||
1, 1, // 1 in, 1 out
|
||||
1, // limit 1
|
||||
1, 1); // 1 in, 1 out
|
||||
|
||||
ceil_out (q,
|
||||
10, 10, // 10 in, 10 out
|
||||
5, // limit 5
|
||||
5, 5); // 5 in, 5 out
|
||||
|
||||
ceil_out (q,
|
||||
10, 10, // 10 in, 10 out
|
||||
20, // limit 20
|
||||
10, 10); // 10 in, 10 out
|
||||
}
|
||||
|
||||
{
|
||||
// 1 in, 2 out:
|
||||
Quality q (Amounts (amount(1),amount(2)));
|
||||
|
||||
ceil_out (q,
|
||||
40, 80, // 40 in, 80 out
|
||||
40, // limit 40
|
||||
20, 40); // 20 in, 40 out
|
||||
|
||||
ceil_out (q,
|
||||
40, 80, // 40 in, 80 out
|
||||
80, // limit 80
|
||||
40, 80); // 40 in, 80 out
|
||||
|
||||
ceil_out (q,
|
||||
40, 80, // 40 in, 80 out
|
||||
100, // limit 100
|
||||
40, 80); // 40 in, 80 out
|
||||
}
|
||||
|
||||
{
|
||||
// 2 in, 1 out:
|
||||
Quality q (Amounts (amount(2),amount(1)));
|
||||
|
||||
ceil_out (q,
|
||||
40, 20, // 40 in, 20 out
|
||||
20, // limit 20
|
||||
40, 20); // 40 in, 20 out
|
||||
|
||||
ceil_out (q,
|
||||
40, 20, // 40 in, 20 out
|
||||
40, // limit 40
|
||||
40, 20); // 40 in, 20 out
|
||||
|
||||
ceil_out (q,
|
||||
40, 20, // 40 in, 20 out
|
||||
10, // limit 10
|
||||
20, 10); // 20 in, 10 out
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_raw()
|
||||
{
|
||||
testcase ("raw");
|
||||
|
||||
{
|
||||
Quality q (0x5d048191fb9130daull); // 126836389.7680090
|
||||
Amounts const value (
|
||||
amount(349469768), // 349.469768 XRP
|
||||
raw (2755280000000000ull, -15)); // 2.75528
|
||||
STAmount const limit (
|
||||
raw (4131113916555555, -16)); // .4131113916555555
|
||||
Amounts const result (
|
||||
q.ceil_out (value, limit));
|
||||
BEAST_EXPECT(result.in != zero);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_comparisons()
|
||||
{
|
||||
testcase ("comparisons");
|
||||
|
||||
STAmount const amount1 (noIssue(), 231);
|
||||
STAmount const amount2 (noIssue(), 462);
|
||||
STAmount const amount3 (noIssue(), 924);
|
||||
|
||||
Quality const q11 (Amounts (amount1, amount1));
|
||||
Quality const q12 (Amounts (amount1, amount2));
|
||||
Quality const q13 (Amounts (amount1, amount3));
|
||||
Quality const q21 (Amounts (amount2, amount1));
|
||||
Quality const q31 (Amounts (amount3, amount1));
|
||||
|
||||
BEAST_EXPECT(q11 == q11);
|
||||
BEAST_EXPECT(q11 < q12);
|
||||
BEAST_EXPECT(q12 < q13);
|
||||
BEAST_EXPECT(q31 < q21);
|
||||
BEAST_EXPECT(q21 < q11);
|
||||
BEAST_EXPECT(q31 != q21);
|
||||
}
|
||||
|
||||
void
|
||||
test_composition ()
|
||||
{
|
||||
testcase ("composition");
|
||||
|
||||
STAmount const amount1 (noIssue(), 231);
|
||||
STAmount const amount2 (noIssue(), 462);
|
||||
STAmount const amount3 (noIssue(), 924);
|
||||
|
||||
Quality const q11 (Amounts (amount1, amount1));
|
||||
Quality const q12 (Amounts (amount1, amount2));
|
||||
Quality const q13 (Amounts (amount1, amount3));
|
||||
Quality const q21 (Amounts (amount2, amount1));
|
||||
Quality const q31 (Amounts (amount3, amount1));
|
||||
|
||||
BEAST_EXPECT(
|
||||
composed_quality (q12, q21) == q11);
|
||||
|
||||
Quality const q13_31 (
|
||||
composed_quality (q13, q31));
|
||||
Quality const q31_13 (
|
||||
composed_quality (q31, q13));
|
||||
|
||||
BEAST_EXPECT(q13_31 == q31_13);
|
||||
BEAST_EXPECT(q13_31 == q11);
|
||||
}
|
||||
|
||||
void
|
||||
test_operations ()
|
||||
{
|
||||
testcase ("operations");
|
||||
|
||||
Quality const q11 (Amounts (
|
||||
STAmount (noIssue(), 731),
|
||||
STAmount (noIssue(), 731)));
|
||||
|
||||
Quality qa (q11);
|
||||
Quality qb (q11);
|
||||
|
||||
BEAST_EXPECT(qa == qb);
|
||||
BEAST_EXPECT(++qa != q11);
|
||||
BEAST_EXPECT(qa != qb);
|
||||
BEAST_EXPECT(--qb != q11);
|
||||
BEAST_EXPECT(qa != qb);
|
||||
BEAST_EXPECT(qb < qa);
|
||||
BEAST_EXPECT(qb++ < qa);
|
||||
BEAST_EXPECT(qb++ < qa);
|
||||
BEAST_EXPECT(qb++ == qa);
|
||||
BEAST_EXPECT(qa < qb);
|
||||
}
|
||||
void
|
||||
run()
|
||||
{
|
||||
test_comparisons ();
|
||||
test_composition ();
|
||||
test_operations ();
|
||||
test_ceil_in ();
|
||||
test_ceil_out ();
|
||||
test_raw ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Quality,protocol,ripple);
|
||||
|
||||
}
|
||||
134
src/test/protocol/STAccount_test.cpp
Normal file
134
src/test/protocol/STAccount_test.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 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/protocol/STAccount.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
struct STAccount_test : public beast::unit_test::suite
|
||||
{
|
||||
void
|
||||
testSTAccount()
|
||||
{
|
||||
{
|
||||
// Test default constructor.
|
||||
STAccount const defaultAcct;
|
||||
BEAST_EXPECT(defaultAcct.getSType() == STI_ACCOUNT);
|
||||
BEAST_EXPECT(defaultAcct.getText() == "");
|
||||
BEAST_EXPECT(defaultAcct.isDefault() == true);
|
||||
BEAST_EXPECT(defaultAcct.value() == AccountID {});
|
||||
{
|
||||
#ifdef NDEBUG // Qualified because the serialization asserts in a debug build.
|
||||
Serializer s;
|
||||
defaultAcct.add (s); // Asserts in debug build
|
||||
BEAST_EXPECT(s.size() == 1);
|
||||
BEAST_EXPECT(s.getHex() == "00");
|
||||
SerialIter sit (s.slice ());
|
||||
STAccount const deserializedDefault (sit, sfAccount);
|
||||
BEAST_EXPECT(deserializedDefault.isEquivalent (defaultAcct));
|
||||
#endif // NDEBUG
|
||||
}
|
||||
{
|
||||
// Construct a deserialized default STAccount.
|
||||
Serializer s;
|
||||
s.addVL (nullptr, 0);
|
||||
SerialIter sit (s.slice ());
|
||||
STAccount const deserializedDefault (sit, sfAccount);
|
||||
BEAST_EXPECT(deserializedDefault.isEquivalent (defaultAcct));
|
||||
}
|
||||
|
||||
// Test constructor from SField.
|
||||
STAccount const sfAcct {sfAccount};
|
||||
BEAST_EXPECT(sfAcct.getSType() == STI_ACCOUNT);
|
||||
BEAST_EXPECT(sfAcct.getText() == "");
|
||||
BEAST_EXPECT(sfAcct.isDefault());
|
||||
BEAST_EXPECT(sfAcct.value() == AccountID {});
|
||||
BEAST_EXPECT(sfAcct.isEquivalent (defaultAcct));
|
||||
{
|
||||
Serializer s;
|
||||
sfAcct.add (s);
|
||||
BEAST_EXPECT(s.size() == 1);
|
||||
BEAST_EXPECT(s.getHex() == "00");
|
||||
SerialIter sit (s.slice ());
|
||||
STAccount const deserializedSf (sit, sfAccount);
|
||||
BEAST_EXPECT(deserializedSf.isEquivalent(sfAcct));
|
||||
}
|
||||
|
||||
// Test constructor from SField and AccountID.
|
||||
STAccount const zeroAcct {sfAccount, AccountID{}};
|
||||
BEAST_EXPECT(zeroAcct.getText() == "rrrrrrrrrrrrrrrrrrrrrhoLvTp");
|
||||
BEAST_EXPECT(! zeroAcct.isDefault());
|
||||
BEAST_EXPECT(zeroAcct.value() == AccountID {0});
|
||||
BEAST_EXPECT(! zeroAcct.isEquivalent (defaultAcct));
|
||||
BEAST_EXPECT(! zeroAcct.isEquivalent (sfAcct));
|
||||
{
|
||||
Serializer s;
|
||||
zeroAcct.add (s);
|
||||
BEAST_EXPECT(s.size() == 21);
|
||||
BEAST_EXPECT(s.getHex() ==
|
||||
"140000000000000000000000000000000000000000");
|
||||
SerialIter sit (s.slice ());
|
||||
STAccount const deserializedZero (sit, sfAccount);
|
||||
BEAST_EXPECT(deserializedZero.isEquivalent (zeroAcct));
|
||||
}
|
||||
{
|
||||
// Construct from a VL that is not exactly 160 bits.
|
||||
Serializer s;
|
||||
const std::uint8_t bits128[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
s.addVL (bits128, sizeof (bits128));
|
||||
SerialIter sit (s.slice ());
|
||||
try
|
||||
{
|
||||
// Constructing an STAccount with a bad size should throw.
|
||||
STAccount const deserializedBadSize (sit, sfAccount);
|
||||
}
|
||||
catch (std::runtime_error const& ex)
|
||||
{
|
||||
BEAST_EXPECT(ex.what() == std::string("Invalid STAccount size"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Interestingly, equal values but different types are equivalent!
|
||||
STAccount const regKey {sfRegularKey, AccountID{}};
|
||||
BEAST_EXPECT(regKey.isEquivalent (zeroAcct));
|
||||
|
||||
// Test assignment.
|
||||
STAccount assignAcct;
|
||||
BEAST_EXPECT(assignAcct.isEquivalent (defaultAcct));
|
||||
BEAST_EXPECT(assignAcct.isDefault());
|
||||
assignAcct = AccountID{};
|
||||
BEAST_EXPECT(! assignAcct.isEquivalent (defaultAcct));
|
||||
BEAST_EXPECT(assignAcct.isEquivalent (zeroAcct));
|
||||
BEAST_EXPECT(! assignAcct.isDefault());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testSTAccount();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(STAccount,protocol,ripple);
|
||||
|
||||
}
|
||||
625
src/test/protocol/STAmount_test.cpp
Normal file
625
src/test/protocol/STAmount_test.cpp
Normal file
@@ -0,0 +1,625 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/basics/random.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class STAmount_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
static STAmount serializeAndDeserialize (STAmount const& s)
|
||||
{
|
||||
Serializer ser;
|
||||
s.add (ser);
|
||||
|
||||
SerialIter sit (ser.slice());
|
||||
return STAmount(sit, sfGeneric);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
STAmount roundSelf (STAmount const& amount)
|
||||
{
|
||||
if (amount.native ())
|
||||
return amount;
|
||||
|
||||
std::uint64_t mantissa = amount.mantissa ();
|
||||
std::uint64_t valueDigits = mantissa % 1000000000;
|
||||
|
||||
if (valueDigits == 1)
|
||||
{
|
||||
mantissa--;
|
||||
|
||||
if (mantissa < STAmount::cMinValue)
|
||||
return { amount.issue (), mantissa, amount.exponent (),
|
||||
amount.negative () };
|
||||
|
||||
return { amount.issue (), mantissa, amount.exponent (),
|
||||
amount.native(), amount.negative (), STAmount::unchecked {} };
|
||||
}
|
||||
|
||||
if (valueDigits == 999999999)
|
||||
{
|
||||
mantissa++;
|
||||
|
||||
if (mantissa > STAmount::cMaxValue)
|
||||
return { amount.issue (), mantissa, amount.exponent (),
|
||||
amount.negative () };
|
||||
|
||||
return { amount.issue (), mantissa, amount.exponent (),
|
||||
amount.native(), amount.negative (), STAmount::unchecked {} };
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
void roundTest (int n, int d, int m)
|
||||
{
|
||||
// check STAmount rounding
|
||||
STAmount num (noIssue(), n);
|
||||
STAmount den (noIssue(), d);
|
||||
STAmount mul (noIssue(), m);
|
||||
STAmount quot = divide (n, d, noIssue());
|
||||
STAmount res = roundSelf (multiply (quot, mul, noIssue()));
|
||||
|
||||
BEAST_EXPECT(! res.native ());
|
||||
|
||||
STAmount cmp (noIssue(), (n * m) / d);
|
||||
|
||||
BEAST_EXPECT(! cmp.native ());
|
||||
|
||||
BEAST_EXPECT(cmp.issue().currency == res.issue().currency);
|
||||
|
||||
if (res != cmp)
|
||||
{
|
||||
log <<
|
||||
"(" << num.getText () << "/" << den.getText () <<
|
||||
") X " << mul.getText () << " = " << res.getText () <<
|
||||
" not " << cmp.getText ();
|
||||
fail ("Rounding");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void mulTest (int a, int b)
|
||||
{
|
||||
STAmount aa (noIssue(), a);
|
||||
STAmount bb (noIssue(), b);
|
||||
STAmount prod1 (multiply (aa, bb, noIssue()));
|
||||
|
||||
BEAST_EXPECT(! prod1.native ());
|
||||
|
||||
STAmount prod2 (noIssue(), static_cast<std::uint64_t> (a) * static_cast<std::uint64_t> (b));
|
||||
|
||||
if (prod1 != prod2)
|
||||
{
|
||||
log <<
|
||||
"nn(" << aa.getFullText () << " * " << bb.getFullText () <<
|
||||
") = " << prod1.getFullText () << " not " << prod2.getFullText ();
|
||||
fail ("Multiplication result is not exact");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testSetValue (
|
||||
std::string const& value, Issue const& issue, bool success = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
STAmount const amount = amountFromString (issue, value);
|
||||
BEAST_EXPECT(amount.getText () == value);
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
BEAST_EXPECT(!success);
|
||||
}
|
||||
}
|
||||
|
||||
void testSetValue ()
|
||||
{
|
||||
{
|
||||
testcase ("set value (native)");
|
||||
|
||||
Issue const xrp (xrpIssue ());
|
||||
|
||||
// fractional XRP (i.e. drops)
|
||||
testSetValue ("1", xrp);
|
||||
testSetValue ("22", xrp);
|
||||
testSetValue ("333", xrp);
|
||||
testSetValue ("4444", xrp);
|
||||
testSetValue ("55555", xrp);
|
||||
testSetValue ("666666", xrp);
|
||||
|
||||
// 1 XRP up to 100 billion, in powers of 10 (in drops)
|
||||
testSetValue ("1000000", xrp);
|
||||
testSetValue ("10000000", xrp);
|
||||
testSetValue ("100000000", xrp);
|
||||
testSetValue ("1000000000", xrp);
|
||||
testSetValue ("10000000000", xrp);
|
||||
testSetValue ("100000000000", xrp);
|
||||
testSetValue ("1000000000000", xrp);
|
||||
testSetValue ("10000000000000", xrp);
|
||||
testSetValue ("100000000000000", xrp);
|
||||
testSetValue ("1000000000000000", xrp);
|
||||
testSetValue ("10000000000000000", xrp);
|
||||
testSetValue ("100000000000000000", xrp);
|
||||
|
||||
// Invalid native values:
|
||||
testSetValue ("1.1", xrp, false);
|
||||
testSetValue ("100000000000000001", xrp, false);
|
||||
testSetValue ("1000000000000000000", xrp, false);
|
||||
}
|
||||
|
||||
{
|
||||
testcase ("set value (iou)");
|
||||
|
||||
Issue const usd (Currency (0x5553440000000000), AccountID (0x4985601));
|
||||
|
||||
testSetValue ("1", usd);
|
||||
testSetValue ("10", usd);
|
||||
testSetValue ("100", usd);
|
||||
testSetValue ("1000", usd);
|
||||
testSetValue ("10000", usd);
|
||||
testSetValue ("100000", usd);
|
||||
testSetValue ("1000000", usd);
|
||||
testSetValue ("10000000", usd);
|
||||
testSetValue ("100000000", usd);
|
||||
testSetValue ("1000000000", usd);
|
||||
testSetValue ("10000000000", usd);
|
||||
|
||||
testSetValue ("1234567.1", usd);
|
||||
testSetValue ("1234567.12", usd);
|
||||
testSetValue ("1234567.123", usd);
|
||||
testSetValue ("1234567.1234", usd);
|
||||
testSetValue ("1234567.12345", usd);
|
||||
testSetValue ("1234567.123456", usd);
|
||||
testSetValue ("1234567.1234567", usd);
|
||||
testSetValue ("1234567.12345678", usd);
|
||||
testSetValue ("1234567.123456789", usd);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testNativeCurrency ()
|
||||
{
|
||||
testcase ("native currency");
|
||||
STAmount zeroSt, one (1), hundred (100);
|
||||
// VFALCO NOTE Why repeat "STAmount fail" so many times??
|
||||
unexpected (serializeAndDeserialize (zeroSt) != zeroSt, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (one) != one, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail");
|
||||
unexpected (!zeroSt.native (), "STAmount fail");
|
||||
unexpected (!hundred.native (), "STAmount fail");
|
||||
unexpected (zeroSt != zero, "STAmount fail");
|
||||
unexpected (one == zero, "STAmount fail");
|
||||
unexpected (hundred == zero, "STAmount fail");
|
||||
unexpected ((zeroSt < zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt < one), "STAmount fail");
|
||||
unexpected (! (zeroSt < hundred), "STAmount fail");
|
||||
unexpected ((one < zeroSt), "STAmount fail");
|
||||
unexpected ((one < one), "STAmount fail");
|
||||
unexpected (! (one < hundred), "STAmount fail");
|
||||
unexpected ((hundred < zeroSt), "STAmount fail");
|
||||
unexpected ((hundred < one), "STAmount fail");
|
||||
unexpected ((hundred < hundred), "STAmount fail");
|
||||
unexpected ((zeroSt > zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt > one), "STAmount fail");
|
||||
unexpected ((zeroSt > hundred), "STAmount fail");
|
||||
unexpected (! (one > zeroSt), "STAmount fail");
|
||||
unexpected ((one > one), "STAmount fail");
|
||||
unexpected ((one > hundred), "STAmount fail");
|
||||
unexpected (! (hundred > zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred > one), "STAmount fail");
|
||||
unexpected ((hundred > hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt <= zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt <= one), "STAmount fail");
|
||||
unexpected (! (zeroSt <= hundred), "STAmount fail");
|
||||
unexpected ((one <= zeroSt), "STAmount fail");
|
||||
unexpected (! (one <= one), "STAmount fail");
|
||||
unexpected (! (one <= hundred), "STAmount fail");
|
||||
unexpected ((hundred <= zeroSt), "STAmount fail");
|
||||
unexpected ((hundred <= one), "STAmount fail");
|
||||
unexpected (! (hundred <= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt >= zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt >= one), "STAmount fail");
|
||||
unexpected ((zeroSt >= hundred), "STAmount fail");
|
||||
unexpected (! (one >= zeroSt), "STAmount fail");
|
||||
unexpected (! (one >= one), "STAmount fail");
|
||||
unexpected ((one >= hundred), "STAmount fail");
|
||||
unexpected (! (hundred >= zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred >= one), "STAmount fail");
|
||||
unexpected (! (hundred >= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt == zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt == one), "STAmount fail");
|
||||
unexpected ((zeroSt == hundred), "STAmount fail");
|
||||
unexpected ((one == zeroSt), "STAmount fail");
|
||||
unexpected (! (one == one), "STAmount fail");
|
||||
unexpected ((one == hundred), "STAmount fail");
|
||||
unexpected ((hundred == zeroSt), "STAmount fail");
|
||||
unexpected ((hundred == one), "STAmount fail");
|
||||
unexpected (! (hundred == hundred), "STAmount fail");
|
||||
unexpected ((zeroSt != zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt != one), "STAmount fail");
|
||||
unexpected (! (zeroSt != hundred), "STAmount fail");
|
||||
unexpected (! (one != zeroSt), "STAmount fail");
|
||||
unexpected ((one != one), "STAmount fail");
|
||||
unexpected (! (one != hundred), "STAmount fail");
|
||||
unexpected (! (hundred != zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred != one), "STAmount fail");
|
||||
unexpected ((hundred != hundred), "STAmount fail");
|
||||
unexpected (STAmount ().getText () != "0", "STAmount fail");
|
||||
unexpected (STAmount (31).getText () != "31", "STAmount fail");
|
||||
unexpected (STAmount (310).getText () != "310", "STAmount fail");
|
||||
unexpected (to_string (Currency ()) != "XRP", "cHC(XRP)");
|
||||
Currency c;
|
||||
unexpected (!to_currency (c, "USD"), "create USD currency");
|
||||
unexpected (to_string (c) != "USD", "check USD currency");
|
||||
|
||||
const std::string cur = "015841551A748AD2C1F76FF6ECB0CCCD00000000";
|
||||
unexpected (!to_currency (c, cur), "create custom currency");
|
||||
unexpected (to_string (c) != cur, "check custom currency");
|
||||
unexpected (c != Currency (
|
||||
from_hex_text<Currency>(cur)), "check custom currency");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testCustomCurrency ()
|
||||
{
|
||||
testcase ("custom currency");
|
||||
STAmount zeroSt (noIssue()), one (noIssue(), 1), hundred (noIssue(), 100);
|
||||
unexpected (serializeAndDeserialize (zeroSt) != zeroSt, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (one) != one, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail");
|
||||
unexpected (zeroSt.native (), "STAmount fail");
|
||||
unexpected (hundred.native (), "STAmount fail");
|
||||
unexpected (zeroSt != zero, "STAmount fail");
|
||||
unexpected (one == zero, "STAmount fail");
|
||||
unexpected (hundred == zero, "STAmount fail");
|
||||
unexpected ((zeroSt < zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt < one), "STAmount fail");
|
||||
unexpected (! (zeroSt < hundred), "STAmount fail");
|
||||
unexpected ((one < zeroSt), "STAmount fail");
|
||||
unexpected ((one < one), "STAmount fail");
|
||||
unexpected (! (one < hundred), "STAmount fail");
|
||||
unexpected ((hundred < zeroSt), "STAmount fail");
|
||||
unexpected ((hundred < one), "STAmount fail");
|
||||
unexpected ((hundred < hundred), "STAmount fail");
|
||||
unexpected ((zeroSt > zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt > one), "STAmount fail");
|
||||
unexpected ((zeroSt > hundred), "STAmount fail");
|
||||
unexpected (! (one > zeroSt), "STAmount fail");
|
||||
unexpected ((one > one), "STAmount fail");
|
||||
unexpected ((one > hundred), "STAmount fail");
|
||||
unexpected (! (hundred > zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred > one), "STAmount fail");
|
||||
unexpected ((hundred > hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt <= zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt <= one), "STAmount fail");
|
||||
unexpected (! (zeroSt <= hundred), "STAmount fail");
|
||||
unexpected ((one <= zeroSt), "STAmount fail");
|
||||
unexpected (! (one <= one), "STAmount fail");
|
||||
unexpected (! (one <= hundred), "STAmount fail");
|
||||
unexpected ((hundred <= zeroSt), "STAmount fail");
|
||||
unexpected ((hundred <= one), "STAmount fail");
|
||||
unexpected (! (hundred <= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt >= zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt >= one), "STAmount fail");
|
||||
unexpected ((zeroSt >= hundred), "STAmount fail");
|
||||
unexpected (! (one >= zeroSt), "STAmount fail");
|
||||
unexpected (! (one >= one), "STAmount fail");
|
||||
unexpected ((one >= hundred), "STAmount fail");
|
||||
unexpected (! (hundred >= zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred >= one), "STAmount fail");
|
||||
unexpected (! (hundred >= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt == zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt == one), "STAmount fail");
|
||||
unexpected ((zeroSt == hundred), "STAmount fail");
|
||||
unexpected ((one == zeroSt), "STAmount fail");
|
||||
unexpected (! (one == one), "STAmount fail");
|
||||
unexpected ((one == hundred), "STAmount fail");
|
||||
unexpected ((hundred == zeroSt), "STAmount fail");
|
||||
unexpected ((hundred == one), "STAmount fail");
|
||||
unexpected (! (hundred == hundred), "STAmount fail");
|
||||
unexpected ((zeroSt != zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt != one), "STAmount fail");
|
||||
unexpected (! (zeroSt != hundred), "STAmount fail");
|
||||
unexpected (! (one != zeroSt), "STAmount fail");
|
||||
unexpected ((one != one), "STAmount fail");
|
||||
unexpected (! (one != hundred), "STAmount fail");
|
||||
unexpected (! (hundred != zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred != one), "STAmount fail");
|
||||
unexpected ((hundred != hundred), "STAmount fail");
|
||||
unexpected (STAmount (noIssue()).getText () != "0", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31).getText () != "31", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, 1).getText () != "310", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, -1).getText () != "3.1", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, -2).getText () != "0.31", "STAmount fail");
|
||||
unexpected (multiply (STAmount (noIssue(), 20), STAmount (3), noIssue()).getText () != "60",
|
||||
"STAmount multiply fail 1");
|
||||
unexpected (multiply (STAmount (noIssue(), 20), STAmount (3), xrpIssue ()).getText () != "60",
|
||||
"STAmount multiply fail 2");
|
||||
unexpected (multiply (STAmount (20), STAmount (3), noIssue()).getText () != "60",
|
||||
"STAmount multiply fail 3");
|
||||
unexpected (multiply (STAmount (20), STAmount (3), xrpIssue ()).getText () != "60",
|
||||
"STAmount multiply fail 4");
|
||||
|
||||
if (divide (STAmount (noIssue(), 60), STAmount (3), noIssue()).getText () != "20")
|
||||
{
|
||||
log << "60/3 = " <<
|
||||
divide (STAmount (noIssue(), 60),
|
||||
STAmount (3), noIssue()).getText ();
|
||||
fail ("STAmount divide fail");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
unexpected (divide (STAmount (noIssue(), 60), STAmount (3), xrpIssue ()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
unexpected (divide (STAmount (noIssue(), 60), STAmount (noIssue(), 3), noIssue()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
unexpected (divide (STAmount (noIssue(), 60), STAmount (noIssue(), 3), xrpIssue ()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
STAmount a1 (noIssue(), 60), a2 (noIssue(), 10, -1);
|
||||
|
||||
unexpected (divide (a2, a1, noIssue()) != amountFromQuality (getRate (a1, a2)),
|
||||
"STAmount setRate(getRate) fail");
|
||||
|
||||
unexpected (divide (a1, a2, noIssue()) != amountFromQuality (getRate (a2, a1)),
|
||||
"STAmount setRate(getRate) fail");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testArithmetic ()
|
||||
{
|
||||
testcase ("arithmetic");
|
||||
|
||||
// Test currency multiplication and division operations such as
|
||||
// convertToDisplayAmount, convertToInternalAmount, getRate, getClaimed, and getNeeded
|
||||
|
||||
unexpected (getRate (STAmount (1), STAmount (10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 1");
|
||||
|
||||
unexpected (getRate (STAmount (10), STAmount (1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 2");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 1), STAmount (noIssue(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 3");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 10), STAmount (noIssue(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 4");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 1), STAmount (10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 5");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 10), STAmount (1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 6");
|
||||
|
||||
unexpected (getRate (STAmount (1), STAmount (noIssue(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 7");
|
||||
|
||||
unexpected (getRate (STAmount (10), STAmount (noIssue(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 8");
|
||||
|
||||
roundTest (1, 3, 3);
|
||||
roundTest (2, 3, 9);
|
||||
roundTest (1, 7, 21);
|
||||
roundTest (1, 2, 4);
|
||||
roundTest (3, 9, 18);
|
||||
roundTest (7, 11, 44);
|
||||
|
||||
for (int i = 0; i <= 100000; ++i)
|
||||
{
|
||||
mulTest (
|
||||
rand_int(10000000),
|
||||
rand_int(10000000));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testUnderflow ()
|
||||
{
|
||||
testcase ("underflow");
|
||||
|
||||
STAmount bigNative (STAmount::cMaxNative / 2);
|
||||
STAmount bigValue (noIssue(),
|
||||
(STAmount::cMinValue + STAmount::cMaxValue) / 2,
|
||||
STAmount::cMaxOffset - 1);
|
||||
STAmount smallValue (noIssue(),
|
||||
(STAmount::cMinValue + STAmount::cMaxValue) / 2,
|
||||
STAmount::cMinOffset + 1);
|
||||
STAmount zeroSt (noIssue(), 0);
|
||||
|
||||
STAmount smallXsmall = multiply (smallValue, smallValue, noIssue());
|
||||
|
||||
BEAST_EXPECT(smallXsmall == zero);
|
||||
|
||||
STAmount bigDsmall = divide (smallValue, bigValue, noIssue());
|
||||
|
||||
BEAST_EXPECT(bigDsmall == zero);
|
||||
|
||||
BEAST_EXPECT(bigDsmall == zero);
|
||||
|
||||
bigDsmall = divide (smallValue, bigValue, xrpIssue ());
|
||||
|
||||
BEAST_EXPECT(bigDsmall == zero);
|
||||
|
||||
bigDsmall = divide (smallValue, bigNative, xrpIssue ());
|
||||
|
||||
BEAST_EXPECT(bigDsmall == zero);
|
||||
|
||||
// very bad offer
|
||||
std::uint64_t r = getRate (smallValue, bigValue);
|
||||
|
||||
BEAST_EXPECT(r == 0);
|
||||
|
||||
// very good offer
|
||||
r = getRate (bigValue, smallValue);
|
||||
|
||||
BEAST_EXPECT(r == 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testRounding ()
|
||||
{
|
||||
// VFALCO TODO There are no actual tests here, just printed output?
|
||||
// Change this to actually do something.
|
||||
|
||||
#if 0
|
||||
beginTestCase ("rounding ");
|
||||
|
||||
std::uint64_t value = 25000000000000000ull;
|
||||
int offset = -14;
|
||||
canonicalizeRound (false, value, offset, true);
|
||||
|
||||
STAmount one (noIssue(), 1);
|
||||
STAmount two (noIssue(), 2);
|
||||
STAmount three (noIssue(), 3);
|
||||
|
||||
STAmount oneThird1 = divRound (one, three, noIssue(), false);
|
||||
STAmount oneThird2 = divide (one, three, noIssue());
|
||||
STAmount oneThird3 = divRound (one, three, noIssue(), true);
|
||||
log << oneThird1;
|
||||
log << oneThird2;
|
||||
log << oneThird3;
|
||||
|
||||
STAmount twoThird1 = divRound (two, three, noIssue(), false);
|
||||
STAmount twoThird2 = divide (two, three, noIssue());
|
||||
STAmount twoThird3 = divRound (two, three, noIssue(), true);
|
||||
log << twoThird1;
|
||||
log << twoThird2;
|
||||
log << twoThird3;
|
||||
|
||||
STAmount oneA = mulRound (oneThird1, three, noIssue(), false);
|
||||
STAmount oneB = multiply (oneThird2, three, noIssue());
|
||||
STAmount oneC = mulRound (oneThird3, three, noIssue(), true);
|
||||
log << oneA;
|
||||
log << oneB;
|
||||
log << oneC;
|
||||
|
||||
STAmount fourThirdsB = twoThird2 + twoThird2;
|
||||
log << fourThirdsA;
|
||||
log << fourThirdsB;
|
||||
log << fourThirdsC;
|
||||
|
||||
STAmount dripTest1 = mulRound (twoThird2, two, xrpIssue (), false);
|
||||
STAmount dripTest2 = multiply (twoThird2, two, xrpIssue ());
|
||||
STAmount dripTest3 = mulRound (twoThird2, two, xrpIssue (), true);
|
||||
log << dripTest1;
|
||||
log << dripTest2;
|
||||
log << dripTest3;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
testConvertXRP ()
|
||||
{
|
||||
testcase ("STAmount to XRPAmount conversions");
|
||||
|
||||
Issue const usd { Currency (0x5553440000000000), AccountID (0x4985601) };
|
||||
Issue const xrp { xrpIssue () };
|
||||
|
||||
for (std::uint64_t drops = 100000000000000000; drops != 1; drops = drops / 10)
|
||||
{
|
||||
auto const t = amountFromString (xrp, std::to_string (drops));
|
||||
auto const s = t.xrp ();
|
||||
BEAST_EXPECT(s.drops() == drops);
|
||||
BEAST_EXPECT(t == STAmount (XRPAmount (drops)));
|
||||
BEAST_EXPECT(s == XRPAmount (drops));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto const t = amountFromString (usd, "136500");
|
||||
fail (to_string (t.xrp ()));
|
||||
}
|
||||
catch (std::logic_error const&)
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
fail ("wrong exception");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testConvertIOU ()
|
||||
{
|
||||
testcase ("STAmount to IOUAmount conversions");
|
||||
|
||||
Issue const usd { Currency (0x5553440000000000), AccountID (0x4985601) };
|
||||
Issue const xrp { xrpIssue () };
|
||||
|
||||
for (std::uint64_t dollars = 10000000000; dollars != 1; dollars = dollars / 10)
|
||||
{
|
||||
auto const t = amountFromString (usd, std::to_string (dollars));
|
||||
auto const s = t.iou ();
|
||||
BEAST_EXPECT(t == STAmount (s, usd));
|
||||
BEAST_EXPECT(s.mantissa () == t.mantissa ());
|
||||
BEAST_EXPECT(s.exponent () == t.exponent ());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto const t = amountFromString (xrp, "136500");
|
||||
fail (to_string (t.iou ()));
|
||||
}
|
||||
catch (std::logic_error const&)
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
fail ("wrong exception");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run ()
|
||||
{
|
||||
testSetValue ();
|
||||
testNativeCurrency ();
|
||||
testCustomCurrency ();
|
||||
testArithmetic ();
|
||||
testUnderflow ();
|
||||
testRounding ();
|
||||
testConvertXRP ();
|
||||
testConvertIOU ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(STAmount,ripple_data,ripple);
|
||||
|
||||
} // ripple
|
||||
513
src/test/protocol/STObject_test.cpp
Normal file
513
src/test/protocol/STObject_test.cpp
Normal file
@@ -0,0 +1,513 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/SecretKey.h>
|
||||
#include <ripple/protocol/st.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class STObject_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
bool parseJSONString (std::string const& json, Json::Value& to)
|
||||
{
|
||||
Json::Reader reader;
|
||||
return reader.parse(json, to) &&
|
||||
bool (to) &&
|
||||
to.isObject();
|
||||
}
|
||||
|
||||
void testParseJSONArrayWithInvalidChildrenObjects ()
|
||||
{
|
||||
testcase ("parse json array invalid children");
|
||||
try
|
||||
{
|
||||
/*
|
||||
|
||||
STArray/STObject constructs don't really map perfectly to json
|
||||
arrays/objects.
|
||||
|
||||
STObject is an associative container, mapping fields to value, but
|
||||
an STObject may also have a Field as its name, stored outside the
|
||||
associative structure. The name is important, so to maintain
|
||||
fidelity, it will take TWO json objects to represent them.
|
||||
|
||||
*/
|
||||
std::string faulty ("{\"Template\":[{"
|
||||
"\"ModifiedNode\":{\"Sequence\":1}, "
|
||||
"\"DeletedNode\":{\"Sequence\":1}"
|
||||
"}]}");
|
||||
|
||||
std::unique_ptr<STObject> so;
|
||||
Json::Value faultyJson;
|
||||
bool parsedOK (parseJSONString(faulty, faultyJson));
|
||||
unexpected(!parsedOK, "failed to parse");
|
||||
STParsedJSONObject parsed ("test", faultyJson);
|
||||
BEAST_EXPECT(! parsed.object);
|
||||
}
|
||||
catch(std::runtime_error& e)
|
||||
{
|
||||
std::string what(e.what());
|
||||
unexpected (what.find("First level children of `Template`") != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void testParseJSONArray ()
|
||||
{
|
||||
testcase ("parse json array");
|
||||
std::string const json (
|
||||
"{\"Template\":[{\"ModifiedNode\":{\"Sequence\":1}}]}");
|
||||
|
||||
Json::Value jsonObject;
|
||||
bool parsedOK (parseJSONString(json, jsonObject));
|
||||
if (parsedOK)
|
||||
{
|
||||
STParsedJSONObject parsed ("test", jsonObject);
|
||||
std::string const& serialized (
|
||||
to_string (parsed.object->getJson(0)));
|
||||
BEAST_EXPECT(serialized == json);
|
||||
}
|
||||
else
|
||||
{
|
||||
fail ("Couldn't parse json: " + json);
|
||||
}
|
||||
}
|
||||
|
||||
void testSerialization ()
|
||||
{
|
||||
testcase ("serialization");
|
||||
|
||||
unexpected (sfGeneric.isUseful (), "sfGeneric must not be useful");
|
||||
|
||||
SField const& sfTestVL = SField::getField (STI_VL, 255);
|
||||
SField const& sfTestH256 = SField::getField (STI_HASH256, 255);
|
||||
SField const& sfTestU32 = SField::getField (STI_UINT32, 255);
|
||||
SField const& sfTestV256 = SField::getField(STI_VECTOR256, 255);
|
||||
SField const& sfTestObject = SField::getField (STI_OBJECT, 255);
|
||||
|
||||
SOTemplate elements;
|
||||
elements.push_back (SOElement (sfFlags, SOE_REQUIRED));
|
||||
elements.push_back (SOElement (sfTestVL, SOE_REQUIRED));
|
||||
elements.push_back (SOElement (sfTestH256, SOE_OPTIONAL));
|
||||
elements.push_back (SOElement (sfTestU32, SOE_REQUIRED));
|
||||
elements.push_back (SOElement (sfTestV256, SOE_OPTIONAL));
|
||||
|
||||
STObject object1 (elements, sfTestObject);
|
||||
STObject object2 (object1);
|
||||
|
||||
unexpected (object1.getSerializer () != object2.getSerializer (),
|
||||
"STObject error 1");
|
||||
|
||||
unexpected (object1.isFieldPresent (sfTestH256) ||
|
||||
!object1.isFieldPresent (sfTestVL), "STObject error");
|
||||
|
||||
object1.makeFieldPresent (sfTestH256);
|
||||
|
||||
unexpected (!object1.isFieldPresent (sfTestH256), "STObject Error 2");
|
||||
|
||||
unexpected (object1.getFieldH256 (sfTestH256) != uint256 (),
|
||||
"STObject error 3");
|
||||
|
||||
if (object1.getSerializer () == object2.getSerializer ())
|
||||
{
|
||||
log <<
|
||||
"O1: " << object1.getJson (0) << '\n' <<
|
||||
"O2: " << object2.getJson (0) << std::endl;
|
||||
fail ("STObject error 4");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
object1.makeFieldAbsent (sfTestH256);
|
||||
|
||||
unexpected (object1.isFieldPresent (sfTestH256), "STObject error 5");
|
||||
|
||||
unexpected (object1.getFlags () != 0, "STObject error 6");
|
||||
|
||||
unexpected (object1.getSerializer () != object2.getSerializer (),
|
||||
"STObject error 7");
|
||||
|
||||
STObject copy (object1);
|
||||
|
||||
unexpected (object1.isFieldPresent (sfTestH256), "STObject error 8");
|
||||
|
||||
unexpected (copy.isFieldPresent (sfTestH256), "STObject error 9");
|
||||
|
||||
unexpected (object1.getSerializer () != copy.getSerializer (),
|
||||
"STObject error 10");
|
||||
|
||||
copy.setFieldU32 (sfTestU32, 1);
|
||||
|
||||
unexpected (object1.getSerializer () == copy.getSerializer (),
|
||||
"STObject error 11");
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
Blob j (i, 2);
|
||||
|
||||
object1.setFieldVL (sfTestVL, j);
|
||||
|
||||
Serializer s;
|
||||
object1.add (s);
|
||||
SerialIter it (s.slice());
|
||||
|
||||
STObject object3 (elements, it, sfTestObject);
|
||||
|
||||
unexpected (object1.getFieldVL (sfTestVL) != j, "STObject error");
|
||||
|
||||
unexpected (object3.getFieldVL (sfTestVL) != j, "STObject error");
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<uint256> uints;
|
||||
uints.reserve(5);
|
||||
for (int i = 0; i < uints.capacity(); ++i)
|
||||
{
|
||||
uints.emplace_back(i);
|
||||
}
|
||||
object1.setFieldV256(sfTestV256, STVector256(uints));
|
||||
|
||||
Serializer s;
|
||||
object1.add(s);
|
||||
SerialIter it(s.slice());
|
||||
|
||||
STObject object3(elements, it, sfTestObject);
|
||||
|
||||
auto const& uints1 = object1.getFieldV256(sfTestV256);
|
||||
auto const& uints3 = object3.getFieldV256(sfTestV256);
|
||||
|
||||
BEAST_EXPECT(uints1 == uints3);
|
||||
}
|
||||
}
|
||||
|
||||
// Exercise field accessors
|
||||
void
|
||||
testFields()
|
||||
{
|
||||
testcase ("fields");
|
||||
|
||||
auto const& sf1 = sfSequence;
|
||||
auto const& sf2 = sfExpiration;
|
||||
auto const& sf3 = sfQualityIn;
|
||||
auto const& sf4 = sfSignature;
|
||||
auto const& sf5 = sfPublicKey;
|
||||
|
||||
// read free object
|
||||
|
||||
{
|
||||
auto const st = [&]()
|
||||
{
|
||||
STObject st(sfGeneric);
|
||||
st.setFieldU32(sf1, 1);
|
||||
st.setFieldU32(sf2, 2);
|
||||
return st;
|
||||
}();
|
||||
|
||||
BEAST_EXPECT(st[sf1] == 1);
|
||||
BEAST_EXPECT(st[sf2] == 2);
|
||||
except<missing_field_error>([&]()
|
||||
{ st[sf3]; });
|
||||
BEAST_EXPECT(*st[~sf1] == 1);
|
||||
BEAST_EXPECT(*st[~sf2] == 2);
|
||||
BEAST_EXPECT(st[~sf3] == boost::none);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
BEAST_EXPECT(!! st[~sf2]);
|
||||
BEAST_EXPECT(! st[~sf3]);
|
||||
BEAST_EXPECT(st[sf1] != st[sf2]);
|
||||
BEAST_EXPECT(st[~sf1] != st[~sf2]);
|
||||
}
|
||||
|
||||
// read templated object
|
||||
|
||||
auto const sot = [&]()
|
||||
{
|
||||
SOTemplate sot;
|
||||
sot.push_back(SOElement(sf1, SOE_REQUIRED));
|
||||
sot.push_back(SOElement(sf2, SOE_OPTIONAL));
|
||||
sot.push_back(SOElement(sf3, SOE_DEFAULT));
|
||||
sot.push_back(SOElement(sf4, SOE_OPTIONAL));
|
||||
sot.push_back(SOElement(sf5, SOE_DEFAULT));
|
||||
return sot;
|
||||
}();
|
||||
|
||||
{
|
||||
auto const st = [&]()
|
||||
{
|
||||
STObject st(sot, sfGeneric);
|
||||
st.setFieldU32(sf1, 1);
|
||||
st.setFieldU32(sf2, 2);
|
||||
return st;
|
||||
}();
|
||||
|
||||
BEAST_EXPECT(st[sf1] == 1);
|
||||
BEAST_EXPECT(st[sf2] == 2);
|
||||
BEAST_EXPECT(st[sf3] == 0);
|
||||
BEAST_EXPECT(*st[~sf1] == 1);
|
||||
BEAST_EXPECT(*st[~sf2] == 2);
|
||||
BEAST_EXPECT(*st[~sf3] == 0);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
BEAST_EXPECT(!! st[~sf2]);
|
||||
BEAST_EXPECT(!! st[~sf3]);
|
||||
}
|
||||
|
||||
// write free object
|
||||
|
||||
{
|
||||
STObject st(sfGeneric);
|
||||
unexcept([&]() { st[sf1]; });
|
||||
except([&](){ return st[sf1] == 0; });
|
||||
BEAST_EXPECT(st[~sf1] == boost::none);
|
||||
BEAST_EXPECT(st[~sf1] == boost::optional<std::uint32_t>{});
|
||||
BEAST_EXPECT(st[~sf1] != boost::optional<std::uint32_t>(1));
|
||||
BEAST_EXPECT(! st[~sf1]);
|
||||
st[sf1] = 2;
|
||||
BEAST_EXPECT(st[sf1] == 2);
|
||||
BEAST_EXPECT(st[~sf1] != boost::none);
|
||||
BEAST_EXPECT(st[~sf1] == boost::optional<std::uint32_t>(2));
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
st[sf1] = 1;
|
||||
BEAST_EXPECT(st[sf1] == 1);
|
||||
BEAST_EXPECT(!! st[sf1]);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
st[sf1] = 0;
|
||||
BEAST_EXPECT(! st[sf1]);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
st[~sf1] = boost::none;
|
||||
BEAST_EXPECT(! st[~sf1]);
|
||||
BEAST_EXPECT(st[~sf1] == boost::none);
|
||||
BEAST_EXPECT(st[~sf1] == boost::optional<std::uint32_t>{});
|
||||
st[~sf1] = boost::none;
|
||||
BEAST_EXPECT(! st[~sf1]);
|
||||
except([&]() { return st[sf1] == 0; });
|
||||
except([&]() { return *st[~sf1]; });
|
||||
st[sf1] = 1;
|
||||
BEAST_EXPECT(st[sf1] == 1);
|
||||
BEAST_EXPECT(!! st[sf1]);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
st[sf1] = 3;
|
||||
st[sf2] = st[sf1];
|
||||
BEAST_EXPECT(st[sf1] == 3);
|
||||
BEAST_EXPECT(st[sf2] == 3);
|
||||
BEAST_EXPECT(st[sf2] == st[sf1]);
|
||||
st[sf1] = 4;
|
||||
st[sf2] = st[sf1];
|
||||
BEAST_EXPECT(st[sf1] == 4);
|
||||
BEAST_EXPECT(st[sf2] == 4);
|
||||
BEAST_EXPECT(st[sf2] == st[sf1]);
|
||||
}
|
||||
|
||||
// Write templated object
|
||||
|
||||
{
|
||||
STObject st(sot, sfGeneric);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
BEAST_EXPECT(st[~sf1] != boost::none);
|
||||
BEAST_EXPECT(st[sf1] == 0);
|
||||
BEAST_EXPECT(*st[~sf1] == 0);
|
||||
BEAST_EXPECT(! st[~sf2]);
|
||||
BEAST_EXPECT(st[~sf2] == boost::none);
|
||||
except([&]() { return st[sf2] == 0; });
|
||||
BEAST_EXPECT(!! st[~sf3]);
|
||||
BEAST_EXPECT(st[~sf3] != boost::none);
|
||||
BEAST_EXPECT(st[sf3] == 0);
|
||||
except([&]() { st[~sf1] = boost::none; });
|
||||
st[sf1] = 1;
|
||||
BEAST_EXPECT(st[sf1] == 1);
|
||||
BEAST_EXPECT(*st[~sf1] == 1);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
st[sf1] = 0;
|
||||
BEAST_EXPECT(st[sf1] == 0);
|
||||
BEAST_EXPECT(*st[~sf1] == 0);
|
||||
BEAST_EXPECT(!! st[~sf1]);
|
||||
st[sf2] = 2;
|
||||
BEAST_EXPECT(st[sf2] == 2);
|
||||
BEAST_EXPECT(*st[~sf2] == 2);
|
||||
BEAST_EXPECT(!! st[~sf2]);
|
||||
st[~sf2] = boost::none;
|
||||
except([&]() { return *st[~sf2]; });
|
||||
BEAST_EXPECT(! st[~sf2]);
|
||||
st[sf3] = 3;
|
||||
BEAST_EXPECT(st[sf3] == 3);
|
||||
BEAST_EXPECT(*st[~sf3] == 3);
|
||||
BEAST_EXPECT(!! st[~sf3]);
|
||||
st[sf3] = 2;
|
||||
BEAST_EXPECT(st[sf3] == 2);
|
||||
BEAST_EXPECT(*st[~sf3] == 2);
|
||||
BEAST_EXPECT(!! st[~sf3]);
|
||||
st[sf3] = 0;
|
||||
BEAST_EXPECT(st[sf3] == 0);
|
||||
BEAST_EXPECT(*st[~sf3] == 0);
|
||||
BEAST_EXPECT(!! st[~sf3]);
|
||||
except([&]() { st[~sf3] = boost::none; });
|
||||
BEAST_EXPECT(st[sf3] == 0);
|
||||
BEAST_EXPECT(*st[~sf3] == 0);
|
||||
BEAST_EXPECT(!! st[~sf3]);
|
||||
}
|
||||
|
||||
// coercion operator to boost::optional
|
||||
|
||||
{
|
||||
STObject st(sfGeneric);
|
||||
auto const v = ~st[~sf1];
|
||||
static_assert(std::is_same<
|
||||
std::decay_t<decltype(v)>,
|
||||
boost::optional<std::uint32_t>>::value, "");
|
||||
}
|
||||
|
||||
// UDT scalar fields
|
||||
|
||||
{
|
||||
STObject st(sfGeneric);
|
||||
st[sfAmount] = STAmount{};
|
||||
st[sfAccount] = AccountID{};
|
||||
st[sfDigest] = uint256{};
|
||||
[&](STAmount){}(st[sfAmount]);
|
||||
[&](AccountID){}(st[sfAccount]);
|
||||
[&](uint256){}(st[sfDigest]);
|
||||
}
|
||||
|
||||
// STBlob and slice
|
||||
|
||||
{
|
||||
{
|
||||
STObject st(sfGeneric);
|
||||
Buffer b(1);
|
||||
BEAST_EXPECT(! b.empty());
|
||||
st[sf4] = std::move(b);
|
||||
BEAST_EXPECT(b.empty());
|
||||
BEAST_EXPECT(Slice(st[sf4]).size() == 1);
|
||||
st[~sf4] = boost::none;
|
||||
BEAST_EXPECT(! ~st[~sf4]);
|
||||
b = Buffer{2};
|
||||
st[sf4] = Slice(b);
|
||||
BEAST_EXPECT(b.size() == 2);
|
||||
BEAST_EXPECT(Slice(st[sf4]).size() == 2);
|
||||
st[sf5] = st[sf4];
|
||||
BEAST_EXPECT(Slice(st[sf4]).size() == 2);
|
||||
BEAST_EXPECT(Slice(st[sf5]).size() == 2);
|
||||
}
|
||||
{
|
||||
STObject st(sot, sfGeneric);
|
||||
BEAST_EXPECT(st[sf5] == Slice{});
|
||||
BEAST_EXPECT(!! st[~sf5]);
|
||||
BEAST_EXPECT(!! ~st[~sf5]);
|
||||
Buffer b(1);
|
||||
st[sf5] = std::move(b);
|
||||
BEAST_EXPECT(b.empty());
|
||||
BEAST_EXPECT(Slice(st[sf5]).size() == 1);
|
||||
st[~sf4] = boost::none;
|
||||
BEAST_EXPECT(! ~st[~sf4]);
|
||||
}
|
||||
}
|
||||
|
||||
// UDT blobs
|
||||
|
||||
{
|
||||
STObject st(sfGeneric);
|
||||
BEAST_EXPECT(! st[~sf5]);
|
||||
auto const kp = generateKeyPair(
|
||||
KeyType::secp256k1,
|
||||
generateSeed("masterpassphrase"));
|
||||
st[sf5] = kp.first;
|
||||
BEAST_EXPECT(st[sf5] != PublicKey{});
|
||||
st[~sf5] = boost::none;
|
||||
#if 0
|
||||
pk = st[sf5];
|
||||
BEAST_EXPECT(pk.size() == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// By reference fields
|
||||
|
||||
{
|
||||
auto const& sf = sfIndexes;
|
||||
STObject st(sfGeneric);
|
||||
std::vector<uint256> v;
|
||||
v.emplace_back(1);
|
||||
v.emplace_back(2);
|
||||
st[sf] = v;
|
||||
st[sf] = std::move(v);
|
||||
auto const& cst = st;
|
||||
BEAST_EXPECT(cst[sf].size() == 2);
|
||||
BEAST_EXPECT(cst[~sf]->size() == 2);
|
||||
BEAST_EXPECT(cst[sf][0] == 1);
|
||||
BEAST_EXPECT(cst[sf][1] == 2);
|
||||
static_assert(std::is_same<decltype(cst[sfIndexes]),
|
||||
std::vector<uint256> const&>::value, "");
|
||||
}
|
||||
|
||||
// Default by reference field
|
||||
|
||||
{
|
||||
auto const& sf1 = sfIndexes;
|
||||
auto const& sf2 = sfHashes;
|
||||
auto const& sf3 = sfAmendments;
|
||||
auto const sot = [&]()
|
||||
{
|
||||
SOTemplate sot;
|
||||
sot.push_back(SOElement(sf1, SOE_REQUIRED));
|
||||
sot.push_back(SOElement(sf2, SOE_OPTIONAL));
|
||||
sot.push_back(SOElement(sf3, SOE_DEFAULT));
|
||||
return sot;
|
||||
}();
|
||||
STObject st(sot, sfGeneric);
|
||||
auto const& cst(st);
|
||||
BEAST_EXPECT(cst[sf1].size() == 0);
|
||||
BEAST_EXPECT(! cst[~sf2]);
|
||||
BEAST_EXPECT(cst[sf3].size() == 0);
|
||||
std::vector<uint256> v;
|
||||
v.emplace_back(1);
|
||||
st[sf1] = v;
|
||||
BEAST_EXPECT(cst[sf1].size() == 1);
|
||||
BEAST_EXPECT(cst[sf1][0] == uint256{1});
|
||||
st[sf2] = v;
|
||||
BEAST_EXPECT(cst[sf2].size() == 1);
|
||||
BEAST_EXPECT(cst[sf2][0] == uint256{1});
|
||||
st[~sf2] = boost::none;
|
||||
BEAST_EXPECT(! st[~sf2]);
|
||||
st[sf3] = v;
|
||||
BEAST_EXPECT(cst[sf3].size() == 1);
|
||||
BEAST_EXPECT(cst[sf3][0] == uint256{1});
|
||||
st[sf3] = std::vector<uint256>{};
|
||||
BEAST_EXPECT(cst[sf3].size() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testFields();
|
||||
testSerialization();
|
||||
testParseJSONArray();
|
||||
testParseJSONArrayWithInvalidChildrenObjects();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(STObject,protocol,ripple);
|
||||
|
||||
} // ripple
|
||||
196
src/test/protocol/STTx_test.cpp
Normal file
196
src/test/protocol/STTx_test.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/Sign.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <ripple/protocol/STParsedJSON.h>
|
||||
#include <ripple/protocol/types.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class STTx_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void run()
|
||||
{
|
||||
testcase ("secp256k1 signatures");
|
||||
testSTTx (KeyType::secp256k1);
|
||||
|
||||
testcase ("ed25519 signatures");
|
||||
testSTTx (KeyType::ed25519);
|
||||
}
|
||||
|
||||
void testSTTx(KeyType keyType)
|
||||
{
|
||||
auto const keypair = randomKeyPair (keyType);
|
||||
|
||||
STTx j (ttACCOUNT_SET,
|
||||
[&keypair](auto& obj)
|
||||
{
|
||||
obj.setAccountID (sfAccount, calcAccountID(keypair.first));
|
||||
obj.setFieldVL (sfMessageKey, keypair.first.slice());
|
||||
obj.setFieldVL (sfSigningPubKey, keypair.first.slice());
|
||||
});
|
||||
j.sign (keypair.first, keypair.second);
|
||||
|
||||
unexpected (!j.checkSign (true).first, "Transaction fails signature test");
|
||||
|
||||
Serializer rawTxn;
|
||||
j.add (rawTxn);
|
||||
SerialIter sit (rawTxn.slice());
|
||||
STTx copy (sit);
|
||||
|
||||
if (copy != j)
|
||||
{
|
||||
log <<
|
||||
"j=" << j.getJson (0) << '\n' <<
|
||||
"copy=" << copy.getJson (0) << std::endl;
|
||||
fail ("Transaction fails serialize/deserialize test");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
STParsedJSONObject parsed ("test", j.getJson (0));
|
||||
if (!parsed.object)
|
||||
fail ("Unable to build object from json");
|
||||
|
||||
if (STObject (j) != parsed.object)
|
||||
{
|
||||
log <<
|
||||
"ORIG: " << j.getJson (0) << '\n' <<
|
||||
"BUILT " << parsed.object->getJson (0) << std::endl;
|
||||
fail ("Built a different transaction");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class InnerObjectFormatsSerializer_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void run()
|
||||
{
|
||||
auto const kp1 = randomKeyPair (KeyType::secp256k1);
|
||||
auto const id1 = calcAccountID(kp1.first);
|
||||
|
||||
STTx txn (ttACCOUNT_SET,
|
||||
[&id1,&kp1](auto& obj)
|
||||
{
|
||||
obj.setAccountID (sfAccount, id1);
|
||||
obj.setFieldVL (sfMessageKey, kp1.first.slice());
|
||||
// Make empty signature for multi-signing
|
||||
obj.setFieldVL (sfSigningPubKey, Slice{});
|
||||
});
|
||||
|
||||
// Create fields for a SigningAccount
|
||||
auto const kp2 = randomKeyPair (KeyType::secp256k1);
|
||||
auto const id2 = calcAccountID(kp2.first);
|
||||
|
||||
// Get the stream of the transaction for use in multi-signing.
|
||||
Serializer s = buildMultiSigningData (txn, id2);
|
||||
|
||||
auto const saMultiSignature = sign (kp2.first, kp2.second, s.slice());
|
||||
|
||||
// The InnerObjectFormats say a Signer is supposed to look
|
||||
// like this:
|
||||
// Signer {
|
||||
// Account: "...",
|
||||
// TxnSignature: "...",
|
||||
// PublicKey: "...""
|
||||
// }
|
||||
// Make one well formed Signer and several mal-formed ones. See
|
||||
// whether the serializer lets the good one through and catches
|
||||
// the bad ones.
|
||||
|
||||
// This lambda contains the bulk of the test code.
|
||||
auto testMalformedSigningAccount =
|
||||
[this, &txn, &id1]
|
||||
(STObject const& signer, bool expectPass)
|
||||
{
|
||||
// Create SigningAccounts array.
|
||||
STArray signers (sfSigners, 1);
|
||||
signers.push_back (signer);
|
||||
|
||||
// Insert signers into transaction.
|
||||
STTx tempTxn (txn);
|
||||
tempTxn.setFieldArray (sfSigners, signers);
|
||||
|
||||
Serializer rawTxn;
|
||||
tempTxn.add (rawTxn);
|
||||
SerialIter sit (rawTxn.slice());
|
||||
bool serialized = false;
|
||||
try
|
||||
{
|
||||
STTx copy (sit);
|
||||
serialized = true;
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
; // If it threw then serialization failed.
|
||||
}
|
||||
BEAST_EXPECT(serialized == expectPass);
|
||||
};
|
||||
|
||||
{
|
||||
// Test case 1. Make a valid Signer object.
|
||||
STObject soTest1 (sfSigner);
|
||||
soTest1.setAccountID (sfAccount, id2);
|
||||
soTest1.setFieldVL (sfSigningPubKey, kp1.first.slice());
|
||||
soTest1.setFieldVL (sfTxnSignature, saMultiSignature);
|
||||
testMalformedSigningAccount (soTest1, true);
|
||||
}
|
||||
{
|
||||
// Test case 2. Omit sfSigningPubKey from SigningAccount.
|
||||
STObject soTest2 (sfSigner);
|
||||
soTest2.setAccountID (sfAccount, id2);
|
||||
soTest2.setFieldVL (sfTxnSignature, saMultiSignature);
|
||||
testMalformedSigningAccount (soTest2, false);
|
||||
}
|
||||
{
|
||||
// Test case 3. Extra sfAmount in SigningAccount.
|
||||
STObject soTest3 (sfSigner);
|
||||
soTest3.setAccountID (sfAccount, id2);
|
||||
soTest3.setFieldVL (sfSigningPubKey, kp1.first.slice());
|
||||
soTest3.setFieldVL (sfTxnSignature, saMultiSignature);
|
||||
soTest3.setFieldAmount (sfAmount, STAmount (10000));
|
||||
testMalformedSigningAccount (soTest3, false);
|
||||
}
|
||||
{
|
||||
// Test case 4. Right number of fields, but wrong ones.
|
||||
STObject soTest4 (sfSigner);
|
||||
soTest4.setFieldVL (sfSigningPubKey, kp1.first.slice());
|
||||
soTest4.setFieldVL (sfTxnSignature, saMultiSignature);
|
||||
soTest4.setFieldAmount (sfAmount, STAmount (10000));
|
||||
testMalformedSigningAccount (soTest4, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(STTx,ripple_app,ripple);
|
||||
BEAST_DEFINE_TESTSUITE(InnerObjectFormatsSerializer,ripple_app,ripple);
|
||||
|
||||
} // ripple
|
||||
293
src/test/protocol/SecretKey_test.cpp
Normal file
293
src/test/protocol/SecretKey_test.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/crypto/csprng.h>
|
||||
#include <ripple/protocol/PublicKey.h>
|
||||
#include <ripple/protocol/SecretKey.h>
|
||||
#include <ripple/protocol/Seed.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <ripple/beast/utility/rngfill.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class SecretKey_test : public beast::unit_test::suite
|
||||
{
|
||||
static
|
||||
bool equal(SecretKey const& lhs, SecretKey const& rhs)
|
||||
{
|
||||
return std::equal (
|
||||
lhs.data(), lhs.data() + lhs.size(),
|
||||
rhs.data(), rhs.data() + rhs.size());
|
||||
}
|
||||
|
||||
public:
|
||||
void testDigestSigning()
|
||||
{
|
||||
testcase ("secp256k1 digest");
|
||||
|
||||
for (std::size_t i = 0; i < 32; i++)
|
||||
{
|
||||
auto const keypair = randomKeyPair (KeyType::secp256k1);
|
||||
|
||||
BEAST_EXPECT(keypair.first == derivePublicKey (KeyType::secp256k1, keypair.second));
|
||||
BEAST_EXPECT(*publicKeyType (keypair.first) == KeyType::secp256k1);
|
||||
|
||||
for (std::size_t j = 0; j < 32; j++)
|
||||
{
|
||||
uint256 digest;
|
||||
beast::rngfill (
|
||||
digest.data(),
|
||||
digest.size(),
|
||||
crypto_prng());
|
||||
|
||||
auto sig = signDigest (
|
||||
keypair.first, keypair.second, digest);
|
||||
|
||||
BEAST_EXPECT(sig.size() != 0);
|
||||
BEAST_EXPECT(verifyDigest (keypair.first,
|
||||
digest, sig, true));
|
||||
|
||||
// Wrong digest:
|
||||
BEAST_EXPECT(!verifyDigest (keypair.first,
|
||||
~digest, sig, true));
|
||||
|
||||
// Slightly change the signature:
|
||||
if (auto ptr = sig.data())
|
||||
ptr[j % sig.size()]++;
|
||||
|
||||
// Wrong signature:
|
||||
BEAST_EXPECT(!verifyDigest (keypair.first,
|
||||
digest, sig, true));
|
||||
|
||||
// Wrong digest and signature:
|
||||
BEAST_EXPECT(!verifyDigest (keypair.first,
|
||||
~digest, sig, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testSigning (KeyType type)
|
||||
{
|
||||
for (std::size_t i = 0; i < 32; i++)
|
||||
{
|
||||
auto const keypair = randomKeyPair (type);
|
||||
|
||||
BEAST_EXPECT(keypair.first == derivePublicKey (type, keypair.second));
|
||||
BEAST_EXPECT(*publicKeyType (keypair.first) == type);
|
||||
|
||||
for (std::size_t j = 0; j < 32; j++)
|
||||
{
|
||||
std::vector<std::uint8_t> data (64 + (8 * i) + j);
|
||||
beast::rngfill (
|
||||
data.data(),
|
||||
data.size(),
|
||||
crypto_prng());
|
||||
|
||||
auto sig = sign (
|
||||
keypair.first, keypair.second,
|
||||
makeSlice (data));
|
||||
|
||||
BEAST_EXPECT(sig.size() != 0);
|
||||
BEAST_EXPECT(verify(keypair.first,
|
||||
makeSlice(data), sig, true));
|
||||
|
||||
// Construct wrong data:
|
||||
auto badData = data;
|
||||
|
||||
// swaps the smallest and largest elements in buffer
|
||||
std::iter_swap (
|
||||
std::min_element (badData.begin(), badData.end()),
|
||||
std::max_element (badData.begin(), badData.end()));
|
||||
|
||||
// Wrong data: should fail
|
||||
BEAST_EXPECT(!verify (keypair.first,
|
||||
makeSlice(badData), sig, true));
|
||||
|
||||
// Slightly change the signature:
|
||||
if (auto ptr = sig.data())
|
||||
ptr[j % sig.size()]++;
|
||||
|
||||
// Wrong signature: should fail
|
||||
BEAST_EXPECT(!verify (keypair.first,
|
||||
makeSlice(data), sig, true));
|
||||
|
||||
// Wrong data and signature: should fail
|
||||
BEAST_EXPECT(!verify (keypair.first,
|
||||
makeSlice(badData), sig, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testBase58 ()
|
||||
{
|
||||
testcase ("Base58");
|
||||
|
||||
// Ensure that parsing some well-known secret keys works
|
||||
{
|
||||
auto const sk1 = generateSecretKey (
|
||||
KeyType::secp256k1,
|
||||
generateSeed ("masterpassphrase"));
|
||||
|
||||
auto const sk2 = parseBase58<SecretKey> (
|
||||
TOKEN_NODE_PRIVATE,
|
||||
"pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe");
|
||||
BEAST_EXPECT(sk2);
|
||||
|
||||
BEAST_EXPECT(equal (sk1, *sk2));
|
||||
}
|
||||
|
||||
{
|
||||
auto const sk1 = generateSecretKey (
|
||||
KeyType::ed25519,
|
||||
generateSeed ("masterpassphrase"));
|
||||
|
||||
auto const sk2 = parseBase58<SecretKey> (
|
||||
TOKEN_NODE_PRIVATE,
|
||||
"paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36");
|
||||
BEAST_EXPECT(sk2);
|
||||
|
||||
BEAST_EXPECT(equal (sk1, *sk2));
|
||||
}
|
||||
|
||||
// Try converting short, long and malformed data
|
||||
BEAST_EXPECT(!parseBase58<SecretKey> (TOKEN_NODE_PRIVATE, ""));
|
||||
BEAST_EXPECT(!parseBase58<SecretKey> (TOKEN_NODE_PRIVATE, " "));
|
||||
BEAST_EXPECT(!parseBase58<SecretKey> (TOKEN_NODE_PRIVATE, "!35gty9mhju8nfjl"));
|
||||
|
||||
auto const good = toBase58 (
|
||||
TokenType::TOKEN_NODE_PRIVATE,
|
||||
randomSecretKey());
|
||||
|
||||
// Short (non-empty) strings
|
||||
{
|
||||
auto s = good;
|
||||
|
||||
// Remove all characters from the string in random order:
|
||||
std::hash<std::string> r;
|
||||
|
||||
while (!s.empty())
|
||||
{
|
||||
s.erase (r(s) % s.size(), 1);
|
||||
BEAST_EXPECT(!parseBase58<SecretKey> (TOKEN_NODE_PRIVATE, s));
|
||||
}
|
||||
}
|
||||
|
||||
// Long strings
|
||||
for (std::size_t i = 1; i != 16; i++)
|
||||
{
|
||||
auto s = good;
|
||||
s.resize (s.size() + i, s[i % s.size()]);
|
||||
BEAST_EXPECT(!parseBase58<SecretKey> (TOKEN_NODE_PRIVATE, s));
|
||||
}
|
||||
|
||||
// Strings with invalid Base58 characters
|
||||
for (auto c : std::string ("0IOl"))
|
||||
{
|
||||
for (std::size_t i = 0; i != good.size(); ++i)
|
||||
{
|
||||
auto s = good;
|
||||
s[i % s.size()] = c;
|
||||
BEAST_EXPECT(!parseBase58<SecretKey> (TOKEN_NODE_PRIVATE, s));
|
||||
}
|
||||
}
|
||||
|
||||
// Strings with incorrect prefix
|
||||
{
|
||||
auto s = good;
|
||||
|
||||
for (auto c : std::string("ansrJqtv7"))
|
||||
{
|
||||
s[0] = c;
|
||||
BEAST_EXPECT(!parseBase58<SecretKey> (TOKEN_NODE_PRIVATE, s));
|
||||
}
|
||||
}
|
||||
|
||||
// Try some random secret keys
|
||||
std::array <SecretKey, 32> keys;
|
||||
|
||||
for (std::size_t i = 0; i != keys.size(); ++i)
|
||||
keys[i] = randomSecretKey();
|
||||
|
||||
for (std::size_t i = 0; i != keys.size(); ++i)
|
||||
{
|
||||
auto const si = toBase58 (
|
||||
TokenType::TOKEN_NODE_PRIVATE,
|
||||
keys[i]);
|
||||
BEAST_EXPECT(!si.empty());
|
||||
|
||||
auto const ski = parseBase58<SecretKey> (
|
||||
TOKEN_NODE_PRIVATE, si);
|
||||
BEAST_EXPECT(ski && equal(keys[i], *ski));
|
||||
|
||||
for (std::size_t j = i; j != keys.size(); ++j)
|
||||
{
|
||||
BEAST_EXPECT(equal (keys[i], keys[j]) == (i == j));
|
||||
|
||||
auto const sj = toBase58 (
|
||||
TokenType::TOKEN_NODE_PRIVATE,
|
||||
keys[j]);
|
||||
|
||||
BEAST_EXPECT((si == sj) == (i == j));
|
||||
|
||||
auto const skj = parseBase58<SecretKey> (
|
||||
TOKEN_NODE_PRIVATE, sj);
|
||||
BEAST_EXPECT(skj && equal(keys[j], *skj));
|
||||
|
||||
BEAST_EXPECT(equal (*ski, *skj) == (i == j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testMiscOperations ()
|
||||
{
|
||||
testcase ("Miscellaneous operations");
|
||||
|
||||
auto const sk1 = generateSecretKey (
|
||||
KeyType::secp256k1,
|
||||
generateSeed ("masterpassphrase"));
|
||||
|
||||
SecretKey sk2 (sk1);
|
||||
BEAST_EXPECT(equal (sk1, sk2));
|
||||
|
||||
SecretKey sk3;
|
||||
sk3 = sk2;
|
||||
BEAST_EXPECT(equal (sk3, sk2));
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testBase58();
|
||||
testDigestSigning();
|
||||
testMiscOperations();
|
||||
|
||||
testcase ("secp256k1");
|
||||
testSigning(KeyType::secp256k1);
|
||||
|
||||
testcase ("ed25519");
|
||||
testSigning(KeyType::ed25519);
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(SecretKey,protocol,ripple);
|
||||
|
||||
} // ripple
|
||||
353
src/test/protocol/Seed_test.cpp
Normal file
353
src/test/protocol/Seed_test.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/random.h>
|
||||
#include <ripple/protocol/PublicKey.h>
|
||||
#include <ripple/protocol/SecretKey.h>
|
||||
#include <ripple/protocol/Seed.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <ripple/beast/utility/rngfill.h>
|
||||
#include <ripple/beast/xor_shift_engine.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Seed_test : public beast::unit_test::suite
|
||||
{
|
||||
static
|
||||
bool equal(Seed const& lhs, Seed const& rhs)
|
||||
{
|
||||
return std::equal (
|
||||
lhs.data(), lhs.data() + lhs.size(),
|
||||
rhs.data(), rhs.data() + rhs.size());
|
||||
}
|
||||
|
||||
public:
|
||||
void testConstruction ()
|
||||
{
|
||||
testcase ("construction");
|
||||
|
||||
{
|
||||
std::uint8_t src[16];
|
||||
|
||||
for (std::uint8_t i = 0; i < 64; i++)
|
||||
{
|
||||
beast::rngfill (
|
||||
src,
|
||||
sizeof(src),
|
||||
default_prng());
|
||||
Seed const seed ({ src, sizeof(src) });
|
||||
BEAST_EXPECT(memcmp (seed.data(), src, sizeof(src)) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
uint128 src;
|
||||
beast::rngfill (
|
||||
src.data(),
|
||||
src.size(),
|
||||
default_prng());
|
||||
Seed const seed (src);
|
||||
BEAST_EXPECT(memcmp (seed.data(), src.data(), src.size()) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::string testPassphrase(std::string passphrase)
|
||||
{
|
||||
auto const seed1 = generateSeed (passphrase);
|
||||
auto const seed2 = parseBase58<Seed>(toBase58(seed1));
|
||||
|
||||
BEAST_EXPECT(static_cast<bool>(seed2));
|
||||
BEAST_EXPECT(equal (seed1, *seed2));
|
||||
return toBase58(seed1);
|
||||
}
|
||||
|
||||
void testPassphrase()
|
||||
{
|
||||
testcase ("generation from passphrase");
|
||||
BEAST_EXPECT(testPassphrase ("masterpassphrase") ==
|
||||
"snoPBrXtMeMyMHUVTgbuqAfg1SUTb");
|
||||
BEAST_EXPECT(testPassphrase ("Non-Random Passphrase") ==
|
||||
"snMKnVku798EnBwUfxeSD8953sLYA");
|
||||
BEAST_EXPECT(testPassphrase ("cookies excitement hand public") ==
|
||||
"sspUXGrmjQhq6mgc24jiRuevZiwKT");
|
||||
}
|
||||
|
||||
void testBase58()
|
||||
{
|
||||
testcase ("base58 operations");
|
||||
|
||||
// Success:
|
||||
BEAST_EXPECT(parseBase58<Seed>("snoPBrXtMeMyMHUVTgbuqAfg1SUTb"));
|
||||
BEAST_EXPECT(parseBase58<Seed>("snMKnVku798EnBwUfxeSD8953sLYA"));
|
||||
BEAST_EXPECT(parseBase58<Seed>("sspUXGrmjQhq6mgc24jiRuevZiwKT"));
|
||||
|
||||
// Failure:
|
||||
BEAST_EXPECT(!parseBase58<Seed>(""));
|
||||
BEAST_EXPECT(!parseBase58<Seed>("sspUXGrmjQhq6mgc24jiRuevZiwK"));
|
||||
BEAST_EXPECT(!parseBase58<Seed>("sspUXGrmjQhq6mgc24jiRuevZiwKTT"));
|
||||
BEAST_EXPECT(!parseBase58<Seed>("sspOXGrmjQhq6mgc24jiRuevZiwKT"));
|
||||
BEAST_EXPECT(!parseBase58<Seed>("ssp/XGrmjQhq6mgc24jiRuevZiwKT"));
|
||||
}
|
||||
|
||||
void testRandom()
|
||||
{
|
||||
testcase ("random generation");
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
auto const seed1 = randomSeed ();
|
||||
auto const seed2 = parseBase58<Seed>(toBase58(seed1));
|
||||
|
||||
BEAST_EXPECT(static_cast<bool>(seed2));
|
||||
BEAST_EXPECT(equal (seed1, *seed2));
|
||||
}
|
||||
}
|
||||
|
||||
void testKeypairGenerationAndSigning ()
|
||||
{
|
||||
std::string const message1 = "http://www.ripple.com";
|
||||
std::string const message2 = "https://www.ripple.com";
|
||||
|
||||
{
|
||||
testcase ("Node keypair generation & signing (secp256k1)");
|
||||
|
||||
auto const secretKey = generateSecretKey (
|
||||
KeyType::secp256k1, generateSeed ("masterpassphrase"));
|
||||
auto const publicKey = derivePublicKey (
|
||||
KeyType::secp256k1, secretKey);
|
||||
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PUBLIC, publicKey) ==
|
||||
"n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9");
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PRIVATE, secretKey) ==
|
||||
"pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe");
|
||||
BEAST_EXPECT(to_string(calcNodeID(publicKey)) ==
|
||||
"7E59C17D50F5959C7B158FEC95C8F815BF653DC8");
|
||||
|
||||
auto sig = sign (publicKey, secretKey, makeSlice(message1));
|
||||
BEAST_EXPECT(sig.size() != 0);
|
||||
BEAST_EXPECT(verify (publicKey, makeSlice(message1), sig));
|
||||
|
||||
// Correct public key but wrong message
|
||||
BEAST_EXPECT(!verify (publicKey, makeSlice(message2), sig));
|
||||
|
||||
// Verify with incorrect public key
|
||||
{
|
||||
auto const otherPublicKey = derivePublicKey (
|
||||
KeyType::secp256k1,
|
||||
generateSecretKey (
|
||||
KeyType::secp256k1,
|
||||
generateSeed ("otherpassphrase")));
|
||||
|
||||
BEAST_EXPECT(!verify (otherPublicKey, makeSlice(message1), sig));
|
||||
}
|
||||
|
||||
// Correct public key but wrong signature
|
||||
{
|
||||
// Slightly change the signature:
|
||||
if (auto ptr = sig.data())
|
||||
ptr[sig.size() / 2]++;
|
||||
|
||||
BEAST_EXPECT(!verify (publicKey, makeSlice(message1), sig));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
testcase ("Node keypair generation & signing (ed25519)");
|
||||
|
||||
auto const secretKey = generateSecretKey (
|
||||
KeyType::ed25519, generateSeed ("masterpassphrase"));
|
||||
auto const publicKey = derivePublicKey (
|
||||
KeyType::ed25519, secretKey);
|
||||
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PUBLIC, publicKey) ==
|
||||
"nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf");
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PRIVATE, secretKey) ==
|
||||
"paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36");
|
||||
BEAST_EXPECT(to_string(calcNodeID(publicKey)) ==
|
||||
"AA066C988C712815CC37AF71472B7CBBBD4E2A0A");
|
||||
|
||||
auto sig = sign (publicKey, secretKey, makeSlice(message1));
|
||||
BEAST_EXPECT(sig.size() != 0);
|
||||
BEAST_EXPECT(verify (publicKey, makeSlice(message1), sig));
|
||||
|
||||
// Correct public key but wrong message
|
||||
BEAST_EXPECT(!verify (publicKey, makeSlice(message2), sig));
|
||||
|
||||
// Verify with incorrect public key
|
||||
{
|
||||
auto const otherPublicKey = derivePublicKey (
|
||||
KeyType::ed25519,
|
||||
generateSecretKey (
|
||||
KeyType::ed25519,
|
||||
generateSeed ("otherpassphrase")));
|
||||
|
||||
BEAST_EXPECT(!verify (otherPublicKey, makeSlice(message1), sig));
|
||||
}
|
||||
|
||||
// Correct public key but wrong signature
|
||||
{
|
||||
// Slightly change the signature:
|
||||
if (auto ptr = sig.data())
|
||||
ptr[sig.size() / 2]++;
|
||||
|
||||
BEAST_EXPECT(!verify (publicKey, makeSlice(message1), sig));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
testcase ("Account keypair generation & signing (secp256k1)");
|
||||
|
||||
auto const keyPair = generateKeyPair (
|
||||
KeyType::secp256k1,
|
||||
generateSeed ("masterpassphrase"));
|
||||
|
||||
BEAST_EXPECT(toBase58(calcAccountID(keyPair.first)) ==
|
||||
"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_PUBLIC, keyPair.first) ==
|
||||
"aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw");
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_SECRET, keyPair.second) ==
|
||||
"p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh");
|
||||
|
||||
auto sig = sign (keyPair.first, keyPair.second, makeSlice(message1));
|
||||
BEAST_EXPECT(sig.size() != 0);
|
||||
BEAST_EXPECT(verify (keyPair.first, makeSlice(message1), sig));
|
||||
|
||||
// Correct public key but wrong message
|
||||
BEAST_EXPECT(!verify (keyPair.first, makeSlice(message2), sig));
|
||||
|
||||
// Verify with incorrect public key
|
||||
{
|
||||
auto const otherKeyPair = generateKeyPair (
|
||||
KeyType::secp256k1,
|
||||
generateSeed ("otherpassphrase"));
|
||||
|
||||
BEAST_EXPECT(!verify (otherKeyPair.first, makeSlice(message1), sig));
|
||||
}
|
||||
|
||||
// Correct public key but wrong signature
|
||||
{
|
||||
// Slightly change the signature:
|
||||
if (auto ptr = sig.data())
|
||||
ptr[sig.size() / 2]++;
|
||||
|
||||
BEAST_EXPECT(!verify (keyPair.first, makeSlice(message1), sig));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
testcase ("Account keypair generation & signing (ed25519)");
|
||||
|
||||
auto const keyPair = generateKeyPair (
|
||||
KeyType::ed25519,
|
||||
generateSeed ("masterpassphrase"));
|
||||
|
||||
BEAST_EXPECT(to_string(calcAccountID(keyPair.first)) ==
|
||||
"rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf");
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_PUBLIC, keyPair.first) ==
|
||||
"aKGheSBjmCsKJVuLNKRAKpZXT6wpk2FCuEZAXJupXgdAxX5THCqR");
|
||||
BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_SECRET, keyPair.second) ==
|
||||
"pwDQjwEhbUBmPuEjFpEG75bFhv2obkCB7NxQsfFxM7xGHBMVPu9");
|
||||
|
||||
auto sig = sign (keyPair.first, keyPair.second, makeSlice(message1));
|
||||
BEAST_EXPECT(sig.size() != 0);
|
||||
BEAST_EXPECT(verify (keyPair.first, makeSlice(message1), sig));
|
||||
|
||||
// Correct public key but wrong message
|
||||
BEAST_EXPECT(!verify (keyPair.first, makeSlice(message2), sig));
|
||||
|
||||
// Verify with incorrect public key
|
||||
{
|
||||
auto const otherKeyPair = generateKeyPair (
|
||||
KeyType::ed25519,
|
||||
generateSeed ("otherpassphrase"));
|
||||
|
||||
BEAST_EXPECT(!verify (otherKeyPair.first, makeSlice(message1), sig));
|
||||
}
|
||||
|
||||
// Correct public key but wrong signature
|
||||
{
|
||||
// Slightly change the signature:
|
||||
if (auto ptr = sig.data())
|
||||
ptr[sig.size() / 2]++;
|
||||
|
||||
BEAST_EXPECT(!verify (keyPair.first, makeSlice(message1), sig));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testSeedParsing ()
|
||||
{
|
||||
testcase ("Parsing");
|
||||
|
||||
// account IDs and node and account public and private
|
||||
// keys should not be parseable as seeds.
|
||||
|
||||
auto const node1 = randomKeyPair(KeyType::secp256k1);
|
||||
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58 (TokenType::TOKEN_NODE_PUBLIC, node1.first)));
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58 (TokenType::TOKEN_NODE_PRIVATE, node1.second)));
|
||||
|
||||
auto const node2 = randomKeyPair(KeyType::ed25519);
|
||||
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58 (TokenType::TOKEN_NODE_PUBLIC, node2.first)));
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58 (TokenType::TOKEN_NODE_PRIVATE, node2.second)));
|
||||
|
||||
auto const account1 = generateKeyPair(
|
||||
KeyType::secp256k1, randomSeed ());
|
||||
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58(calcAccountID(account1.first))));
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58(TokenType::TOKEN_ACCOUNT_PUBLIC, account1.first)));
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58(TokenType::TOKEN_ACCOUNT_SECRET, account1.second)));
|
||||
|
||||
auto const account2 = generateKeyPair(
|
||||
KeyType::ed25519, randomSeed ());
|
||||
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58(calcAccountID(account2.first))));
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58(TokenType::TOKEN_ACCOUNT_PUBLIC, account2.first)));
|
||||
BEAST_EXPECT(!parseGenericSeed (
|
||||
toBase58(TokenType::TOKEN_ACCOUNT_SECRET, account2.second)));
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testConstruction();
|
||||
testPassphrase();
|
||||
testBase58();
|
||||
testRandom();
|
||||
testKeypairGenerationAndSigning();
|
||||
testSeedParsing ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Seed,protocol,ripple);
|
||||
|
||||
} // ripple
|
||||
206
src/test/protocol/XRPAmount_test.cpp
Normal file
206
src/test/protocol/XRPAmount_test.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/XRPAmount.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class XRPAmount_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void testSigNum ()
|
||||
{
|
||||
testcase ("signum");
|
||||
|
||||
for (auto i : { -1, 0, 1})
|
||||
{
|
||||
XRPAmount const x(i);
|
||||
|
||||
if (i < 0)
|
||||
BEAST_EXPECT(x.signum () < 0);
|
||||
else if (i > 0)
|
||||
BEAST_EXPECT(x.signum () > 0);
|
||||
else
|
||||
BEAST_EXPECT(x.signum () == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void testBeastZero ()
|
||||
{
|
||||
testcase ("beast::Zero Comparisons");
|
||||
|
||||
for (auto i : { -1, 0, 1})
|
||||
{
|
||||
XRPAmount const x (i);
|
||||
|
||||
BEAST_EXPECT((i == 0) == (x == zero));
|
||||
BEAST_EXPECT((i != 0) == (x != zero));
|
||||
BEAST_EXPECT((i < 0) == (x < zero));
|
||||
BEAST_EXPECT((i > 0) == (x > zero));
|
||||
BEAST_EXPECT((i <= 0) == (x <= zero));
|
||||
BEAST_EXPECT((i >= 0) == (x >= zero));
|
||||
|
||||
BEAST_EXPECT((0 == i) == (zero == x));
|
||||
BEAST_EXPECT((0 != i) == (zero != x));
|
||||
BEAST_EXPECT((0 < i) == (zero < x));
|
||||
BEAST_EXPECT((0 > i) == (zero > x));
|
||||
BEAST_EXPECT((0 <= i) == (zero <= x));
|
||||
BEAST_EXPECT((0 >= i) == (zero >= x));
|
||||
}
|
||||
}
|
||||
|
||||
void testComparisons ()
|
||||
{
|
||||
testcase ("XRP Comparisons");
|
||||
|
||||
for (auto i : { -1, 0, 1})
|
||||
{
|
||||
XRPAmount const x (i);
|
||||
|
||||
for (auto j : { -1, 0, 1})
|
||||
{
|
||||
XRPAmount const y (j);
|
||||
|
||||
BEAST_EXPECT((i == j) == (x == y));
|
||||
BEAST_EXPECT((i != j) == (x != y));
|
||||
BEAST_EXPECT((i < j) == (x < y));
|
||||
BEAST_EXPECT((i > j) == (x > y));
|
||||
BEAST_EXPECT((i <= j) == (x <= y));
|
||||
BEAST_EXPECT((i >= j) == (x >= y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testAddSub ()
|
||||
{
|
||||
testcase ("Addition & Subtraction");
|
||||
|
||||
for (auto i : { -1, 0, 1})
|
||||
{
|
||||
XRPAmount const x (i);
|
||||
|
||||
for (auto j : { -1, 0, 1})
|
||||
{
|
||||
XRPAmount const y (j);
|
||||
|
||||
BEAST_EXPECT(XRPAmount(i + j) == (x + y));
|
||||
BEAST_EXPECT(XRPAmount(i - j) == (x - y));
|
||||
|
||||
BEAST_EXPECT((x + y) == (y + x)); // addition is commutative
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testMulRatio()
|
||||
{
|
||||
testcase ("mulRatio");
|
||||
|
||||
constexpr auto maxUInt32 = std::numeric_limits<std::uint32_t>::max ();
|
||||
constexpr auto maxUInt64 = std::numeric_limits<std::uint64_t>::max ();
|
||||
|
||||
{
|
||||
// multiply by a number that would overflow then divide by the same
|
||||
// number, and check we didn't lose any value
|
||||
XRPAmount big (maxUInt64);
|
||||
BEAST_EXPECT(big == mulRatio (big, maxUInt32, maxUInt32, true));
|
||||
// rounding mode shouldn't matter as the result is exact
|
||||
BEAST_EXPECT(big == mulRatio (big, maxUInt32, maxUInt32, false));
|
||||
}
|
||||
|
||||
{
|
||||
// Similar test as above, but for neative values
|
||||
XRPAmount big (maxUInt64);
|
||||
BEAST_EXPECT(big == mulRatio (big, maxUInt32, maxUInt32, true));
|
||||
// rounding mode shouldn't matter as the result is exact
|
||||
BEAST_EXPECT(big == mulRatio (big, maxUInt32, maxUInt32, false));
|
||||
}
|
||||
|
||||
{
|
||||
// small amounts
|
||||
XRPAmount tiny (1);
|
||||
// Round up should give the smallest allowable number
|
||||
BEAST_EXPECT(tiny == mulRatio (tiny, 1, maxUInt32, true));
|
||||
// rounding down should be zero
|
||||
BEAST_EXPECT(beast::zero == mulRatio (tiny, 1, maxUInt32, false));
|
||||
BEAST_EXPECT(beast::zero ==
|
||||
mulRatio (tiny, maxUInt32 - 1, maxUInt32, false));
|
||||
|
||||
// tiny negative numbers
|
||||
XRPAmount tinyNeg (-1);
|
||||
// Round up should give zero
|
||||
BEAST_EXPECT(zero == mulRatio (tinyNeg, 1, maxUInt32, true));
|
||||
BEAST_EXPECT(zero == mulRatio (tinyNeg, maxUInt32 - 1, maxUInt32, true));
|
||||
// rounding down should be tiny
|
||||
BEAST_EXPECT(tinyNeg == mulRatio (tinyNeg, maxUInt32 - 1, maxUInt32, false));
|
||||
}
|
||||
|
||||
{
|
||||
// rounding
|
||||
{
|
||||
XRPAmount one (1);
|
||||
auto const rup = mulRatio (one, maxUInt32 - 1, maxUInt32, true);
|
||||
auto const rdown = mulRatio (one, maxUInt32 - 1, maxUInt32, false);
|
||||
BEAST_EXPECT(rup.drops () - rdown.drops () == 1);
|
||||
}
|
||||
|
||||
{
|
||||
XRPAmount big (maxUInt64);
|
||||
auto const rup = mulRatio (big, maxUInt32 - 1, maxUInt32, true);
|
||||
auto const rdown = mulRatio (big, maxUInt32 - 1, maxUInt32, false);
|
||||
BEAST_EXPECT(rup.drops () - rdown.drops () == 1);
|
||||
}
|
||||
|
||||
{
|
||||
XRPAmount negOne (-1);
|
||||
auto const rup = mulRatio (negOne, maxUInt32 - 1, maxUInt32, true);
|
||||
auto const rdown = mulRatio (negOne, maxUInt32 - 1, maxUInt32, false);
|
||||
BEAST_EXPECT(rup.drops () - rdown.drops () == 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// division by zero
|
||||
XRPAmount one (1);
|
||||
except ([&] {mulRatio (one, 1, 0, true);});
|
||||
}
|
||||
|
||||
{
|
||||
// overflow
|
||||
XRPAmount big (maxUInt64);
|
||||
except ([&] {mulRatio (big, 2, 0, true);});
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run ()
|
||||
{
|
||||
testSigNum ();
|
||||
testBeastZero ();
|
||||
testComparisons ();
|
||||
testAddSub ();
|
||||
testMulRatio ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(XRPAmount,protocol,ripple);
|
||||
|
||||
} // ripple
|
||||
162
src/test/protocol/digest_test.cpp
Normal file
162
src/test/protocol/digest_test.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/digest.h>
|
||||
#include <ripple/beast/utility/rngfill.h>
|
||||
#include <ripple/beast/xor_shift_engine.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class digest_test : public beast::unit_test::suite
|
||||
{
|
||||
std::vector<uint256> dataset1;
|
||||
|
||||
template <class Hasher>
|
||||
void test (char const* name)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
// Prime the cache
|
||||
for (int i = 0; i != 4; i++)
|
||||
{
|
||||
for (auto const& x : dataset1)
|
||||
{
|
||||
Hasher h;
|
||||
h (x.data (), x.size ());
|
||||
(void) static_cast<typename Hasher::result_type>(h);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<nanoseconds, 128> results;
|
||||
|
||||
for (auto& result : results)
|
||||
{
|
||||
auto const start = high_resolution_clock::now ();
|
||||
|
||||
for (auto const& x : dataset1)
|
||||
{
|
||||
Hasher h;
|
||||
h (x.data (), x.size ());
|
||||
(void) static_cast<typename Hasher::result_type>(h);
|
||||
}
|
||||
|
||||
auto const d = high_resolution_clock::now () - start;
|
||||
|
||||
result = d;
|
||||
}
|
||||
|
||||
log << " " << name << ":" << '\n';
|
||||
|
||||
auto const sum = std::accumulate(
|
||||
results.begin(), results.end(),
|
||||
nanoseconds{0});
|
||||
{
|
||||
auto s = duration_cast<seconds>(sum);
|
||||
auto ms = duration_cast<milliseconds>(sum) - s;
|
||||
log <<
|
||||
" Total Time = " << s.count() <<
|
||||
"." << ms.count() << " seconds" << std::endl;
|
||||
}
|
||||
|
||||
auto const mean = sum / results.size();
|
||||
{
|
||||
auto s = duration_cast<seconds>(mean);
|
||||
auto ms = duration_cast<milliseconds>(mean) - s;
|
||||
log <<
|
||||
" Mean Time = " << s.count() <<
|
||||
"." << ms.count() << " seconds" << std::endl;
|
||||
}
|
||||
|
||||
std::vector<nanoseconds::rep> diff(results.size());
|
||||
std::transform(
|
||||
results.begin(), results.end(), diff.begin(),
|
||||
[&mean](nanoseconds trial)
|
||||
{
|
||||
return (trial - mean).count();
|
||||
});
|
||||
auto const sq_sum = std::inner_product(
|
||||
diff.begin(), diff.end(), diff.begin(), 0.0);
|
||||
{
|
||||
nanoseconds const stddev {
|
||||
static_cast<nanoseconds::rep>(
|
||||
std::sqrt(sq_sum / results.size()))
|
||||
};
|
||||
auto s = duration_cast<seconds>(stddev);
|
||||
auto ms = duration_cast<milliseconds>(stddev) - s;
|
||||
log <<
|
||||
" Std Dev = " << s.count() <<
|
||||
"." << ms.count() << " seconds" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
digest_test ()
|
||||
{
|
||||
beast::xor_shift_engine g(19207813);
|
||||
std::uint8_t buf[32];
|
||||
|
||||
for (int i = 0; i < 1000000; i++)
|
||||
{
|
||||
beast::rngfill (buf, sizeof(buf), g);
|
||||
dataset1.push_back (uint256::fromVoid (buf));
|
||||
}
|
||||
}
|
||||
|
||||
void testSHA512 ()
|
||||
{
|
||||
testcase ("SHA512");
|
||||
test<openssl_ripemd160_hasher> ("OpenSSL");
|
||||
test<beast::ripemd160_hasher> ("Beast");
|
||||
pass ();
|
||||
}
|
||||
|
||||
void testSHA256 ()
|
||||
{
|
||||
testcase ("SHA256");
|
||||
test<openssl_sha256_hasher> ("OpenSSL");
|
||||
test<beast::sha256_hasher> ("Beast");
|
||||
pass ();
|
||||
}
|
||||
|
||||
void testRIPEMD160 ()
|
||||
{
|
||||
testcase ("RIPEMD160");
|
||||
test<openssl_ripemd160_hasher> ("OpenSSL");
|
||||
test<beast::ripemd160_hasher> ("Beast");
|
||||
pass ();
|
||||
}
|
||||
|
||||
void run ()
|
||||
{
|
||||
testSHA512 ();
|
||||
testSHA256 ();
|
||||
testRIPEMD160 ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(digest,ripple_data,ripple);
|
||||
|
||||
} // ripple
|
||||
47
src/test/protocol/types_test.cpp
Normal file
47
src/test/protocol/types_test.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/protocol/types.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
struct types_test : public beast::unit_test::suite
|
||||
{
|
||||
void
|
||||
testAccountID()
|
||||
{
|
||||
auto const s =
|
||||
"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
|
||||
if (BEAST_EXPECT(parseBase58<AccountID>(s)))
|
||||
BEAST_EXPECT(toBase58(
|
||||
*parseBase58<AccountID>(s)) == s);
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testAccountID();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(types,protocol,ripple);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user