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/protocol/TER.h>
21 #include <ripple/beast/unit_test.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) ||
37  isTemMalformed(t) ||
38  isTefFailure(t) ||
39  isTerRetry(t) ||
40  isTesSuccess(t) ||
41  isTecClaim(t);
42 
43  std::string token, text;
44  auto good = transResultInfo(t, token, text);
45  BEAST_EXPECT(inRange || !good);
46  BEAST_EXPECT(transToken(t) == (good ? token : "-"));
47  BEAST_EXPECT(transHuman(t) == (good ? text : "-"));
48 
49  auto code = transCode(token);
50  BEAST_EXPECT(good == !!code);
51  BEAST_EXPECT(!code || *code == t);
52  }
53  }
54 
55  // Helper template that makes sure two types are not convertible or
56  // assignable if not the same.
57  // o I1 one tuple index.
58  // o I2 other tuple index.
59  // o Tup is expected to be a tuple.
60  // It's a functor, rather than a function template, since a class template
61  // can be a template argument without being full specified.
62  template<std::size_t I1, std::size_t I2>
64  {
65  public:
66  template<typename Tup>
67  void operator()(Tup const& tup, beast::unit_test::suite&) const
68  {
69  // Entries in the tuple should not be convertible or assignable
70  // unless they are the same types.
71  using To_t = std::decay_t<decltype (std::get<I1>(tup))>;
72  using From_t = std::decay_t<decltype (std::get<I2>(tup))>;
73  static_assert (std::is_same<From_t, To_t>::value ==
75  static_assert (std::is_same<To_t, From_t>::value ==
77  static_assert (std::is_same <To_t, From_t>::value ==
79 
80  // Assignment or conversion from integer to type should never work.
81  static_assert (
82  ! std::is_convertible<int, To_t>::value, "Convert err");
83  static_assert (
84  ! std::is_constructible<To_t, int>::value, "Construct err");
85  static_assert (
87  }
88  };
89 
90  // Fast iteration over the tuple.
91  template<std::size_t I1, std::size_t I2,
92  template<std::size_t, std::size_t> class Func, typename Tup>
94  testIterate (Tup const& tup, beast::unit_test::suite& s)
95  {
96  Func<I1, I2> func;
97  func (tup, s);
98  testIterate<I1 - 1, I2, Func>(tup, s);
99  }
100 
101  // Slow iteration over the tuple.
102  template<std::size_t I1, std::size_t I2,
103  template<std::size_t, std::size_t> class Func, typename Tup>
105  testIterate (Tup const& tup, beast::unit_test::suite& s)
106  {
107  Func<I1, I2> func;
108  func (tup, s);
109  testIterate<std::tuple_size<Tup>::value - 1, I2 - 1, Func>(tup, s);
110  }
111 
112  // Finish iteration over the tuple.
113  template<std::size_t I1, std::size_t I2,
114  template<std::size_t, std::size_t> class Func, typename Tup>
116  testIterate (Tup const& tup, beast::unit_test::suite& s)
117  {
118  Func<I1, I2> func;
119  func (tup, s);
120  }
121 
123  {
124  // Verify that valid conversions are valid and invalid conversions
125  // are not valid.
126 
127  // Examples of each kind of enum.
128  static auto const terEnums = std::make_tuple (telLOCAL_ERROR,
130  static const int hiIndex {
131  std::tuple_size<decltype (terEnums)>::value - 1};
132 
133  // Verify that enums cannot be converted to other enum types.
134  testIterate<hiIndex, hiIndex, NotConvertible> (terEnums, *this);
135 
136  // Lambda that verifies assignability and convertibility.
137  auto isConvertable = [] (auto from, auto to)
138  {
139  using From_t = std::decay_t<decltype (from)>;
140  using To_t = std::decay_t<decltype (to)>;
141  static_assert (
143  static_assert (
145  static_assert (
147  };
148 
149  // Verify the right types convert to NotTEC.
150  NotTEC const notTec;
151  isConvertable (telLOCAL_ERROR, notTec);
152  isConvertable (temMALFORMED, notTec);
153  isConvertable (tefFAILURE, notTec);
154  isConvertable (terRETRY, notTec);
155  isConvertable (tesSUCCESS, notTec);
156  isConvertable (notTec, notTec);
157 
158  // Lambda that verifies types and not assignable or convertible.
159  auto notConvertible = [] (auto from, auto to)
160  {
161  using To_t = std::decay_t<decltype (to)>;
162  using From_t = std::decay_t<decltype (from)>;
163  static_assert (
165  static_assert (
167  static_assert (
169  };
170 
171  // Verify types that shouldn't convert to NotTEC.
172  TER const ter;
173  notConvertible (tecCLAIM, notTec);
174  notConvertible (ter, notTec);
175  notConvertible (4, notTec);
176 
177  // Verify the right types convert to TER.
178  isConvertable (telLOCAL_ERROR, ter);
179  isConvertable (temMALFORMED, ter);
180  isConvertable (tefFAILURE, ter);
181  isConvertable (terRETRY, ter);
182  isConvertable (tesSUCCESS, ter);
183  isConvertable (tecCLAIM, ter);
184  isConvertable (notTec, ter);
185  isConvertable (ter, ter);
186 
187  // Verify that you can't convert from int to ter.
188  notConvertible (4, ter);
189  }
190 
191  // Helper template that makes sure two types are comparable. Also
192  // verifies that one of the types does not compare to int.
193  // o I1 one tuple index.
194  // o I2 other tuple index.
195  // o Tup is expected to be a tuple.
196  // It's a functor, rather than a function template, since a class template
197  // can be a template argument without being full specified.
198  template<std::size_t I1, std::size_t I2>
200  {
201  public:
202  template<typename Tup>
203  void operator()(Tup const& tup, beast::unit_test::suite& s) const
204  {
205  // All entries in the tuple should be comparable one to the other.
206  auto const lhs = std::get<I1>(tup);
207  auto const rhs = std::get<I2>(tup);
208 
209  static_assert (std::is_same<
210  decltype (operator== (lhs, rhs)), bool>::value, "== err");
211 
212  static_assert (std::is_same<
213  decltype (operator!= (lhs, rhs)), bool>::value, "!= err");
214 
215  static_assert (std::is_same<
216  decltype (operator< (lhs, rhs)), bool>::value, "< err");
217 
218  static_assert (std::is_same<
219  decltype (operator<= (lhs, rhs)), bool>::value, "<= err");
220 
221  static_assert (std::is_same<
222  decltype (operator> (lhs, rhs)), bool>::value, "> err");
223 
224  static_assert (std::is_same<
225  decltype (operator>= (lhs, rhs)), bool>::value, ">= err");
226 
227  // Make sure a sampling of TER types exhibit the expected behavior
228  // for all comparison operators.
229  s.expect ((lhs == rhs) == (TERtoInt (lhs) == TERtoInt (rhs)));
230  s.expect ((lhs != rhs) == (TERtoInt (lhs) != TERtoInt (rhs)));
231  s.expect ((lhs < rhs) == (TERtoInt (lhs) < TERtoInt (rhs)));
232  s.expect ((lhs <= rhs) == (TERtoInt (lhs) <= TERtoInt (rhs)));
233  s.expect ((lhs > rhs) == (TERtoInt (lhs) > TERtoInt (rhs)));
234  s.expect ((lhs >= rhs) == (TERtoInt (lhs) >= TERtoInt (rhs)));
235  }
236  };
237 
239  {
240  // All of the TER-related types should be comparable.
241 
242  // Examples of all the types we expect to successfully compare.
243  static auto const ters = std::make_tuple (telLOCAL_ERROR, temMALFORMED,
246  static const int hiIndex {
247  std::tuple_size<decltype (ters)>::value - 1};
248 
249  // Verify that all types in the ters tuple can be compared with all
250  // the other types in ters.
251  testIterate<hiIndex, hiIndex, CheckComparable> (ters, *this);
252  }
253 
254  void
255  run() override
256  {
258  testConversion();
259  testComparison();
260  }
261 };
262 
264 
265 } //namespace ripple
ripple::TER_test::CheckComparable::operator()
void operator()(Tup const &tup, beast::unit_test::suite &s) const
Definition: TER_test.cpp:203
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:501
ripple::TER_test::testIterate
std::enable_if_t< I1 !=0 > testIterate(Tup const &tup, beast::unit_test::suite &s)
Definition: TER_test.cpp:94
ripple::telLOCAL_ERROR
@ telLOCAL_ERROR
Definition: TER.h:53
ripple::TER_test
Definition: TER_test.cpp:28
ripple::transToken
std::string transToken(TER code)
Definition: TER.cpp:183
std::is_assignable
tuple
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:289
ripple::TER_test::NotConvertible
Definition: TER_test.cpp:63
ripple::TER_test::testTransResultInfo
void testTransResultInfo()
Definition: TER_test.cpp:31
ripple::isTecClaim
bool isTecClaim(TER x)
Definition: TER.h:506
std::is_convertible
ripple::isTerRetry
bool isTerRetry(TER x)
Definition: TER.h:496
ripple::TER_test::testConversion
void testConversion()
Definition: TER_test.cpp:122
std::enable_if_t
ripple::terRETRY
@ terRETRY
Definition: TER.h:192
ripple::TERSubset< CanCvtToTER >
ripple::isTefFailure
bool isTefFailure(TER x)
Definition: TER.h:491
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:105
ripple::TER
TERSubset< CanCvtToTER > TER
Definition: TER.h:477
ripple::TER_test::CheckComparable
Definition: TER_test.cpp:199
ripple::tefFAILURE
@ tefFAILURE
Definition: TER.h:146
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:191
ripple::TER_test::NotConvertible::operator()
void operator()(Tup const &tup, beast::unit_test::suite &) const
Definition: TER_test.cpp:67
ripple::TER_test::run
void run() override
Definition: TER_test.cpp:255
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:169
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:116
ripple::transCode
boost::optional< TER > transCode(std::string const &token)
Definition: TER.cpp:200
ripple::TERSubset< CanCvtToTER >::fromInt
static constexpr TERSubset fromInt(int from)
Definition: TER.h:323
ripple::isTelLocal
bool isTelLocal(TER x)
Definition: TER.h:481
std::is_constructible
std::size_t
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:85
ripple::tecCLAIM
@ tecCLAIM
Definition: TER.h:246
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:219
type_traits
ripple::isTemMalformed
bool isTemMalformed(TER x)
Definition: TER.h:486
ripple::TER_test::testComparison
void testComparison()
Definition: TER_test.cpp:238