blob: bfe115b3edc4b12cdde61b3fca25dcc056a63083 [file] [log] [blame]
Georgios Pinitas3f26ef42021-02-23 10:01:33 +00001/*
2 * Copyright (c) 2021 Arm Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
Georgios Pinitasc3c352e2021-03-18 10:59:40 +000024#ifndef ARM_COMPUTE_TEST_UNIT_TENSOR_FIXTURE
25#define ARM_COMPUTE_TEST_UNIT_TENSOR_FIXTURE
Georgios Pinitas3f26ef42021-02-23 10:01:33 +000026
27#include "arm_compute/Acl.hpp"
28#include "tests/framework/Asserts.h"
29#include "tests/framework/Fixture.h"
30#include "tests/framework/Macros.h"
31#include "tests/validation/Validation.h"
32
33namespace arm_compute
34{
35namespace test
36{
37namespace validation
38{
39/** Test case for AclCreateTensor
40 *
41 * Validate that AclCreateTensor behaves as expected with invalid context
42 *
43 * Test Steps:
44 * - Call AclCreateTensor with an invalid context
45 * - Confirm that AclInvalidArgument is reported
46 * - Confirm that the tensor is still nullptr
47 */
48class CreateTensorWithInvalidContextFixture : public framework::Fixture
49{
50public:
51 void setup()
52 {
53 AclTensor tensor = nullptr;
54 ARM_COMPUTE_ASSERT(AclCreateTensor(&tensor, nullptr, nullptr, false) == AclStatus::AclInvalidArgument);
55 ARM_COMPUTE_ASSERT(tensor == nullptr);
56 };
57};
58
59/** Test-case for AclCreateTensor
60 *
61 * Validate that AclCreateTensor behaves as expected on invalid descriptor
62 *
63 * Test Steps:
64 * - Call AclCreateTensor with valid context but invalid descriptor
65 * - Confirm that AclInvalidArgument is reported
66 * - Confirm that tensor is still nullptr
67 */
68template <acl::Target Target>
69class CreateTensorWithInvalidDescriptorFixture : public framework::Fixture
70{
71public:
72 void setup()
73 {
74 acl::Context ctx(Target);
75 AclTensor tensor = nullptr;
76 ARM_COMPUTE_ASSERT(AclCreateTensor(&tensor, ctx.get(), nullptr, false) == AclStatus::AclInvalidArgument);
77 ARM_COMPUTE_ASSERT(tensor == nullptr);
78
79 // Check invalid data type
80 AclTensorDescriptor invalid_desc;
81 invalid_desc.ndims = 4;
82 invalid_desc.data_type = static_cast<AclDataType>(-1);
83 ARM_COMPUTE_ASSERT(AclCreateTensor(&tensor, ctx.get(), &invalid_desc, false) == AclStatus::AclInvalidArgument);
84 ARM_COMPUTE_ASSERT(tensor == nullptr);
85
86 // Check invalid number of dimensions
87 invalid_desc.data_type = AclDataType::AclFloat32;
88 invalid_desc.ndims = 15;
89 ARM_COMPUTE_ASSERT(AclCreateTensor(&tensor, ctx.get(), &invalid_desc, false) == AclStatus::AclInvalidArgument);
90 ARM_COMPUTE_ASSERT(tensor == nullptr);
91 };
92};
93
94/** Test case for AclDestroyTensor
95*
96* Validate that AclDestroyTensor behaves as expected when an invalid tensor is given
97*
98* Test Steps:
99* - Call AclDestroyTensor with null tensor
100* - Confirm that AclInvalidArgument is reported
101* - Call AclDestroyTensor on empty array
102* - Confirm that AclInvalidArgument is reported
103* - Call AclDestroyTensor on an ACL object other than AclTensor
104* - Confirm that AclInvalidArgument is reported
105* - Confirm that tensor is still nullptr
106*/
107template <acl::Target Target>
108class DestroyInvalidTensorFixture : public framework::Fixture
109{
110public:
111 void setup()
112 {
113 acl::Context ctx(Target);
114
115 std::array<char, 256> empty_array{};
116 AclTensor tensor = nullptr;
117
118 ARM_COMPUTE_ASSERT(AclDestroyTensor(tensor) == AclStatus::AclInvalidArgument);
119 ARM_COMPUTE_ASSERT(AclDestroyTensor(reinterpret_cast<AclTensor>(ctx.get())) == AclStatus::AclInvalidArgument);
120 ARM_COMPUTE_ASSERT(AclDestroyTensor(reinterpret_cast<AclTensor>(empty_array.data())) == AclStatus::AclInvalidArgument);
121 ARM_COMPUTE_ASSERT(tensor == nullptr);
122 };
123};
124
125/** Test case for AclCreateTensor
126 *
127 * Validate that a tensor can be created successfully
128 *
129 * Test Steps:
130 * - Create a valid context
131 * - Create a valid tensor
132 * - Confirm that AclSuccess is returned
133 */
134template <acl::Target Target>
135class SimpleTensorFixture : public framework::Fixture
136{
137public:
138 void setup()
139 {
140 acl::StatusCode err = acl::StatusCode::Success;
141 acl::Context ctx(Target, &err);
142
143 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
144 acl::Tensor tensor(ctx, acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32), &err);
145 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
146 };
147};
148
149/** Test case for AclTensor
150 *
151 * Validate that multiple tensors can be created successfully
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000152 * Stress the possibility of memory leaks
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000153 *
154 * Test Steps:
155 * - Create a valid context
156 * - Create a lot of tensors
157 * - Confirm that AclSuccess is returned
158 */
159template <acl::Target Target>
160class TensorStressFixture : public framework::Fixture
161{
162public:
163 void setup()
164 {
165 acl::StatusCode err = acl::StatusCode::Success;
166
167 acl::Context ctx(Target, &err);
168 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
169
170 const unsigned int num_tensors = 1024;
171 for(unsigned int i = 0; i < num_tensors; ++i)
172 {
173 acl::Tensor tensor(ctx, acl::TensorDescriptor({ 1024, 1024 }, acl::DataType::Float32), &err);
174 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
175 }
176 };
177};
178
179/** Test case for AclMapTensor
180 *
181 * Validate that map on an invalid object fails
182 *
183 * Test Steps:
184 * - Create a valid context
185 * - Pass and invalid object for mapping
186 * - Confirm that AclInvalidArgument is returned
187 */
188template <acl::Target Target>
189class MapInvalidTensorFixture : public framework::Fixture
190{
191public:
192 void setup()
193 {
194 acl::StatusCode err = acl::StatusCode::Success;
195
196 acl::Context ctx(Target, &err);
197 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
198
199 void *handle = nullptr;
200 ARM_COMPUTE_ASSERT(AclMapTensor(reinterpret_cast<AclTensor>(ctx.get()), &handle) == AclStatus::AclInvalidArgument);
201 };
202};
203
204/** Test case for AclMapTensor
205 *
206 * Validate that map of an unallocated pointer is nullptr
207 *
208 * Test Steps:
209 * - Create a valid context
210 * - Create a valid tensor without allocating
211 * - Map tensor
212 * - Check that mapping is nullptr
213 */
214template <acl::Target Target>
215class MapNotAllocatedTensorFixture : public framework::Fixture
216{
217public:
218 void setup()
219 {
220 acl::StatusCode err = acl::StatusCode::Success;
221
222 acl::Context ctx(Target, &err);
223 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
224
225 acl::Tensor tensor(ctx, acl::TensorDescriptor({ 8, 8 }, acl::DataType::Float32), false /* allocate */, &err);
226 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
227 ARM_COMPUTE_ASSERT(tensor.map() == nullptr);
228 };
229};
230
231/** Test case for AclMapTensor
232 *
233 * Validate that map of a valid tensor return a non-nullptr value
234 *
235 * Test Steps:
236 * - Create a valid context
237 * - Create a valid tensor while allocating
238 * - Map tensor
239 * - Check that mapping is not nullptr
240 */
241template <acl::Target Target>
242class MapAllocatedTensorFixture : public framework::Fixture
243{
244public:
245 void setup()
246 {
247 acl::StatusCode err = acl::StatusCode::Success;
248
249 acl::Context ctx(Target, &err);
250 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
251
252 acl::Tensor tensor(ctx, acl::TensorDescriptor({ 8, 8 }, acl::DataType::Float32), &err);
253 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
254
255 void *handle = tensor.map();
256 ARM_COMPUTE_ASSERT(handle != nullptr);
257 ARM_COMPUTE_ASSERT(tensor.unmap(handle) == acl::StatusCode::Success);
258 };
259};
260
261/** Test case for AclTensorImport
262 *
263 * Validate that an externally memory can be successfully imported
264 *
265 * Test Steps:
266 * - Create a valid context
267 * - Create a valid tensor without allocating
268 * - Allocate external memory
269 * - Import memory to the tensor
270 * - Check that imported pointer matches
271 */
272template <acl::Target Target>
273class ImportMemoryFixture : public framework::Fixture
274{
275public:
276 void setup()
277 {
278 acl::StatusCode err = acl::StatusCode::Success;
279
280 acl::Context ctx(Target, &err);
281 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
282
283 const int32_t size = 8;
284 acl::Tensor tensor(ctx, acl::TensorDescriptor({ size }, acl::DataType::Float32), false /* allocate */, &err);
285 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
286
287 std::vector<float> data(size);
288 err = tensor.import(data.data(), acl::ImportType::Host);
289
290 void *handle = tensor.map();
291 ARM_COMPUTE_ASSERT(handle == data.data());
292 ARM_COMPUTE_ASSERT(tensor.unmap(handle) == acl::StatusCode::Success);
293 }
294};
Sang-Hoon Parkc6fcfb42021-03-31 15:18:16 +0100295/** Test case for get_size() interface of Tensor
296 *
297 *
298 * Test Steps:
299 * - Create a valid context
300 * - Create a valid tensor
301 * - Compare the size value returned with the expected value
302 */
303template <acl::Target Target>
304class TensorSizeFixture : public framework::Fixture
305{
306public:
307 void setup()
308 {
309 acl::StatusCode err = acl::StatusCode::Success;
310 acl::Context ctx(Target, &err);
311
312 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
313 acl::Tensor tensor(ctx, acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32), &err);
314
315 // size should be 6 elements (2x3) times 4 bytes (float32) = 24 bytes
316 constexpr size_t expected_size = 24;
317 ARM_COMPUTE_ASSERT(tensor.get_size() == expected_size);
318 };
319};
320/** Test case for get_size() dealing with invalid arguments
321 *
322 * Test Steps:
323 * - Test nullptr tensor can return a correct error
324 * - Create a valid tensor
325 * - Test C interface with null size argument can return a correct error
326 */
327template <acl::Target Target>
328class InvalidTensorSizeFixture : public framework::Fixture
329{
330public:
331 void setup()
332 {
333 // Null tensor
334 AclTensor null_tensor = nullptr;
335 uint64_t size{ 0 };
336 ARM_COMPUTE_ASSERT(AclGetTensorSize(null_tensor, &size) == AclStatus::AclInvalidArgument);
337
338 // Create valid tensor
339 acl::StatusCode err = acl::StatusCode::Success;
340 acl::Context ctx(Target, &err);
341 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
342 acl::Tensor tensor(ctx, acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32), &err);
343
344 // Null size argument
345 ARM_COMPUTE_ASSERT(AclGetTensorSize(tensor.get(), nullptr) == AclStatus::AclInvalidArgument);
346 };
347};
348
349template <acl::Target Target>
350class DescriptorConversionFixture : public framework::Fixture
351{
352 bool compare_descriptor(const AclTensorDescriptor &desc_a, const AclTensorDescriptor &desc_b)
353 {
354 auto are_descriptors_same = true;
355
356 are_descriptors_same &= desc_a.ndims == desc_b.ndims;
357 are_descriptors_same &= desc_a.data_type == desc_b.data_type;
358 are_descriptors_same &= desc_a.shape != nullptr && desc_b.shape != nullptr;
359
360 for(int32_t d = 0; d < desc_a.ndims; ++d)
361 {
362 are_descriptors_same &= desc_a.shape[d] == desc_b.shape[d];
363 }
364
365 // other attributes should be added here
366
367 return are_descriptors_same;
368 }
369
370public:
371 void setup()
372 {
373 auto err{ acl::StatusCode::Success };
374 auto ctx{ acl::Context(Target, &err) };
375 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
376
377 auto desc{ acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32) };
378 acl::Tensor tensor(ctx, desc, &err);
379
380 auto desc_from_tensor = tensor.get_descriptor();
381
382 ARM_COMPUTE_ASSERT(compare_descriptor(*desc.get(), *desc_from_tensor.get()));
383 ARM_COMPUTE_ASSERT(desc == desc_from_tensor);
384
385 // Test c interface with "prepopulated" descriptor
386 // Note: When c interface used, there are possibility of memory leak
387 // if members are not correctly deleted (e.g., shape).
388 // Since that is considered user's responsibility, we don't test here.
389 AclTensorDescriptor prepopulated_descriptor
390 {
391 3, nullptr, AclDataType::AclBFloat16, nullptr, 0
392 };
393
394 ARM_COMPUTE_ASSERT(AclGetTensorDescriptor(tensor.get(), &prepopulated_descriptor) == AclStatus::AclSuccess);
395 ARM_COMPUTE_ASSERT(compare_descriptor(*desc.get(), prepopulated_descriptor));
396 ARM_COMPUTE_ASSERT(desc == acl::TensorDescriptor(prepopulated_descriptor));
397 };
398};
399
400template <acl::Target Target>
401class InvalidDescriptorConversionFixture : public framework::Fixture
402{
403public:
404 void setup()
405 {
406 // Null tensor
407 AclTensor null_tensor = nullptr;
408 AclTensorDescriptor desc{};
409 ARM_COMPUTE_ASSERT(AclGetTensorDescriptor(null_tensor, &desc) == AclStatus::AclInvalidArgument);
410
411 // Create valid tensor
412 acl::StatusCode err = acl::StatusCode::Success;
413 acl::Context ctx(Target, &err);
414 ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success);
415 acl::Tensor tensor(ctx, acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32), &err);
416
417 // Null size argument
418 ARM_COMPUTE_ASSERT(AclGetTensorDescriptor(tensor.get(), nullptr) == AclStatus::AclInvalidArgument);
419 };
420};
Georgios Pinitas3f26ef42021-02-23 10:01:33 +0000421} // namespace validation
422} // namespace test
423} // namespace arm_compute
Georgios Pinitasc3c352e2021-03-18 10:59:40 +0000424#endif /* ARM_COMPUTE_TEST_UNIT_TENSOR_FIXTURE */