1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //  This software is distributed WITHOUT ANY WARRANTY; without even
6 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 //  PURPOSE.  See the above copyright notice for more information.
8 //
9 //  Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 //  Copyright 2014 UT-Battelle, LLC.
11 //  Copyright 2014 Los Alamos National Security.
12 //
13 //  Under the terms of Contract DE-NA0003525 with NTESS,
14 //  the U.S. Government retains certain rights in this software.
15 //
16 //  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 //  Laboratory (LANL), the U.S. Government retains certain rights in
18 //  this software.
19 //============================================================================
20 
21 #include <vtkm/cont/ArrayHandle.h>
22 #include <vtkm/cont/StorageBasic.h>
23 
24 #include <vtkm/VecTraits.h>
25 #include <vtkm/cont/testing/Testing.h>
26 
27 #if defined(VTKM_STORAGE)
28 #undef VTKM_STORAGE
29 #endif
30 
31 #define VTKM_STORAGE VTKM_STORAGE_ERROR
32 
33 namespace
34 {
35 
36 const vtkm::Id ARRAY_SIZE = 10;
37 
38 template <typename T>
39 struct TemplatedTests
40 {
41   using StorageType = vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic>;
42   using ValueType = typename StorageType::ValueType;
43   using PortalType = typename StorageType::PortalType;
44 
SetStorage__anon9c0f15680111::TemplatedTests45   void SetStorage(StorageType& array, const ValueType& value)
46   {
47     PortalType portal = array.GetPortal();
48     for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); index++)
49     {
50       portal.Set(index, value);
51     }
52   }
53 
CheckStorage__anon9c0f15680111::TemplatedTests54   bool CheckStorage(StorageType& array, const ValueType& value)
55   {
56     PortalType portal = array.GetPortal();
57     for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); index++)
58     {
59       if (!test_equal(portal.Get(index), value))
60       {
61         return false;
62       }
63     }
64     return true;
65   }
66 
STOLEN_ARRAY_VALUE__anon9c0f15680111::TemplatedTests67   typename vtkm::VecTraits<ValueType>::ComponentType STOLEN_ARRAY_VALUE() { return 29; }
68 
69   /// Returned value should later be passed to StealArray2.  It is best to
70   /// put as much between the two test parts to maximize the chance of a
71   /// deallocated array being overridden (and thus detected).
StealArray1__anon9c0f15680111::TemplatedTests72   ValueType* StealArray1()
73   {
74     ValueType* stolenArray;
75 
76     ValueType stolenArrayValue = ValueType(STOLEN_ARRAY_VALUE());
77 
78     StorageType stealMyArray;
79     stealMyArray.Allocate(ARRAY_SIZE);
80     this->SetStorage(stealMyArray, stolenArrayValue);
81 
82     VTKM_TEST_ASSERT(stealMyArray.GetNumberOfValues() == ARRAY_SIZE,
83                      "Array not properly allocated.");
84     // This call steals the array and prevents deallocation.
85     VTKM_TEST_ASSERT(stealMyArray.WillDeallocate() == true,
86                      "Array to be stolen needs to be owned by VTK-m");
87     stolenArray = stealMyArray.StealArray();
88     VTKM_TEST_ASSERT(stealMyArray.WillDeallocate() == false,
89                      "Stolen array should not be owned by VTK-m");
90 
91     return stolenArray;
92   }
StealArray2__anon9c0f15680111::TemplatedTests93   void StealArray2(ValueType* stolenArray)
94   {
95     ValueType stolenArrayValue = ValueType(STOLEN_ARRAY_VALUE());
96 
97     for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
98     {
99       VTKM_TEST_ASSERT(test_equal(stolenArray[index], stolenArrayValue),
100                        "Stolen array did not retain values.");
101     }
102     typename StorageType::AllocatorType allocator;
103     allocator.deallocate(stolenArray);
104   }
105 
BasicAllocation__anon9c0f15680111::TemplatedTests106   void BasicAllocation()
107   {
108     StorageType arrayStorage;
109     VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == 0, "New array storage not zero sized.");
110 
111     arrayStorage.Allocate(ARRAY_SIZE);
112     VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE,
113                      "Array not properly allocated.");
114 
115     const ValueType BASIC_ALLOC_VALUE = ValueType(48);
116     this->SetStorage(arrayStorage, BASIC_ALLOC_VALUE);
117     VTKM_TEST_ASSERT(this->CheckStorage(arrayStorage, BASIC_ALLOC_VALUE),
118                      "Array not holding value.");
119 
120     arrayStorage.Allocate(ARRAY_SIZE * 2);
121     VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE * 2,
122                      "Array not reallocated correctly.");
123 
124     arrayStorage.Shrink(ARRAY_SIZE);
125     VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE,
126                      "Array Shrnk failed to resize.");
127 
128     arrayStorage.ReleaseResources();
129     VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == 0, "Array not released correctly.");
130 
131     try
132     {
133       arrayStorage.Shrink(ARRAY_SIZE);
134       VTKM_TEST_ASSERT(true == false,
135                        "Array shrink do a larger size was possible. This can't be allowed.");
136     }
137     catch (vtkm::cont::ErrorBadValue&)
138     {
139     }
140   }
141 
UserFreeFunction__anon9c0f15680111::TemplatedTests142   void UserFreeFunction()
143   {
144     ValueType* temp = new ValueType[ARRAY_SIZE];
145     StorageType arrayStorage(
146       temp, ARRAY_SIZE, [](void* ptr) { delete[] static_cast<ValueType*>(ptr); });
147     VTKM_TEST_ASSERT(temp == arrayStorage.GetArray(),
148                      "improper pointer after telling storage to own user allocated memory");
149 
150     const ValueType BASIC_ALLOC_VALUE = ValueType(48);
151     this->SetStorage(arrayStorage, BASIC_ALLOC_VALUE);
152     VTKM_TEST_ASSERT(this->CheckStorage(arrayStorage, BASIC_ALLOC_VALUE),
153                      "Array not holding value.");
154 
155     arrayStorage.Allocate(ARRAY_SIZE * 2);
156     VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE * 2,
157                      "Array not reallocated correctly.");
158   }
159 
operator ()__anon9c0f15680111::TemplatedTests160   void operator()()
161   {
162     ValueType* stolenArray = StealArray1();
163 
164     BasicAllocation();
165     UserFreeFunction();
166 
167     StealArray2(stolenArray);
168   }
169 };
170 
171 struct TestFunctor
172 {
173   template <typename T>
operator ()__anon9c0f15680111::TestFunctor174   void operator()(T) const
175   {
176     TemplatedTests<T> tests;
177     tests();
178   }
179 };
180 
TestStorageBasic()181 void TestStorageBasic()
182 {
183   vtkm::testing::Testing::TryTypes(TestFunctor());
184 }
185 
186 } // Anonymous namespace
187 
UnitTestStorageBasic(int,char * [])188 int UnitTestStorageBasic(int, char* [])
189 {
190   return vtkm::cont::testing::Testing::Run(TestStorageBasic);
191 }
192