Lumiera  0.pre.03
»edit your freedom«
opaque-unchecked-buffer-test.cpp
Go to the documentation of this file.
1 /*
2  OpaqueUncheckedBuffer(Test) - passive inline buffer test
3 
4  Copyright (C)
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
20 #include "lib/test/run.hpp"
21 #include "lib/test/test-helper.hpp"
22 #include "lib/nocopy.hpp"
23 #include "lib/util.hpp"
24 
25 #include "lib/opaque-holder.hpp"
26 
27 #include <iostream>
28 #include <cstring>
29 
30 namespace lib {
31 namespace test{
32 
33  using ::Test;
34  using util::min;
35  using lumiera::error::LUMIERA_ERROR_FATAL;
36  using lumiera::error::LUMIERA_ERROR_CAPACITY;
37  using util::MoveOnly;
38 
39  using std::strlen;
40  using std::cout;
41  using std::endl;
42 
43 
44 
45  namespace { // test dummy hierarchy
46  // Note: vtable (and virtual dtor), but varying storage requirements
47 
48  long _checksum = 0;
49  uint _create_count = 0;
50 
51 
52  struct Base
53  : MoveOnly
54  {
55  uint id_;
56 
58  virtual ~Base() =default;
59  virtual void confess() =0;
60 
61  Base(uint i)
62  : id_(i)
63  {
64  ++_create_count;
65  _checksum += id_;
66  }
67 
68  Base(Base&& o)
69  : id_{o.id_}
70  {
71  _checksum += id_;
72  };
73  };
74 
75 
76  template<uint ii>
77  struct DD : Base
78  {
79  char buff_[ii+1];
80 
81  ~DD() { _checksum -= ii; } // verify the correct dtor is called...
82 
83  DD(Symbol sym = 0)
84  : Base(ii)
85  {
86  memset (&buff_, '*', ii);
87  if (sym)
88  memcpy (&buff_, sym, min (ii, strlen (sym)));
89  buff_[ii] = 0;
90  }
91  DD(DD&&) =default; // note: explicit dtor would suppress generation of move ctor
92 
93  void
94  confess ()
95  {
96  cout << "DD<" << ii << ">: " << buff_ << endl;
97  }
98  };
99 
100 
101  struct D42Sub
102  : DD<42>
103  {
104  D42Sub (string s1, string s2)
105  : DD<42> ((s1+' '+s2).c_str())
106  { }
107 
108  void
109  confess ()
110  {
111  cout << "I'm special, " << buff_ << endl;
112  }
113  };
114 
115 
116  struct Killer
117  : DD<23>
118  {
119  Killer () { throw lumiera::error::Fatal ("crisscross"); }
120  };
121 
122 
123 
128  const size_t _ALIGNMENT_OVERHEAD_ = sizeof(size_t);
129 
130  }
131 
132 
133 
134 
135 
136  /******************************************************************************/
143  class OpaqueUncheckedBuffer_test : public Test
144  {
145 
146  virtual void
147  run (Arg)
148  {
149  _checksum = 0;
150  _create_count = 0;
151  {
152  using Buffer = InPlaceBuffer<Base, sizeof(DD<42>), DD<0>>;
153 
154  Buffer buff;
155  CHECK (sizeof(buff) <= sizeof(DD<42>) + _ALIGNMENT_OVERHEAD_);
156  CHECK (1 == _create_count);
157  CHECK (0 == _checksum);
158  buff->confess(); // one default object of type DD<0> has been created
159 
160  buff.create<DD<5>>();
161  buff->confess();
162 
163  VERIFY_ERROR( FATAL, buff.create<Killer> () );
164 
165  CHECK (0 == buff->id_); // default object was created, due to exception...
166  CHECK (4 == _create_count);
167 
168 
169  // as a variation: use a "planting handle" to implant yet another subtype
170  // into the opaque buffer. This setup helps to expose such a buffer via API
171  using Handle = Buffer::Handle;
172 
173  Handle plantingHandle{buff};
174  plantingHandle.emplace (std::move (DD<9>{"I'm fine"}));
175 
176  // subclass instance was indeed implanted into the opaque buffer
177  buff->confess();
178  CHECK (9 == _checksum); // DD<5> has been properly destroyed, DD<9> created in place
179 
180  // Handles can be passed and copied freely
181  Handle copyHandle = plantingHandle;
182 
183  CHECK (9 == buff->id_); // nothing changed with the buffer, still holding the DD<9>...
184  VERIFY_ERROR( FATAL, copyHandle.create<Killer>() );
185  CHECK (0 == buff->id_); // previous object destroyed, Killer-ctor fails, default created DD<0> to fill the void
186 
187  VERIFY_ERROR( CAPACITY, copyHandle.create<DD<55>>() ); // buffer size constraint observed
188 
190 // copyHandle.create<std::string>();
191 
192  copyHandle.create<D42Sub> ("what the f**","is going on here?");
193 
194  buff->confess();
195 
196  CHECK (8 == _create_count);
197  CHECK (42 == _checksum); // No.42 is alive
198  }
199  CHECK (0 == _checksum); // all dead
200  }
201  };
202 
203 
204  LAUNCHER (OpaqueUncheckedBuffer_test, "unit common");
205 
206 
207 }} // namespace lib::test
208 
Generic opaque reference counting handle, for accessing a service and managing its lifecycle...
Definition: handle.hpp:63
Definition: run.hpp:40
Types marked with this mix-in may be moved but not copied.
Definition: nocopy.hpp:49
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Token or Atom with distinct identity.
Definition: symbol.hpp:117
Mix-Ins to allow or prohibit various degrees of copying and cloning.
const size_t _ALIGNMENT_OVERHEAD_
maximum additional storage maybe wasted due to alignment of the contained object within OpaqueHolder&#39;...
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Helper allowing type erasure while holding the actual object inline.
A collection of frequently used helper functions to support unit testing.
Buffer to place and maintain an object instance privately within another object.