Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ArrayView_UnitTests.cpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Teuchos: Common Tools Package
6 // Copyright (2004) Sandia Corporation
7 //
8 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9 // license for use of this work by or on behalf of the U.S. Government.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 */
43 
45 
47 
48 
49 namespace {
50 
51 
54 using Teuchos::RCP;
55 using Teuchos::rcp;
56 using Teuchos::Array;
57 using Teuchos::ArrayRCP;
58 using Teuchos::arcp;
59 using Teuchos::ArrayView;
60 using Teuchos::arrayView;
61 using Teuchos::av_const_cast;
62 using Teuchos::av_reinterpret_cast;
64 using Teuchos::as;
65 using Teuchos::null;
67 
68 
69 TEUCHOS_UNIT_TEST( ArrayView, assignSelf )
70 {
71  ArrayView<int> av;
72  av = av;
73  TEST_ASSERT(is_null(av));
74  TEST_ASSERT(!nonnull(av));
75 }
76 
77 
78 TEUCHOS_UNIT_TEST( ArrayView, assignFuncSelf )
79 {
80  Array<int> a = generateArray<int>(n);
81  ArrayView<int> av = a;
82  av.assign(av);
83 }
84 
85 
86 TEUCHOS_UNIT_TEST( ArrayView, av_const_cast_null )
87 {
88  ArrayView<const int> av_int1 = null;
89  ArrayView<int> av_int2 = av_const_cast<int>(av_int1);
90  TEST_ASSERT(is_null(av_int2));
91 }
92 
93 
94 TEUCHOS_UNIT_TEST( ArrayView, av_const_cast )
95 {
96  ArrayRCP<const int> arcp_int = arcp<int>(n);
97  ArrayView<const int> av_int1 = arcp_int();
98  ArrayView<int> av_int2 = av_const_cast<int>(av_int1);
99  TEST_ASSERT(nonnull(av_int2));
100  TEST_EQUALITY(av_int2.getRawPtr(), av_int1.getRawPtr());
101  TEST_EQUALITY(av_int2.data(), av_int1.data());
102  TEST_EQUALITY(av_int2.getRawPtr(), arcp_int.getRawPtr());
103  TEST_EQUALITY(av_int2.data(), arcp_int.getRawPtr());
104 }
105 
106 
107 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_null )
108 {
109  ArrayView<char> av_char = null;
110  ArrayView<int> av_int = av_reinterpret_cast<int>(av_char);
111  TEST_ASSERT(is_null(av_int));
112 }
113 
114 
115 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_char_to_int )
116 {
117 
118  const int sizeOfInt = sizeof(int);
119  const int sizeOfChar = sizeof(char);
120  const int num_ints = n;
121  const int num_chars = (num_ints*sizeOfInt)/sizeOfChar;
122  out << "num_ints = " << num_ints << "\n";
123  out << "num_chars = " << num_chars << "\n";
124 
125  ArrayRCP<char> arcp_char = arcp<char>(num_chars);
126  ArrayView<int> av_int = av_reinterpret_cast<int>(arcp_char());
127  TEST_EQUALITY(av_int.size(), num_ints);
128  TEST_EQUALITY(implicit_ptr_cast<void>(&av_int[0]),
129  implicit_ptr_cast<void>(&arcp_char[0]));
130  TEST_EQUALITY(implicit_ptr_cast<void>((&av_int[num_ints-1])+1),
131  implicit_ptr_cast<void>((&arcp_char[num_chars-1])+1));
132 
133 }
134 
135 
136 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_int_to_char )
137 {
138 
139  const int sizeOfInt = sizeof(int);
140  const int sizeOfChar = sizeof(char);
141  const int num_ints = n;
142  const int num_chars = (num_ints*sizeOfInt)/sizeOfChar;
143  out << "num_ints = " << num_ints << "\n";
144  out << "num_chars = " << num_chars << "\n";
145 
146  ArrayRCP<int> arcp_int = arcp<int>(num_ints);
147  ArrayView<char> av_char = av_reinterpret_cast<char>(arcp_int());
148  TEST_EQUALITY(av_char.size(), num_chars);
149  TEST_EQUALITY(implicit_ptr_cast<void>(&arcp_int[0]),
150  implicit_ptr_cast<void>(&av_char[0]));
151  TEST_EQUALITY(implicit_ptr_cast<void>((&arcp_int[num_ints-1])+1),
152  implicit_ptr_cast<void>((&av_char[num_chars-1])+1));
153  TEST_EQUALITY(implicit_ptr_cast<void>((&arcp_int[num_ints-1])+1),
154  implicit_ptr_cast<void>((&av_char[num_chars-1])+1));
155 
156 }
157 
158 
159 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, arrayView_construct_zero_size, T )
160 {
161  Array<T> a;
162  const ArrayView<T> av = arrayView(a.getRawPtr(), a.size());
163  TEST_EQUALITY_CONST(av.size(), 0);
164  TEST_ASSERT(is_null(av));
165  TEST_ASSERT(!nonnull(av));
166 }
167 
168 
170 {
171  Array<T> a = generateArray<T>(n);
172  const ArrayView<T> av = arrayView(&a[0], a.size());
173  TEST_COMPARE_ARRAYS( a, av );
174 }
175 
176 
177 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, null_zero_ArrayView_operator, T )
178 {
179  const ArrayView<T> av_0;
180  const ArrayView<T> av = av_0(0, 0);
181  TEST_ASSERT(is_null(av));
182 }
183 
184 
185 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, null_zero_ArrayView_func, T )
186 {
187  const ArrayView<T> av_0;
188  const ArrayView<T> av = av_0.view(0, 0);
189  TEST_ASSERT(is_null(av));
190 }
191 
192 
193 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, raw_ptr_self_view, T )
194 {
195  T *data = new T[10];
196  ArrayView<T> view(data, 10);
197  view = view(0, 5);
198  TEST_EQUALITY(view.getRawPtr(), data);
199  TEST_EQUALITY(view.data(), data);
200  TEST_EQUALITY_CONST(view.size(), 5);
201  ArrayView<const T> cview = view.getConst();
202  TEST_EQUALITY(cview.getRawPtr(), const_cast<const T*>(data));
203  TEST_EQUALITY(cview.data(), const_cast<const T*>(data));
204  TEST_EQUALITY_CONST(cview.size(), 5);
205 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
206  ArrayRCP<const T> cview_arcp = cview.access_private_arcp();
207  TEST_EQUALITY(cview_arcp.getRawPtr(), const_cast<const T*>(data));
208  TEST_EQUALITY_CONST(cview_arcp.size(), 5);
209 #endif
210  delete [] data;
211 }
212 
213 
214 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, raw_ptr_self_view_const, T )
215 {
216  T const * data = new T[10];
217  ArrayView<const T> view(data, 10);
218  view = view(0, 5);
219  TEST_EQUALITY(view.getRawPtr(), data);
220  TEST_EQUALITY(view.data(), data);
221  TEST_EQUALITY_CONST(view.size(), 5);
222  ArrayView<const T> cview = view.getConst();
223  TEST_EQUALITY(cview.getRawPtr(), data);
224  TEST_EQUALITY(cview.data(), data);
225  TEST_EQUALITY_CONST(cview.size(), 5);
226 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
227  ArrayRCP<const T> cview_arcp = cview.access_private_arcp();
228  TEST_EQUALITY(cview_arcp.getRawPtr(), data);
229  TEST_EQUALITY_CONST(cview_arcp.size(), 5);
230 #endif
231  delete [] data;
232 }
233 
234 
235 template<typename T>
236 void resizeRawView(
237  Teuchos::ArrayView<T> &view_inout, Teuchos::Ordinal offset, Teuchos::Ordinal size
238  )
239 {
240  if (view_inout.size() == 0 && size == 0) { return; }
241 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
242  const T &next_to_last = view_inout[offset+size-1];
243  (void)next_to_last;
244 #endif
245  view_inout = arrayView<T>(&view_inout[offset], size);
246 }
247 
248 
249 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, resize_raw_ptr_self_view, T )
250 {
251  T *data = new T[10];
252  ArrayView<T> view(data, 10);
253  resizeRawView(view, 0, 5);
254  TEST_EQUALITY(view.getRawPtr(), data);
255  TEST_EQUALITY(view.data(), data);
256  TEST_EQUALITY_CONST(view.size(), 5);
257  delete [] data;
258  // NOTE: The above works because we are creating a completely new ArrayView
259  // object and are not viewing the original array object which is going away.
260 }
261 
262 
263 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, assignmentOperator, T )
264 {
265  Array<T> a = generateArray<T>(n);
266  ArrayView<T> av1;
267  av1 = a;
268  ArrayView<T> av2;
269  av2 = av1;
270  TEST_EQUALITY( av1.getRawPtr(), a.getRawPtr() );
271  TEST_EQUALITY( av1.data(), a.data() );
272  TEST_EQUALITY( av1.getRawPtr(), a.data() );
273  TEST_EQUALITY( av1.data(), a.getRawPtr() );
274  TEST_EQUALITY( av1.size(), as<int>(a.size()) );
275  TEST_EQUALITY( av1.getRawPtr(), av2.getRawPtr() );
276  TEST_EQUALITY( av1.data(), av2.data() );
277  TEST_EQUALITY( av1.data(), av2.getRawPtr() );
278  TEST_EQUALITY( av1.getRawPtr(), av2.data() );
279  TEST_EQUALITY( av1.size(), av2.size() );
280  TEST_COMPARE_ARRAYS( av1, a );
281  TEST_COMPARE_ARRAYS( av1, av2 );
282  av1 = null;
283  TEST_EQUALITY_CONST( av1.getRawPtr(), 0 );
284  TEST_EQUALITY_CONST( av1.data(), 0 );
285  TEST_EQUALITY_CONST( av1.size(), 0 );
286  av2 = null;
287  TEST_EQUALITY_CONST( av2.getRawPtr(), 0 );
288  TEST_EQUALITY_CONST( av2.data(), 0 );
289  TEST_EQUALITY_CONST( av2.size(), 0 );
290 }
291 
292 
293 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, iterators, T )
294 {
295  typedef typename ArrayView<T>::iterator iter_t;
296  typedef Teuchos::ScalarTraits<T> ST;
297  ECHO(Array<T> a = generateArray<T>(n));
298  ECHO(ArrayView<T> av = a);
299  ECHO(const iter_t av_begin = av.begin());
300  ECHO(const iter_t av_end = av.end());
301 #ifdef TEUCHOS_DEBUG
302  TEST_ASSERT(av_begin.shares_resource(av_end));
303 #endif
304  ECHO(std::fill(av_begin, av_end, ST::random()));
305  ECHO(Array<T> a2 = generateArray<T>(n));
306  ECHO(ArrayView<T> av2 = a2);
307  ECHO(std::copy(av.begin(), av.end(), av2.begin()));
308  TEST_COMPARE_ARRAYS(a, a2);
309 }
310 
311 
312 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, arrayView_convertToConst, T )
313 {
314  const int nsize = 3;
315  T t[nsize];
316  t[0] = 1;
317  t[1] = 2;
318  t[2] = 3;
319  ArrayView<const T> av1 = arrayView<T>(&t[0], nsize);
320  TEST_EQUALITY_CONST(av1[0], 1);
321  TEST_EQUALITY_CONST(av1[1], 2);
322  TEST_EQUALITY_CONST(av1[2], 3);
323 }
324 
325 
326 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, danglingView_std_vector, T )
327 {
328  ArrayView<T> av;
329  T* badPtr = 0;
330  {
331  std::vector<T> v(n);
332  av = v;
333  badPtr = &v[0];
334  }
335  // Access the raw pointer but it now points to invalid memory!
336  TEST_EQUALITY(av.getRawPtr(), badPtr);
337  TEST_EQUALITY(av.data(), badPtr);
338  // Above, we have no way to detect that the underlying std::vector object
339  // has gone away. This is the whole point of needing Teuchos::Array and
340  // having an integrated set of utility classes that all work together!
341 }
342 
343 
344 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, danglingView_rcp_std_vector, T )
345 {
346  ArrayView<T> av;
347  {
348  ArrayRCP<T> ap = arcp(rcp(new std::vector<T>(n)));
349  av = ap();
350  }
351 #ifdef TEUCHOS_DEBUG
352  TEST_THROW(av.getRawPtr(), DanglingReferenceError);
353  TEST_THROW(av.data(), DanglingReferenceError);
354 #endif
355  // Above, because we wrapped the initial std::vector in an RCP object, we
356  // can sucessfully detect when the object goes away in debug mode!
357 }
358 
359 
360 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
361 
362 
363 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
364 
365 
366 //
367 // Instantiations
368 //
369 
370 
371 
372 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
373 
374 # define DEBUG_UNIT_TEST_GROUP( T )
375 
376 #else // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
377 
378 # define DEBUG_UNIT_TEST_GROUP( T )
379 
380 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
381 
382 
383 #define UNIT_TEST_GROUP( T ) \
384  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView_construct_zero_size, T ) \
385  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView, T ) \
386  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, null_zero_ArrayView_operator, T ) \
387  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, null_zero_ArrayView_func, T ) \
388  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, raw_ptr_self_view, T ) \
389  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, raw_ptr_self_view_const, T ) \
390  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, resize_raw_ptr_self_view, T ) \
391  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, assignmentOperator, T ) \
392  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, iterators, T ) \
393  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView_convertToConst, T ) \
394  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, danglingView_std_vector, T ) \
395  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, danglingView_rcp_std_vector, T ) \
396  DEBUG_UNIT_TEST_GROUP( T )
397 
398 
399 UNIT_TEST_GROUP(int)
400 UNIT_TEST_GROUP(float)
401 UNIT_TEST_GROUP(double)
402 
403 
404 } // namespace
Dangling reference error exception class.
RCP< T > rcp(const boost::shared_ptr< T > &sptr)
Conversion function that takes in a boost::shared_ptr object and spits out a Teuchos::RCP object...
ArrayView< T > arrayView(T *p, typename ArrayView< T >::size_type size)
Construct a const or non-const view to const or non-const data.
#define TEST_ASSERT(v1)
Assert the given statement is true.
#define UNIT_TEST_GROUP(T)
#define ECHO(statement)
Echo the given statement before it is executed.
#define TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(TEST_GROUP, TEST_NAME, TYPE)
Macro for defining a templated unit test with one template parameter.
size_type size() const
The total number of items in the managed array.
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
#define TEST_THROW(code, ExceptType)
Assert that the statement &#39;code&#39; throws the exception &#39;ExceptType&#39; (otherwise the test fails)...
ArrayRCP< T > arcp(const RCP< Array< T > > &v)
Wrap an RCP&lt;Array&lt;T&gt; &gt; object as an ArrayRCP&lt;T&gt; object.
#define TEUCHOS_UNIT_TEST(TEST_GROUP, TEST_NAME)
Macro for defining a (non-templated) unit test.
bool is_null(const ArrayRCP< T > &p)
Returns true if p.get()==NULL.
This structure defines some basic traits for a scalar field type.
ArrayView< T2 > av_reinterpret_cast(const ArrayView< T1 > &p1)
Reinterpret cast of underlying ArrayView type from T1* to T2*.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
ArrayView< T2 > av_const_cast(const ArrayView< T1 > &p1)
Const cast of underlying ArrayView type from const T* to T*.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
TypeTo * implicit_ptr_cast(TypeFrom *t)
Perform an implicit cast of pointer types with a pointer being returned.
int size(const Comm< Ordinal > &comm)
Get the number of processes in the communicator.
Teuchos::Array< T > generateArray(const int n_in)
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
#define TEST_COMPARE_ARRAYS(a1, a2)
Assert that a1.size()==a2.size() and a[i]==b[i], i=0....
Nonowning array view.
Smart reference counting pointer class for automatic garbage collection.
bool nonnull(const ArrayRCP< T > &p)
Returns true if p.get()!=NULL.
Reference-counted smart pointer for managing arrays.
Replacement for std::vector that is compatible with the Teuchos Memory Management classes...