Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ArrayView_UnitTests.cpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 //
00005 //                    Teuchos: Common Tools Package
00006 //                 Copyright (2004) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 // @HEADER
00042 */
00043 
00044 #include "Array_UnitTest_helpers.hpp"
00045 
00046 #include "Teuchos_implicit_cast.hpp"
00047 
00048 
00049 namespace {
00050 
00051 
00052 using ArrayUnitTestHelpers::n;
00053 using ArrayUnitTestHelpers::generateArray;
00054 using Teuchos::RCP;
00055 using Teuchos::rcp;
00056 using Teuchos::Array;
00057 using Teuchos::ArrayRCP;
00058 using Teuchos::arcp;
00059 using Teuchos::ArrayView;
00060 using Teuchos::arrayView;
00061 using Teuchos::av_const_cast;
00062 using Teuchos::av_reinterpret_cast;
00063 using Teuchos::DanglingReferenceError;
00064 using Teuchos::as;
00065 using Teuchos::null;
00066 using Teuchos::implicit_ptr_cast;
00067 
00068 
00069 TEUCHOS_UNIT_TEST( ArrayView, assignSelf )
00070 {
00071   ArrayView<int> av;
00072   av = av;
00073   TEST_ASSERT(is_null(av));
00074   TEST_ASSERT(!nonnull(av));
00075 }
00076 
00077 
00078 TEUCHOS_UNIT_TEST( ArrayView, assignFuncSelf )
00079 {
00080   Array<int> a = generateArray<int>(n);
00081   ArrayView<int> av = a;
00082   av.assign(av);
00083 }
00084 
00085 
00086 TEUCHOS_UNIT_TEST( ArrayView, av_const_cast_null )
00087 {
00088   ArrayView<const int> av_int1 = null;
00089   ArrayView<int> av_int2 = av_const_cast<int>(av_int1);
00090   TEST_ASSERT(is_null(av_int2));
00091 }
00092 
00093 
00094 TEUCHOS_UNIT_TEST( ArrayView, av_const_cast )
00095 {
00096   ArrayRCP<const int> arcp_int = arcp<int>(n);
00097   ArrayView<const int> av_int1 = arcp_int();
00098   ArrayView<int> av_int2 = av_const_cast<int>(av_int1);
00099   TEST_ASSERT(nonnull(av_int2));
00100   TEST_EQUALITY(av_int2.getRawPtr(), av_int1.getRawPtr());
00101   TEST_EQUALITY(av_int2.getRawPtr(), arcp_int.getRawPtr());
00102 }
00103 
00104 
00105 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_null )
00106 {
00107   ArrayView<char> av_char = null;
00108   ArrayView<int> av_int = av_reinterpret_cast<int>(av_char);
00109   TEST_ASSERT(is_null(av_int));
00110 }
00111 
00112 
00113 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_char_to_int )
00114 {
00115 
00116   const int sizeOfInt = sizeof(int);
00117   const int sizeOfChar = sizeof(char);
00118   const int num_ints = n;
00119   const int num_chars = (num_ints*sizeOfInt)/sizeOfChar;
00120   out << "num_ints = " << num_ints << "\n";
00121   out << "num_chars = " << num_chars << "\n";
00122 
00123   ArrayRCP<char> arcp_char = arcp<char>(num_chars);
00124   ArrayView<int> av_int = av_reinterpret_cast<int>(arcp_char());
00125   TEST_EQUALITY(av_int.size(), num_ints);
00126   TEST_EQUALITY(implicit_ptr_cast<void>(&av_int[0]),
00127     implicit_ptr_cast<void>(&arcp_char[0]));
00128   TEST_EQUALITY(implicit_ptr_cast<void>((&av_int[num_ints-1])+1),
00129     implicit_ptr_cast<void>((&arcp_char[num_chars-1])+1));
00130 
00131 }
00132 
00133 
00134 TEUCHOS_UNIT_TEST( ArrayView, av_reinterpret_cast_int_to_char )
00135 {
00136 
00137   const int sizeOfInt = sizeof(int);
00138   const int sizeOfChar = sizeof(char);
00139   const int num_ints = n;
00140   const int num_chars = (num_ints*sizeOfInt)/sizeOfChar;
00141   out << "num_ints = " << num_ints << "\n";
00142   out << "num_chars = " << num_chars << "\n";
00143 
00144   ArrayRCP<int> arcp_int = arcp<int>(num_ints);
00145   ArrayView<char> av_char = av_reinterpret_cast<char>(arcp_int());
00146   TEST_EQUALITY(av_char.size(), num_chars);
00147   TEST_EQUALITY(implicit_ptr_cast<void>(&arcp_int[0]),
00148     implicit_ptr_cast<void>(&av_char[0]));
00149   TEST_EQUALITY(implicit_ptr_cast<void>((&arcp_int[num_ints-1])+1),
00150     implicit_ptr_cast<void>((&av_char[num_chars-1])+1));
00151   TEST_EQUALITY(implicit_ptr_cast<void>((&arcp_int[num_ints-1])+1),
00152     implicit_ptr_cast<void>((&av_char[num_chars-1])+1));
00153 
00154 }
00155 
00156 
00157 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, arrayView_construct_zero_size, T )
00158 {
00159   Array<T> a;
00160   const ArrayView<T> av = arrayView(a.getRawPtr(), a.size());
00161   TEST_EQUALITY_CONST(av.size(), 0);
00162   TEST_ASSERT(is_null(av));
00163   TEST_ASSERT(!nonnull(av));
00164 }
00165 
00166 
00167 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, arrayView, T )
00168 {
00169   Array<T> a = generateArray<T>(n);
00170   const ArrayView<T> av = arrayView(&a[0], a.size());
00171   TEST_COMPARE_ARRAYS( a, av );
00172 }
00173 
00174 
00175 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, null_zero_ArrayView_operator, T )
00176 {
00177   const ArrayView<T> av_0;
00178   const ArrayView<T> av = av_0(0, 0);
00179   TEST_ASSERT(is_null(av));
00180 }
00181 
00182 
00183 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, null_zero_ArrayView_func, T )
00184 {
00185   const ArrayView<T> av_0;
00186   const ArrayView<T> av = av_0.view(0, 0);
00187   TEST_ASSERT(is_null(av));
00188 }
00189 
00190 
00191 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, raw_ptr_self_view, T )
00192 {
00193   T *data = new T[10];
00194   ArrayView<T> view(data, 10);
00195   view = view(0, 5);
00196   TEST_EQUALITY(view.getRawPtr(), data);
00197   TEST_EQUALITY_CONST(view.size(), 5);
00198   ArrayView<const T> cview = view.getConst();
00199   TEST_EQUALITY(cview.getRawPtr(), const_cast<const T*>(data));
00200   TEST_EQUALITY_CONST(cview.size(), 5);
00201 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00202   ArrayRCP<const T> cview_arcp = cview.access_private_arcp();
00203   TEST_EQUALITY(cview_arcp.getRawPtr(), const_cast<const T*>(data));
00204   TEST_EQUALITY_CONST(cview_arcp.size(), 5);
00205 #endif
00206   delete [] data;
00207 }
00208 
00209 
00210 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, raw_ptr_self_view_const, T )
00211 {
00212   T const * data = new T[10];
00213   ArrayView<const T> view(data, 10);
00214   view = view(0, 5);
00215   TEST_EQUALITY(view.getRawPtr(), data);
00216   TEST_EQUALITY_CONST(view.size(), 5);
00217   ArrayView<const T> cview = view.getConst();
00218   TEST_EQUALITY(cview.getRawPtr(), data);
00219   TEST_EQUALITY_CONST(cview.size(), 5);
00220 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00221   ArrayRCP<const T> cview_arcp = cview.access_private_arcp();
00222   TEST_EQUALITY(cview_arcp.getRawPtr(), data);
00223   TEST_EQUALITY_CONST(cview_arcp.size(), 5);
00224 #endif
00225   delete [] data;
00226 }
00227 
00228 
00229 template<typename T>
00230 void resizeRawView(
00231   Teuchos::ArrayView<T> &view_inout, Teuchos::Ordinal offset, Teuchos::Ordinal size
00232   )
00233 {
00234   if (view_inout.size() == 0 && size == 0) { return; }
00235 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00236   const T &next_to_last = view_inout[offset+size-1];
00237   (void)next_to_last;
00238 #endif
00239   view_inout = arrayView<T>(&view_inout[offset], size);
00240 }
00241 
00242 
00243 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, resize_raw_ptr_self_view, T )
00244 {
00245   T *data = new T[10];
00246   ArrayView<T> view(data, 10);
00247   resizeRawView(view, 0, 5);
00248   TEST_EQUALITY(view.getRawPtr(), data);
00249   TEST_EQUALITY_CONST(view.size(), 5);
00250   delete [] data;
00251   // NOTE: The above works because we are creating a completely new ArrayView
00252   // object and are not viewing the original array object which is going away.
00253 }
00254 
00255 
00256 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, assignmentOperator, T )
00257 {
00258   Array<T> a = generateArray<T>(n);
00259   ArrayView<T> av1;
00260   av1 = a;
00261   ArrayView<T> av2;
00262   av2 = av1;
00263   TEST_EQUALITY( av1.getRawPtr(), a.getRawPtr() );
00264   TEST_EQUALITY( av1.size(), as<int>(a.size()) );
00265   TEST_EQUALITY( av1.getRawPtr(), av2.getRawPtr() );
00266   TEST_EQUALITY( av1.size(), av2.size() );
00267   TEST_COMPARE_ARRAYS( av1, a );
00268   TEST_COMPARE_ARRAYS( av1, av2 );
00269   av1 = null;
00270   TEST_EQUALITY_CONST( av1.getRawPtr(), 0 );
00271   TEST_EQUALITY_CONST( av1.size(), 0 );
00272   av2 = null;
00273   TEST_EQUALITY_CONST( av2.getRawPtr(), 0 );
00274   TEST_EQUALITY_CONST( av2.size(), 0 );
00275 }
00276 
00277 
00278 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, iterators, T )
00279 {
00280   typedef typename ArrayView<T>::iterator iter_t;
00281   typedef Teuchos::ScalarTraits<T> ST;
00282   ECHO(Array<T> a = generateArray<T>(n));
00283   ECHO(ArrayView<T> av = a);
00284   ECHO(const iter_t av_begin = av.begin());
00285   ECHO(const iter_t av_end = av.end());
00286 #ifdef TEUCHOS_DEBUG
00287   TEST_ASSERT(av_begin.shares_resource(av_end));
00288 #endif
00289   ECHO(std::fill(av_begin, av_end, ST::random()));
00290   ECHO(Array<T> a2 = generateArray<T>(n));
00291   ECHO(ArrayView<T> av2 = a2);
00292   ECHO(std::copy(av.begin(), av.end(), av2.begin()));
00293   TEST_COMPARE_ARRAYS(a, a2);
00294 }
00295 
00296 
00297 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, danglingView_std_vector, T )
00298 {
00299   ArrayView<T> av;
00300   T* badPtr = 0;
00301   {
00302     std::vector<T> v(n);
00303     av = v;
00304     badPtr = &v[0];
00305   }
00306   // Access the raw pointer but it now points to invalid memory!
00307   TEST_EQUALITY(av.getRawPtr(), badPtr);
00308   // Above, we have no way to detect that the underlying std::vector object
00309   // has gone away.  This is the whole point of needing Teuchos::Array and
00310   // having an integrated set of utility classes that all work together!
00311 }
00312 
00313 
00314 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( ArrayView, danglingView_rcp_std_vector, T )
00315 {
00316   ArrayView<T> av;
00317   {
00318     ArrayRCP<T> ap = arcp(rcp(new std::vector<T>(n)));
00319     av = ap();
00320   }
00321 #ifdef TEUCHOS_DEBUG
00322   TEST_THROW(av.getRawPtr(), DanglingReferenceError);
00323 #endif
00324   // Above, because we wrapped the initial std::vector in an RCP object, we
00325   // can sucessfully detect when the object goes away in debug mode!
00326 }
00327 
00328 
00329 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00330 
00331 
00332 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00333 
00334 
00335 //
00336 // Instantiations
00337 //
00338 
00339 
00340 
00341 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00342 
00343 #  define DEBUG_UNIT_TEST_GROUP( T )
00344 
00345 #else // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00346 
00347 #  define DEBUG_UNIT_TEST_GROUP( T )
00348 
00349 #endif // HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00350 
00351 
00352 #define UNIT_TEST_GROUP( T ) \
00353   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView_construct_zero_size, T ) \
00354   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, arrayView, T ) \
00355   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, null_zero_ArrayView_operator, T ) \
00356   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, null_zero_ArrayView_func, T ) \
00357   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, raw_ptr_self_view, T ) \
00358   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, raw_ptr_self_view_const, T ) \
00359   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, resize_raw_ptr_self_view, T ) \
00360   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, assignmentOperator, T ) \
00361   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, iterators, T ) \
00362   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, danglingView_std_vector, T ) \
00363   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( ArrayView, danglingView_rcp_std_vector, T ) \
00364   DEBUG_UNIT_TEST_GROUP( T )
00365 
00366 
00367 UNIT_TEST_GROUP(int)
00368 UNIT_TEST_GROUP(float)
00369 UNIT_TEST_GROUP(double)
00370 
00371 
00372 } // namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines