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 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
11 
13 
14 
15 namespace {
16 
17 
20 using Teuchos::RCP;
21 using Teuchos::rcp;
22 using Teuchos::Array;
23 using Teuchos::ArrayRCP;
24 using Teuchos::arcp;
25 using Teuchos::ArrayView;
26 using Teuchos::arrayView;
27 using Teuchos::av_const_cast;
28 using Teuchos::av_reinterpret_cast;
30 using Teuchos::as;
31 using Teuchos::null;
33 
34 
35 TEUCHOS_UNIT_TEST( ArrayView, assignSelf )
36 {
37  ArrayView<int> av;
38  av = av;
39  TEST_ASSERT(is_null(av));
40  TEST_ASSERT(!nonnull(av));
41 }
42 
43 
44 TEUCHOS_UNIT_TEST( ArrayView, assignFuncSelf )
45 {
46  Array<int> a = generateArray<int>(n);
47  ArrayView<int> av = a;
48  av.assign(av);
49 }
50 
51 
52 TEUCHOS_UNIT_TEST( ArrayView, av_const_cast_null )
53 {
54  ArrayView<const int> av_int1 = null;
55  ArrayView<int> av_int2 = av_const_cast<int>(av_int1);
56  TEST_ASSERT(is_null(av_int2));
57 }
58 
59 
60 TEUCHOS_UNIT_TEST( ArrayView, av_const_cast )
61 {
62  ArrayRCP<const int> arcp_int = arcp<int>(n);
63  ArrayView<const int> av_int1 = arcp_int();
64  ArrayView<int> av_int2 = av_const_cast<int>(av_int1);
65  TEST_ASSERT(nonnull(av_int2));
66  TEST_EQUALITY(av_int2.getRawPtr(), av_int1.getRawPtr());
67  TEST_EQUALITY(av_int2.data(), av_int1.data());
68  TEST_EQUALITY(av_int2.getRawPtr(), arcp_int.getRawPtr());
69  TEST_EQUALITY(av_int2.data(), arcp_int.getRawPtr());
70 }
71 
72 
73 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_null )
74 {
75  ArrayView<char> av_char = null;
76  ArrayView<int> av_int = av_reinterpret_cast<int>(av_char);
77  TEST_ASSERT(is_null(av_int));
78 }
79 
80 
81 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_char_to_int )
82 {
83 
84  const int sizeOfInt = sizeof(int);
85  const int sizeOfChar = sizeof(char);
86  const int num_ints = n;
87  const int num_chars = (num_ints*sizeOfInt)/sizeOfChar;
88  out << "num_ints = " << num_ints << "\n";
89  out << "num_chars = " << num_chars << "\n";
90 
91  ArrayRCP<char> arcp_char = arcp<char>(num_chars);
92  ArrayView<int> av_int = av_reinterpret_cast<int>(arcp_char());
93  TEST_EQUALITY(av_int.size(), num_ints);
94  TEST_EQUALITY(implicit_ptr_cast<void>(&av_int[0]),
95  implicit_ptr_cast<void>(&arcp_char[0]));
96  TEST_EQUALITY(implicit_ptr_cast<void>((&av_int[num_ints-1])+1),
97  implicit_ptr_cast<void>((&arcp_char[num_chars-1])+1));
98 
99 }
100 
101 
102 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_int_to_char )
103 {
104 
105  const int sizeOfInt = sizeof(int);
106  const int sizeOfChar = sizeof(char);
107  const int num_ints = n;
108  const int num_chars = (num_ints*sizeOfInt)/sizeOfChar;
109  out << "num_ints = " << num_ints << "\n";
110  out << "num_chars = " << num_chars << "\n";
111 
112  ArrayRCP<int> arcp_int = arcp<int>(num_ints);
113  ArrayView<char> av_char = av_reinterpret_cast<char>(arcp_int());
114  TEST_EQUALITY(av_char.size(), num_chars);
115  TEST_EQUALITY(implicit_ptr_cast<void>(&arcp_int[0]),
116  implicit_ptr_cast<void>(&av_char[0]));
117  TEST_EQUALITY(implicit_ptr_cast<void>((&arcp_int[num_ints-1])+1),
118  implicit_ptr_cast<void>((&av_char[num_chars-1])+1));
119  TEST_EQUALITY(implicit_ptr_cast<void>((&arcp_int[num_ints-1])+1),
120  implicit_ptr_cast<void>((&av_char[num_chars-1])+1));
121 
122 }
123 
124 
125 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, arrayView_construct_zero_size, T )
126 {
127  Array<T> a;
128  const ArrayView<T> av = arrayView(a.getRawPtr(), a.size());
129  TEST_EQUALITY_CONST(av.size(), 0);
130  TEST_ASSERT(is_null(av));
131  TEST_ASSERT(!nonnull(av));
132 }
133 
134 
136 {
137  Array<T> a = generateArray<T>(n);
138  const ArrayView<T> av = arrayView(&a[0], a.size());
139  TEST_COMPARE_ARRAYS( a, av );
140 }
141 
142 
143 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, null_zero_ArrayView_operator, T )
144 {
145  const ArrayView<T> av_0;
146  const ArrayView<T> av = av_0(0, 0);
147  TEST_ASSERT(is_null(av));
148 }
149 
150 
151 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, null_zero_ArrayView_func, T )
152 {
153  const ArrayView<T> av_0;
154  const ArrayView<T> av = av_0.view(0, 0);
155  TEST_ASSERT(is_null(av));
156 }
157 
158 
159 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, raw_ptr_self_view, T )
160 {
161  T *data = new T[10];
162  ArrayView<T> view(data, 10);
163  view = view(0, 5);
164  TEST_EQUALITY(view.getRawPtr(), data);
165  TEST_EQUALITY(view.data(), data);
166  TEST_EQUALITY_CONST(view.size(), 5);
167  ArrayView<const T> cview = view.getConst();
168  TEST_EQUALITY(cview.getRawPtr(), const_cast<const T*>(data));
169  TEST_EQUALITY(cview.data(), const_cast<const T*>(data));
170  TEST_EQUALITY_CONST(cview.size(), 5);
171 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
172  ArrayRCP<const T> cview_arcp = cview.access_private_arcp();
173  TEST_EQUALITY(cview_arcp.getRawPtr(), const_cast<const T*>(data));
174  TEST_EQUALITY_CONST(cview_arcp.size(), 5);
175 #endif
176  delete [] data;
177 }
178 
179 
180 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, raw_ptr_self_view_const, T )
181 {
182  T const * data = new T[10];
183  ArrayView<const T> view(data, 10);
184  view = view(0, 5);
185  TEST_EQUALITY(view.getRawPtr(), data);
186  TEST_EQUALITY(view.data(), data);
187  TEST_EQUALITY_CONST(view.size(), 5);
188  ArrayView<const T> cview = view.getConst();
189  TEST_EQUALITY(cview.getRawPtr(), data);
190  TEST_EQUALITY(cview.data(), data);
191  TEST_EQUALITY_CONST(cview.size(), 5);
192 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
193  ArrayRCP<const T> cview_arcp = cview.access_private_arcp();
194  TEST_EQUALITY(cview_arcp.getRawPtr(), data);
195  TEST_EQUALITY_CONST(cview_arcp.size(), 5);
196 #endif
197  delete [] data;
198 }
199 
200 
201 template<typename T>
202 void resizeRawView(
203  Teuchos::ArrayView<T> &view_inout, Teuchos::Ordinal offset, Teuchos::Ordinal size
204  )
205 {
206  if (view_inout.size() == 0 && size == 0) { return; }
207 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
208  const T &next_to_last = view_inout[offset+size-1];
209  (void)next_to_last;
210 #endif
211  view_inout = arrayView<T>(&view_inout[offset], size);
212 }
213 
214 
215 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, resize_raw_ptr_self_view, T )
216 {
217  T *data = new T[10];
218  ArrayView<T> view(data, 10);
219  resizeRawView(view, 0, 5);
220  TEST_EQUALITY(view.getRawPtr(), data);
221  TEST_EQUALITY(view.data(), data);
222  TEST_EQUALITY_CONST(view.size(), 5);
223  delete [] data;
224  // NOTE: The above works because we are creating a completely new ArrayView
225  // object and are not viewing the original array object which is going away.
226 }
227 
228 
229 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, assignmentOperator, T )
230 {
231  Array<T> a = generateArray<T>(n);
232  ArrayView<T> av1;
233  av1 = a;
234  ArrayView<T> av2;
235  av2 = av1;
236  TEST_EQUALITY( av1.getRawPtr(), a.getRawPtr() );
237  TEST_EQUALITY( av1.data(), a.data() );
238  TEST_EQUALITY( av1.getRawPtr(), a.data() );
239  TEST_EQUALITY( av1.data(), a.getRawPtr() );
240  TEST_EQUALITY( av1.size(), as<int>(a.size()) );
241  TEST_EQUALITY( av1.getRawPtr(), av2.getRawPtr() );
242  TEST_EQUALITY( av1.data(), av2.data() );
243  TEST_EQUALITY( av1.data(), av2.getRawPtr() );
244  TEST_EQUALITY( av1.getRawPtr(), av2.data() );
245  TEST_EQUALITY( av1.size(), av2.size() );
246  TEST_COMPARE_ARRAYS( av1, a );
247  TEST_COMPARE_ARRAYS( av1, av2 );
248  av1 = null;
249  TEST_EQUALITY_CONST( av1.getRawPtr(), 0 );
250  TEST_EQUALITY_CONST( av1.data(), 0 );
251  TEST_EQUALITY_CONST( av1.size(), 0 );
252  av2 = null;
253  TEST_EQUALITY_CONST( av2.getRawPtr(), 0 );
254  TEST_EQUALITY_CONST( av2.data(), 0 );
255  TEST_EQUALITY_CONST( av2.size(), 0 );
256 }
257 
258 
259 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, iterators, T )
260 {
261  typedef typename ArrayView<T>::iterator iter_t;
262  typedef Teuchos::ScalarTraits<T> ST;
263  ECHO(Array<T> a = generateArray<T>(n));
264  ECHO(ArrayView<T> av = a);
265  ECHO(const iter_t av_begin = av.begin());
266  ECHO(const iter_t av_end = av.end());
267 #ifdef TEUCHOS_DEBUG
268  TEST_ASSERT(av_begin.shares_resource(av_end));
269 #endif
270  ECHO(std::fill(av_begin, av_end, ST::random()));
271  ECHO(Array<T> a2 = generateArray<T>(n));
272  ECHO(ArrayView<T> av2 = a2);
273  ECHO(std::copy(av.begin(), av.end(), av2.begin()));
274  TEST_COMPARE_ARRAYS(a, a2);
275 }
276 
277 
278 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, arrayView_convertToConst, T )
279 {
280  const int nsize = 3;
281  T t[nsize];
282  t[0] = 1;
283  t[1] = 2;
284  t[2] = 3;
285  ArrayView<const T> av1 = arrayView<T>(&t[0], nsize);
286  TEST_EQUALITY_CONST(av1[0], 1);
287  TEST_EQUALITY_CONST(av1[1], 2);
288  TEST_EQUALITY_CONST(av1[2], 3);
289 }
290 
291 
292 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, danglingView_std_vector, T )
293 {
294  ArrayView<T> av;
295  T* badPtr = 0;
296  {
297  std::vector<T> v(n);
298  av = v;
299  badPtr = &v[0];
300  }
301  // Access the raw pointer but it now points to invalid memory!
302  TEST_EQUALITY(av.getRawPtr(), badPtr);
303  TEST_EQUALITY(av.data(), badPtr);
304  // Above, we have no way to detect that the underlying std::vector object
305  // has gone away. This is the whole point of needing Teuchos::Array and
306  // having an integrated set of utility classes that all work together!
307 }
308 
309 
310 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, danglingView_rcp_std_vector, T )
311 {
312  ArrayView<T> av;
313  {
314  ArrayRCP<T> ap = arcp(rcp(new std::vector<T>(n)));
315  av = ap();
316  }
317 #ifdef TEUCHOS_DEBUG
318  TEST_THROW(av.getRawPtr(), DanglingReferenceError);
319  TEST_THROW(av.data(), DanglingReferenceError);
320 #endif
321  // Above, because we wrapped the initial std::vector in an RCP object, we
322  // can sucessfully detect when the object goes away in debug mode!
323 }
324 
325 
326 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
327 
328 
329 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
330 
331 
332 //
333 // Instantiations
334 //
335 
336 
337 
338 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
339 
340 # define DEBUG_UNIT_TEST_GROUP( T )
341 
342 #else // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
343 
344 # define DEBUG_UNIT_TEST_GROUP( T )
345 
346 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
347 
348 
349 #define UNIT_TEST_GROUP( T ) \
350  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView_construct_zero_size, T ) \
351  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView, T ) \
352  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, null_zero_ArrayView_operator, T ) \
353  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, null_zero_ArrayView_func, T ) \
354  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, raw_ptr_self_view, T ) \
355  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, raw_ptr_self_view_const, T ) \
356  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, resize_raw_ptr_self_view, T ) \
357  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, assignmentOperator, T ) \
358  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, iterators, T ) \
359  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView_convertToConst, T ) \
360  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, danglingView_std_vector, T ) \
361  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, danglingView_rcp_std_vector, T ) \
362  DEBUG_UNIT_TEST_GROUP( T )
363 
364 
365 UNIT_TEST_GROUP(int)
366 UNIT_TEST_GROUP(float)
367 UNIT_TEST_GROUP(double)
368 
369 
370 } // 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...