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/Blob.h>
21 #include <ripple/basics/base_uint.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 operator std::size_t() noexcept
51  {
52  return WIDTH;
53  }
54 };
55 
56 struct base_uint_test : beast::unit_test::suite
57 {
60  static_assert(std::is_copy_assignable<test96>::value, "");
61 
62  void
63  run() override
64  {
65  static_assert(
67  static_assert(
69  // used to verify set insertion (hashing required)
71 
72  Blob raw{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
73  BEAST_EXPECT(test96::bytes == raw.size());
74 
75  test96 u{raw};
76  uset.insert(u);
77  BEAST_EXPECT(raw.size() == u.size());
78  BEAST_EXPECT(to_string(u) == "0102030405060708090A0B0C");
79  BEAST_EXPECT(*u.data() == 1);
80  BEAST_EXPECT(u.signum() == 1);
81  BEAST_EXPECT(!!u);
82  BEAST_EXPECT(!u.isZero());
83  BEAST_EXPECT(u.isNonZero());
84  unsigned char t = 0;
85  for (auto& d : u)
86  {
87  BEAST_EXPECT(d == ++t);
88  }
89 
90  // Test hash_append by "hashing" with a no-op hasher (h)
91  // and then extracting the bytes that were written during hashing
92  // back into another base_uint (w) for comparison with the original
93  nonhash<96> h;
94  hash_append(h, u);
96  BEAST_EXPECT(w == u);
97 
98  test96 v{~u};
99  uset.insert(v);
100  BEAST_EXPECT(to_string(v) == "FEFDFCFBFAF9F8F7F6F5F4F3");
101  BEAST_EXPECT(*v.data() == 0xfe);
102  BEAST_EXPECT(v.signum() == 1);
103  BEAST_EXPECT(!!v);
104  BEAST_EXPECT(!v.isZero());
105  BEAST_EXPECT(v.isNonZero());
106  t = 0xff;
107  for (auto& d : v)
108  {
109  BEAST_EXPECT(d == --t);
110  }
111 
112  BEAST_EXPECT(compare(u, v) < 0);
113  BEAST_EXPECT(compare(v, u) > 0);
114 
115  v = u;
116  BEAST_EXPECT(v == u);
117 
118  test96 z{beast::zero};
119  uset.insert(z);
120  BEAST_EXPECT(to_string(z) == "000000000000000000000000");
121  BEAST_EXPECT(*z.data() == 0);
122  BEAST_EXPECT(*z.begin() == 0);
123  BEAST_EXPECT(*std::prev(z.end(), 1) == 0);
124  BEAST_EXPECT(z.signum() == 0);
125  BEAST_EXPECT(!z);
126  BEAST_EXPECT(z.isZero());
127  BEAST_EXPECT(!z.isNonZero());
128  for (auto& d : z)
129  {
130  BEAST_EXPECT(d == 0);
131  }
132 
133  test96 n{z};
134  n++;
135  BEAST_EXPECT(n == test96(1));
136  n--;
137  BEAST_EXPECT(n == beast::zero);
138  BEAST_EXPECT(n == z);
139  n--;
140  BEAST_EXPECT(to_string(n) == "FFFFFFFFFFFFFFFFFFFFFFFF");
141  n = beast::zero;
142  BEAST_EXPECT(n == z);
143 
144  test96 zp1{z};
145  zp1++;
146  test96 zm1{z};
147  zm1--;
148  test96 x{zm1 ^ zp1};
149  uset.insert(x);
150  BEAST_EXPECTS(to_string(x) == "FFFFFFFFFFFFFFFFFFFFFFFE", to_string(x));
151 
152  BEAST_EXPECT(uset.size() == 4);
153 
154  // SetHex tests...
155  test96 fromHex;
156  BEAST_EXPECT(fromHex.SetHexExact(to_string(u)));
157  BEAST_EXPECT(fromHex == u);
158  fromHex = z;
159 
160  // fails with extra char
161  BEAST_EXPECT(!fromHex.SetHexExact("A" + to_string(u)));
162  fromHex = z;
163 
164  // fails with extra char at end
165  BEAST_EXPECT(!fromHex.SetHexExact(to_string(u) + "A"));
166  // NOTE: the value fromHex is actually correctly parsed
167  // in this case, but that is an implementation detail and
168  // not guaranteed, thus we don't check the value here.
169  fromHex = z;
170 
171  BEAST_EXPECT(fromHex.SetHex(to_string(u)));
172  BEAST_EXPECT(fromHex == u);
173  fromHex = z;
174 
175  // leading space/0x allowed if not strict
176  BEAST_EXPECT(fromHex.SetHex(" 0x" + to_string(u)));
177  BEAST_EXPECT(fromHex == u);
178  fromHex = z;
179 
180  // other leading chars also allowed (ignored)
181  BEAST_EXPECT(fromHex.SetHex("FEFEFE" + to_string(u)));
182  BEAST_EXPECT(fromHex == u);
183  fromHex = z;
184 
185  // invalid hex chars should fail (0 replaced with Z here)
186  BEAST_EXPECT(!fromHex.SetHex(
187  boost::algorithm::replace_all_copy(to_string(u), "0", "Z")));
188  fromHex = z;
189 
190  BEAST_EXPECT(fromHex.SetHex(to_string(u), true));
191  BEAST_EXPECT(fromHex == u);
192  fromHex = z;
193 
194  // strict mode fails with leading chars
195  BEAST_EXPECT(!fromHex.SetHex(" 0x" + to_string(u), true));
196  fromHex = z;
197 
198  // SetHex ignores extra leading hexits, so the parsed value
199  // is still correct for the following case (strict or non-strict)
200  BEAST_EXPECT(fromHex.SetHex("DEAD" + to_string(u), true));
201  BEAST_EXPECT(fromHex == u);
202  fromHex = z;
203 
204  BEAST_EXPECT(fromHex.SetHex("DEAD" + to_string(u), false));
205  BEAST_EXPECT(fromHex == u);
206  fromHex = z;
207  }
208 };
209 
210 BEAST_DEFINE_TESTSUITE(base_uint, ripple_basics, ripple);
211 
212 } // namespace test
213 } // namespace ripple
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
ripple::test::base_uint_test
Definition: base_uint_test.cpp:56
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:63
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:497
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:406
ripple::test::base_uint_test::test96
base_uint< 96 > test96
Definition: base_uint_test.cpp:58
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:370
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:149
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:63
std::array::data
T data(T... args)
type_traits
beast::endian
endian
Definition: endian.h:30