Lumiera  0.pre.03
»edit your freedom«
result-test.cpp
Go to the documentation of this file.
1 /*
2  Result(Test) - verify the either-result-or-failure intermediary wrapper
3 
4  Copyright (C) Lumiera.org
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
30 #include "lib/test/run.hpp"
31 #include "lib/test/test-helper.hpp"
32 #include "lib/result.hpp"
33 #include "lib/util.hpp"
34 
35 #include <cstdlib>
36 
37 
38 
39 namespace lib {
40 namespace test{
41 
42  using util::isSameObject;
43  using std::rand;
44 
45  namespace error = lumiera::error;
46  using error::LUMIERA_ERROR_FATAL;
47  using error::LUMIERA_ERROR_STATE;
48 
49 
50  namespace {
51  const Literal THE_END = "all dead and hero got the girl";
52 
53 
54  #define Type(_EXPR_) lib::test::showType<decltype(_EXPR_)>()
55  }
56 
57 
58 
59 
60 
61  /***********************************************************************************/
74  : public Test
75  {
76 
77  void
78  run (Arg)
79  {
80  auto happy = Result{THE_END};
81  CHECK (happy == THE_END);
82  CHECK (happy.isValid());
83  CHECK (bool(happy));
84 
85  happy.maybeThrow(); // still alive...
86 
87  CHECK (Type(happy) == "Result<Literal const&>"_expect);
88 
89  // Note type deduction: RValue moved into the Result...
90  auto sequel = Result{Literal{THE_END}};
91  CHECK (sequel.isValid());
92  CHECK (Type(sequel) == "Result<Literal>"_expect);
93 
94  CHECK ( isSameObject (happy.get<Literal const&>(), THE_END));
95  CHECK (not isSameObject (sequel.get<Literal const&>(), THE_END));
96 
97  // »Either Right« case : mark as failure
98  Result<double> facepalm{error::Fatal("zOMG")};
99  CHECK (not facepalm.isValid());
100 
101  VERIFY_ERROR (FATAL, (double)facepalm );
102  VERIFY_ERROR (FATAL, facepalm.get<double&>());
103  VERIFY_ERROR (FATAL, facepalm.maybeThrow() );
104 
105  CHECK (42.0 == facepalm.or_else([]{ return 42; }));
106  CHECK (42.0 == facepalm.value_or(210/5));
107 
108 
109  // a generic functor (template) to invoke
110  auto evil = [](auto it)
111  {
112  if (it % 2)
113  throw error::State{"conspiracy"};
114  else
115  return it;
116  };
117 
118  // Invoke failsafe and capture result....
119  auto seed = Result{evil, '*'}; // this invocation is successful
120  CHECK (Type(seed) == "Result<char>"_expect); // generic λ instantiated with <char>
121  CHECK (42 == seed); // int('*') == 42
122 
123  auto breed = Result{evil, 55ll}; // an odd number...
124  VERIFY_ERROR (STATE, breed.maybeThrow() );
125  CHECK (Type(breed) == "Result<long long>"_expect);
126 
127  auto dead = Result{[]{ throw 55; }};
128  auto deed = Result{[]{ /* :-) */ }};
129 
130  CHECK (Type(dead) == "Result<void>"_expect);
131  CHECK (Type(deed) == "Result<void>"_expect);
132 
133  CHECK (not dead.isValid());
134  CHECK ( deed.isValid());
135 
136  try { dead.maybeThrow(); } // can handle really *anything* thrown
137  catch(int oo)
138  { CHECK (oo == 55); }
139 
140  // can also invoke member function....
141  auto deaf = Result{&Literal::empty, &THE_END}; // Note: instance "this"-ptr as first argument
142  CHECK (deaf.isValid()); // no exception was thrown => state isValid()
143  CHECK (deaf == false); // yet invocation of THE_END.empty() yields false
144  CHECK (not deaf); // Warning: in this case, the conversion to payload type shadows
145  CHECK (Type(deaf) == "Result<bool>"_expect);
146  }
147  };
148 
149 
151  LAUNCHER (Result_test, "unit common");
152 
153 
154 }} // namespace lib::test
Representation of the result of some operation, EITHER a value or a failure.
Definition: result.hpp:106
Definition: run.hpp:49
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Intermediary value object to represent »either« an operation result or a failure. ...
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A collection of frequently used helper functions to support unit testing.
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372