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) Lumiera.org
5  2009, 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 
29 #include "lib/test/run.hpp"
30 #include "lib/test/test-helper.hpp"
31 #include "lib/nocopy.hpp"
32 #include "lib/util.hpp"
33 
34 #include "lib/opaque-holder.hpp"
35 
36 #include <iostream>
37 #include <cstring>
38 
39 namespace lib {
40 namespace test{
41 
42  using ::Test;
43  using util::min;
44  using lumiera::error::LUMIERA_ERROR_FATAL;
45  using lumiera::error::LUMIERA_ERROR_CAPACITY;
46  using util::MoveOnly;
47 
48  using std::strlen;
49  using std::cout;
50  using std::endl;
51 
52 
53 
54  namespace { // test dummy hierarchy
55  // Note: vtable (and virtual dtor), but varying storage requirements
56 
57  long _checksum = 0;
58  uint _create_count = 0;
59 
60 
61  struct Base
62  : MoveOnly
63  {
64  uint id_;
65 
67  virtual ~Base() =default;
68  virtual void confess() =0;
69 
70  Base(uint i)
71  : id_(i)
72  {
73  ++_create_count;
74  _checksum += id_;
75  }
76 
77  Base(Base&& o)
78  : id_{o.id_}
79  {
80  _checksum += id_;
81  };
82  };
83 
84 
85  template<uint ii>
86  struct DD : Base
87  {
88  char buff_[ii+1];
89 
90  ~DD() { _checksum -= ii; } // verify the correct dtor is called...
91 
92  DD(Symbol sym = 0)
93  : Base(ii)
94  {
95  memset (&buff_, '*', ii);
96  if (sym)
97  memcpy (&buff_, sym, min (ii, strlen (sym)));
98  buff_[ii] = 0;
99  }
100  DD(DD&&) =default; // note: explicit dtor would suppress generation of move ctor
101 
102  void
103  confess ()
104  {
105  cout << "DD<" << ii << ">: " << buff_ << endl;
106  }
107  };
108 
109 
110  struct D42Sub
111  : DD<42>
112  {
113  D42Sub (string s1, string s2)
114  : DD<42> ((s1+' '+s2).c_str())
115  { }
116 
117  void
118  confess ()
119  {
120  cout << "I'm special, " << buff_ << endl;
121  }
122  };
123 
124 
125  struct Killer
126  : DD<23>
127  {
128  Killer () { throw lumiera::error::Fatal ("crisscross"); }
129  };
130 
131 
132 
137  const size_t _ALIGNMENT_OVERHEAD_ = sizeof(size_t);
138 
139  }
140 
141 
142 
143 
144 
145  /******************************************************************************/
152  class OpaqueUncheckedBuffer_test : public Test
153  {
154 
155  virtual void
156  run (Arg)
157  {
158  _checksum = 0;
159  _create_count = 0;
160  {
161  using Buffer = InPlaceBuffer<Base, sizeof(DD<42>), DD<0>>;
162 
163  Buffer buff;
164  CHECK (sizeof(buff) <= sizeof(DD<42>) + _ALIGNMENT_OVERHEAD_);
165  CHECK (1 == _create_count);
166  CHECK (0 == _checksum);
167  buff->confess(); // one default object of type DD<0> has been created
168 
169  buff.create<DD<5>>();
170  buff->confess();
171 
172  VERIFY_ERROR( FATAL, buff.create<Killer> () );
173 
174  CHECK (0 == buff->id_); // default object was created, due to exception...
175  CHECK (4 == _create_count);
176 
177 
178  // as a variation: use a "planting handle" to implant yet another subtype
179  // into the opaque buffer. This setup helps to expose such a buffer via API
180  using Handle = Buffer::Handle;
181 
182  Handle plantingHandle{buff};
183  plantingHandle.emplace (std::move (DD<9>{"I'm fine"}));
184 
185  // subclass instance was indeed implanted into the opaque buffer
186  buff->confess();
187  CHECK (9 == _checksum); // DD<5> has been properly destroyed, DD<9> created in place
188 
189  // Handles can be passed and copied freely
190  Handle copyHandle = plantingHandle;
191 
192  CHECK (9 == buff->id_); // nothing changed with the buffer, still holding the DD<9>...
193  VERIFY_ERROR( FATAL, copyHandle.create<Killer>() );
194  CHECK (0 == buff->id_); // previous object destroyed, Killer-ctor fails, default created DD<0> to fill the void
195 
196  VERIFY_ERROR( CAPACITY, copyHandle.create<DD<55>>() ); // buffer size constraint observed
197 
199 // copyHandle.create<std::string>();
200 
201  copyHandle.create<D42Sub> ("what the f**","is going on here?");
202 
203  buff->confess();
204 
205  CHECK (8 == _create_count);
206  CHECK (42 == _checksum); // No.42 is alive
207  }
208  CHECK (0 == _checksum); // all dead
209  }
210  };
211 
212 
213  LAUNCHER (OpaqueUncheckedBuffer_test, "unit common");
214 
215 
216 }} // namespace lib::test
217 
Generic opaque reference counting handle, for accessing a service and managing its lifecycle...
Definition: handle.hpp:72
Definition: run.hpp:49
Types marked with this mix-in may be moved but not copied.
Definition: nocopy.hpp:58
#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:199
Token or Atom with distinct identity.
Definition: symbol.hpp:126
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;...
Simple 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.