rippled
base_uint_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2016 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/base_uint.h>
21 #include <ripple/basics/Blob.h>
22 #include <ripple/basics/hardened_hash.h>
23 #include <ripple/beast/unit_test.h>
24 #include <boost/algorithm/string.hpp>
25 #include <complex>
26 
27 #include <type_traits>
28 
29 namespace ripple {
30 namespace test {
31 
32 // a non-hashing Hasher that just copies the bytes.
33 // Used to test hash_append in base_uint
34 template <std::size_t Bits>
35 struct nonhash
36 {
37  static constexpr std::size_t WIDTH = Bits / 8;
40 
41  nonhash() = default;
42 
43  void
44  operator() (void const* key, std::size_t len) noexcept
45  {
46  assert(len == WIDTH);
47  memcpy(data_.data(), key, len);
48  }
49 
50  explicit
51  operator std::size_t() noexcept { return WIDTH; }
52 };
53 
54 struct base_uint_test : beast::unit_test::suite
55 {
58  static_assert(std::is_copy_assignable<test96>::value, "");
59 
60  void run() override
61  {
62  static_assert(!std::is_constructible<test96, std::complex<double>>::value, "");
63  static_assert(!std::is_assignable<test96&, std::complex<double>>::value, "");
64  // used to verify set insertion (hashing required)
66 
67  Blob raw { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
68  BEAST_EXPECT(test96::bytes == raw.size());
69 
70  test96 u { raw };
71  uset.insert(u);
72  BEAST_EXPECT(raw.size() == u.size());
73  BEAST_EXPECT(to_string(u) == "0102030405060708090A0B0C");
74  BEAST_EXPECT(*u.data() == 1);
75  BEAST_EXPECT(u.signum() == 1);
76  BEAST_EXPECT(!!u);
77  BEAST_EXPECT(!u.isZero());
78  BEAST_EXPECT(u.isNonZero());
79  unsigned char t = 0;
80  for (auto& d : u)
81  {
82  BEAST_EXPECT(d == ++t);
83  }
84 
85  // Test hash_append by "hashing" with a no-op hasher (h)
86  // and then extracting the bytes that were written during hashing
87  // back into another base_uint (w) for comparison with the original
88  nonhash<96> h;
89  hash_append(h, u);
91  BEAST_EXPECT(w == u);
92 
93  test96 v { ~u };
94  uset.insert(v);
95  BEAST_EXPECT(to_string(v) == "FEFDFCFBFAF9F8F7F6F5F4F3");
96  BEAST_EXPECT(*v.data() == 0xfe);
97  BEAST_EXPECT(v.signum() == 1);
98  BEAST_EXPECT(!!v);
99  BEAST_EXPECT(!v.isZero());
100  BEAST_EXPECT(v.isNonZero());
101  t = 0xff;
102  for (auto& d : v)
103  {
104  BEAST_EXPECT(d == --t);
105  }
106 
107  BEAST_EXPECT(compare(u, v) < 0);
108  BEAST_EXPECT(compare(v, u) > 0);
109 
110  v = u;
111  BEAST_EXPECT(v == u);
112 
113  test96 z { beast::zero };
114  uset.insert(z);
115  BEAST_EXPECT(to_string(z) == "000000000000000000000000");
116  BEAST_EXPECT(*z.data() == 0);
117  BEAST_EXPECT(*z.begin() == 0);
118  BEAST_EXPECT(*std::prev(z.end(), 1) == 0);
119  BEAST_EXPECT(z.signum() == 0);
120  BEAST_EXPECT(!z);
121  BEAST_EXPECT(z.isZero());
122  BEAST_EXPECT(!z.isNonZero());
123  for (auto& d : z)
124  {
125  BEAST_EXPECT(d == 0);
126  }
127 
128  test96 n { z };
129  n++;
130  BEAST_EXPECT(n == test96(1));
131  n--;
132  BEAST_EXPECT(n == beast::zero);
133  BEAST_EXPECT(n == z);
134  n--;
135  BEAST_EXPECT(to_string(n) == "FFFFFFFFFFFFFFFFFFFFFFFF");
136  n = beast::zero;
137  BEAST_EXPECT(n == z);
138 
139  test96 zp1 { z };
140  zp1++;
141  test96 zm1 { z };
142  zm1--;
143  test96 x { zm1 ^ zp1 };
144  uset.insert(x);
145  BEAST_EXPECTS(to_string(x) == "FFFFFFFFFFFFFFFFFFFFFFFE", to_string(x));
146 
147  BEAST_EXPECT(uset.size() == 4);
148 
149  // SetHex tests...
150  test96 fromHex;
151  BEAST_EXPECT(fromHex.SetHexExact(to_string(u)));
152  BEAST_EXPECT(fromHex == u);
153  fromHex = z;
154 
155  // fails with extra char
156  BEAST_EXPECT(! fromHex.SetHexExact("A" + to_string(u)));
157  fromHex = z;
158 
159  // fails with extra char at end
160  BEAST_EXPECT(! fromHex.SetHexExact(to_string(u) + "A"));
161  // NOTE: the value fromHex is actually correctly parsed
162  // in this case, but that is an implementation detail and
163  // not guaranteed, thus we don't check the value here.
164  fromHex = z;
165 
166  BEAST_EXPECT(fromHex.SetHex(to_string(u)));
167  BEAST_EXPECT(fromHex == u);
168  fromHex = z;
169 
170  // leading space/0x allowed if not strict
171  BEAST_EXPECT(fromHex.SetHex(" 0x" + to_string(u)));
172  BEAST_EXPECT(fromHex == u);
173  fromHex = z;
174 
175  // other leading chars also allowed (ignored)
176  BEAST_EXPECT(fromHex.SetHex("FEFEFE" + to_string(u)));
177  BEAST_EXPECT(fromHex == u);
178  fromHex = z;
179 
180  // invalid hex chars should fail (0 replaced with Z here)
181  BEAST_EXPECT(! fromHex.SetHex(
182  boost::algorithm::replace_all_copy(to_string(u), "0", "Z")));
183  fromHex = z;
184 
185  BEAST_EXPECT(fromHex.SetHex(to_string(u), true));
186  BEAST_EXPECT(fromHex == u);
187  fromHex = z;
188 
189  // strict mode fails with leading chars
190  BEAST_EXPECT(! fromHex.SetHex(" 0x" + to_string(u), true));
191  fromHex = z;
192 
193  // SetHex ignores extra leading hexits, so the parsed value
194  // is still correct for the following case (strict or non-strict)
195  BEAST_EXPECT(fromHex.SetHex("DEAD" + to_string(u), true ));
196  BEAST_EXPECT(fromHex == u);
197  fromHex = z;
198 
199  BEAST_EXPECT(fromHex.SetHex("DEAD" + to_string(u), false ));
200  BEAST_EXPECT(fromHex == u);
201  fromHex = z;
202  }
203 };
204 
205 BEAST_DEFINE_TESTSUITE(base_uint, ripple_basics, ripple);
206 
207 } // namespace test
208 } // namespace ripple
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
ripple::test::base_uint_test
Definition: base_uint_test.cpp:54
beast::endian::big
@ big
std::unordered_set
STL class.
ripple::test::nonhash::WIDTH
static constexpr std::size_t WIDTH
Definition: base_uint_test.cpp:37
std::vector< unsigned char >
std::unordered_set::size
T size(T... args)
std::is_assignable
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::base_uint
Definition: base_uint.h:65
ripple::base_uint::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:86
ripple::test::nonhash::endian
static const beast::endian endian
Definition: base_uint_test.cpp:39
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:439
std::array< std::uint8_t, WIDTH >
ripple::base_uint::SetHex
bool SetHex(const char *psz, bool bStrict=false)
Parse a hex string into a base_uint The input can be:
Definition: base_uint.h:362
ripple::test::base_uint_test::test96
base_uint< 96 > test96
Definition: base_uint_test.cpp:56
ripple::base_uint::SetHexExact
bool SetHexExact(const char *psz)
Parse a hex string into a base_uint The string must contain exactly bytes * 2 hex characters and must...
Definition: base_uint.h:327
ripple::test::nonhash::nonhash
nonhash()=default
std::is_copy_constructible
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::nonhash
Definition: base_uint_test.cpp:35
std::array::begin
T begin(T... args)
std::unordered_set::insert
T insert(T... args)
ripple::hash_append
void hash_append(Hasher &h, Slice const &v)
Definition: Slice.h:151
ripple::test::nonhash::operator()
void operator()(void const *key, std::size_t len) noexcept
Definition: base_uint_test.cpp:44
std::is_constructible
complex
std::size_t
std::array::end
T end(T... args)
std::is_copy_assignable
std::prev
T prev(T... args)
ripple::test::nonhash::data_
std::array< std::uint8_t, WIDTH > data_
Definition: base_uint_test.cpp:38
ripple::test::base_uint_test::run
void run() override
Definition: base_uint_test.cpp:60
std::array::data
T data(T... args)
type_traits
beast::endian
endian
Definition: endian.h:30