rippled
TER_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/beast/unit_test.h>
21 #include <ripple/protocol/TER.h>
22 
23 #include <tuple>
24 #include <type_traits>
25 
26 namespace ripple {
27 
28 struct TER_test : public beast::unit_test::suite
29 {
30  void
32  {
33  for (auto i = -400; i < 400; ++i)
34  {
35  TER t = TER::fromInt(i);
36  auto inRange = isTelLocal(t) || isTemMalformed(t) ||
37  isTefFailure(t) || isTerRetry(t) || isTesSuccess(t) ||
38  isTecClaim(t);
39 
40  std::string token, text;
41  auto good = transResultInfo(t, token, text);
42  BEAST_EXPECT(inRange || !good);
43  BEAST_EXPECT(transToken(t) == (good ? token : "-"));
44  BEAST_EXPECT(transHuman(t) == (good ? text : "-"));
45 
46  auto code = transCode(token);
47  BEAST_EXPECT(good == !!code);
48  BEAST_EXPECT(!code || *code == t);
49  }
50  }
51 
52  // Helper template that makes sure two types are not convertible or
53  // assignable if not the same.
54  // o I1 one tuple index.
55  // o I2 other tuple index.
56  // o Tup is expected to be a tuple.
57  // It's a functor, rather than a function template, since a class template
58  // can be a template argument without being full specified.
59  template <std::size_t I1, std::size_t I2>
61  {
62  public:
63  template <typename Tup>
64  void
65  operator()(Tup const& tup, beast::unit_test::suite&) const
66  {
67  // Entries in the tuple should not be convertible or assignable
68  // unless they are the same types.
69  using To_t = std::decay_t<decltype(std::get<I1>(tup))>;
70  using From_t = std::decay_t<decltype(std::get<I2>(tup))>;
71  static_assert(
74  "Convert err");
75  static_assert(
78  "Construct err");
79  static_assert(
82  "Assign err");
83 
84  // Assignment or conversion from integer to type should never work.
85  static_assert(
87  static_assert(
88  !std::is_constructible<To_t, int>::value, "Construct err");
89  static_assert(
91  }
92  };
93 
94  // Fast iteration over the tuple.
95  template <
96  std::size_t I1,
97  std::size_t I2,
98  template <std::size_t, std::size_t>
99  class Func,
100  typename Tup>
102  testIterate(Tup const& tup, beast::unit_test::suite& s)
103  {
104  Func<I1, I2> func;
105  func(tup, s);
106  testIterate<I1 - 1, I2, Func>(tup, s);
107  }
108 
109  // Slow iteration over the tuple.
110  template <
111  std::size_t I1,
112  std::size_t I2,
113  template <std::size_t, std::size_t>
114  class Func,
115  typename Tup>
117  testIterate(Tup const& tup, beast::unit_test::suite& s)
118  {
119  Func<I1, I2> func;
120  func(tup, s);
121  testIterate<std::tuple_size<Tup>::value - 1, I2 - 1, Func>(tup, s);
122  }
123 
124  // Finish iteration over the tuple.
125  template <
126  std::size_t I1,
127  std::size_t I2,
128  template <std::size_t, std::size_t>
129  class Func,
130  typename Tup>
132  testIterate(Tup const& tup, beast::unit_test::suite& s)
133  {
134  Func<I1, I2> func;
135  func(tup, s);
136  }
137 
138  void
140  {
141  // Verify that valid conversions are valid and invalid conversions
142  // are not valid.
143 
144  // Examples of each kind of enum.
145  static auto const terEnums = std::make_tuple(
147  temMALFORMED,
148  tefFAILURE,
149  terRETRY,
150  tesSUCCESS,
151  tecCLAIM);
152  static const int hiIndex{
153  std::tuple_size<decltype(terEnums)>::value - 1};
154 
155  // Verify that enums cannot be converted to other enum types.
156  testIterate<hiIndex, hiIndex, NotConvertible>(terEnums, *this);
157 
158  // Lambda that verifies assignability and convertibility.
159  auto isConvertable = [](auto from, auto to) {
160  using From_t = std::decay_t<decltype(from)>;
161  using To_t = std::decay_t<decltype(to)>;
162  static_assert(
164  static_assert(
166  static_assert(
168  };
169 
170  // Verify the right types convert to NotTEC.
171  NotTEC const notTec;
172  isConvertable(telLOCAL_ERROR, notTec);
173  isConvertable(temMALFORMED, notTec);
174  isConvertable(tefFAILURE, notTec);
175  isConvertable(terRETRY, notTec);
176  isConvertable(tesSUCCESS, notTec);
177  isConvertable(notTec, notTec);
178 
179  // Lambda that verifies types and not assignable or convertible.
180  auto notConvertible = [](auto from, auto to) {
181  using To_t = std::decay_t<decltype(to)>;
182  using From_t = std::decay_t<decltype(from)>;
183  static_assert(
185  static_assert(
187  static_assert(
189  };
190 
191  // Verify types that shouldn't convert to NotTEC.
192  TER const ter;
193  notConvertible(tecCLAIM, notTec);
194  notConvertible(ter, notTec);
195  notConvertible(4, notTec);
196 
197  // Verify the right types convert to TER.
198  isConvertable(telLOCAL_ERROR, ter);
199  isConvertable(temMALFORMED, ter);
200  isConvertable(tefFAILURE, ter);
201  isConvertable(terRETRY, ter);
202  isConvertable(tesSUCCESS, ter);
203  isConvertable(tecCLAIM, ter);
204  isConvertable(notTec, ter);
205  isConvertable(ter, ter);
206 
207  // Verify that you can't convert from int to ter.
208  notConvertible(4, ter);
209  }
210 
211  // Helper template that makes sure two types are comparable. Also
212  // verifies that one of the types does not compare to int.
213  // o I1 one tuple index.
214  // o I2 other tuple index.
215  // o Tup is expected to be a tuple.
216  // It's a functor, rather than a function template, since a class template
217  // can be a template argument without being full specified.
218  template <std::size_t I1, std::size_t I2>
220  {
221  public:
222  template <typename Tup>
223  void
224  operator()(Tup const& tup, beast::unit_test::suite& s) const
225  {
226  // All entries in the tuple should be comparable one to the other.
227  auto const lhs = std::get<I1>(tup);
228  auto const rhs = std::get<I2>(tup);
229 
230  static_assert(
231  std::is_same<decltype(operator==(lhs, rhs)), bool>::value,
232  "== err");
233 
234  static_assert(
235  std::is_same<decltype(operator!=(lhs, rhs)), bool>::value,
236  "!= err");
237 
238  static_assert(
239  std::is_same<decltype(operator<(lhs, rhs)), bool>::value,
240  "< err");
241 
242  static_assert(
243  std::is_same<decltype(operator<=(lhs, rhs)), bool>::value,
244  "<= err");
245 
246  static_assert(
247  std::is_same<decltype(operator>(lhs, rhs)), bool>::value,
248  "> err");
249 
250  static_assert(
251  std::is_same<decltype(operator>=(lhs, rhs)), bool>::value,
252  ">= err");
253 
254  // Make sure a sampling of TER types exhibit the expected behavior
255  // for all comparison operators.
256  s.expect((lhs == rhs) == (TERtoInt(lhs) == TERtoInt(rhs)));
257  s.expect((lhs != rhs) == (TERtoInt(lhs) != TERtoInt(rhs)));
258  s.expect((lhs < rhs) == (TERtoInt(lhs) < TERtoInt(rhs)));
259  s.expect((lhs <= rhs) == (TERtoInt(lhs) <= TERtoInt(rhs)));
260  s.expect((lhs > rhs) == (TERtoInt(lhs) > TERtoInt(rhs)));
261  s.expect((lhs >= rhs) == (TERtoInt(lhs) >= TERtoInt(rhs)));
262  }
263  };
264 
265  void
267  {
268  // All of the TER-related types should be comparable.
269 
270  // Examples of all the types we expect to successfully compare.
271  static auto const ters = std::make_tuple(
273  temMALFORMED,
274  tefFAILURE,
275  terRETRY,
276  tesSUCCESS,
277  tecCLAIM,
279  TER{tecCLAIM});
280  static const int hiIndex{std::tuple_size<decltype(ters)>::value - 1};
281 
282  // Verify that all types in the ters tuple can be compared with all
283  // the other types in ters.
284  testIterate<hiIndex, hiIndex, CheckComparable>(ters, *this);
285  }
286 
287  void
288  run() override
289  {
291  testConversion();
292  testComparison();
293  }
294 };
295 
297 
298 } // namespace ripple
ripple::TER_test::CheckComparable::operator()
void operator()(Tup const &tup, beast::unit_test::suite &s) const
Definition: TER_test.cpp:224
std::is_same
std::make_tuple
T make_tuple(T... args)
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::isTesSuccess
bool isTesSuccess(TER x)
Definition: TER.h:597
ripple::TER_test::testIterate
std::enable_if_t< I1 !=0 > testIterate(Tup const &tup, beast::unit_test::suite &s)
Definition: TER_test.cpp:102
ripple::telLOCAL_ERROR
@ telLOCAL_ERROR
Definition: TER.h:51
ripple::TER_test
Definition: TER_test.cpp:28
ripple::transToken
std::string transToken(TER code)
Definition: TER.cpp:210
std::is_assignable
tuple
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:301
ripple::TER_test::NotConvertible
Definition: TER_test.cpp:60
ripple::TER_test::testTransResultInfo
void testTransResultInfo()
Definition: TER_test.cpp:31
ripple::isTecClaim
bool isTecClaim(TER x)
Definition: TER.h:603
ripple::transCode
std::optional< TER > transCode(std::string const &token)
Definition: TER.cpp:228
std::is_convertible
ripple::isTerRetry
bool isTerRetry(TER x)
Definition: TER.h:591
ripple::TER_test::testConversion
void testConversion()
Definition: TER_test.cpp:139
std::enable_if_t
ripple::terRETRY
@ terRETRY
Definition: TER.h:195
ripple::TERSubset< CanCvtToTER >
ripple::isTefFailure
bool isTefFailure(TER x)
Definition: TER.h:585
ripple::TER_test::testIterate
std::enable_if_t< I1==0 &&I2 !=0 > testIterate(Tup const &tup, beast::unit_test::suite &s)
Definition: TER_test.cpp:117
ripple::TER
TERSubset< CanCvtToTER > TER
Definition: TER.h:568
ripple::TER_test::CheckComparable
Definition: TER_test.cpp:219
ripple::tefFAILURE
@ tefFAILURE
Definition: TER.h:148
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:219
ripple::TER_test::NotConvertible::operator()
void operator()(Tup const &tup, beast::unit_test::suite &) const
Definition: TER_test.cpp:65
ripple::TER_test::run
void run() override
Definition: TER_test.cpp:288
std::decay_t
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::transResultInfo
bool transResultInfo(TER code, std::string &token, std::string &text)
Definition: TER.cpp:195
ripple::TER_test::testIterate
std::enable_if_t< I1==0 &&I2==0 > testIterate(Tup const &tup, beast::unit_test::suite &s)
Definition: TER_test.cpp:132
protocol
Definition: ValidatorList.h:38
ripple::TERSubset< CanCvtToTER >::fromInt
static constexpr TERSubset fromInt(int from)
Definition: TER.h:359
ripple::isTelLocal
bool isTelLocal(TER x)
Definition: TER.h:573
std::is_constructible
std::size_t
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:85
ripple::tecCLAIM
@ tecCLAIM
Definition: TER.h:248
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:222
type_traits
ripple::isTemMalformed
bool isTemMalformed(TER x)
Definition: TER.h:579
ripple::TER_test::testComparison
void testComparison()
Definition: TER_test.cpp:266