1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "DriverTestHelpers.hpp"
6 #include "TestTensor.hpp"
7
8 #include "../1.0/HalPolicy.hpp"
9
10 #include <boost/test/unit_test.hpp>
11 #include <boost/test/data/test_case.hpp>
12
13 #include <array>
14 #include <log/log.h>
15
16
17 BOOST_AUTO_TEST_SUITE(ConcatTests)
18
19 using namespace android::hardware;
20 using namespace driverTestHelpers;
21 using namespace armnn_driver;
22
23 using HalPolicy = hal_1_0::HalPolicy;
24
25 namespace
26 {
27
28 #ifndef ARMCOMPUTECL_ENABLED
29 static const std::array<armnn::Compute, 1> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef }};
30 #else
31 static const std::array<armnn::Compute, 2> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef, armnn::Compute::GpuAcc }};
32 #endif
33
34 void
ConcatTestImpl(const std::vector<const TestTensor * > & inputs,int32_t concatAxis,const TestTensor & expectedOutputTensor,armnn::Compute computeDevice,V1_0::ErrorStatus expectedPrepareStatus=V1_0::ErrorStatus::NONE,V1_0::ErrorStatus expectedExecStatus=V1_0::ErrorStatus::NONE)35 ConcatTestImpl(const std::vector<const TestTensor*> & inputs,
36 int32_t concatAxis,
37 const TestTensor & expectedOutputTensor,
38 armnn::Compute computeDevice,
39 V1_0::ErrorStatus expectedPrepareStatus=V1_0::ErrorStatus::NONE,
40 V1_0::ErrorStatus expectedExecStatus=V1_0::ErrorStatus::NONE)
41 {
42 std::unique_ptr<ArmnnDriver> driver = std::make_unique<ArmnnDriver>(DriverOptions(computeDevice));
43 HalPolicy::Model model{};
44
45 hidl_vec<uint32_t> modelInputIds;
46 modelInputIds.resize(inputs.size()+1);
47 for (uint32_t i = 0; i<inputs.size(); ++i)
48 {
49 modelInputIds[i] = i;
50 AddInputOperand<HalPolicy>(model, inputs[i]->GetDimensions());
51 }
52 modelInputIds[inputs.size()] = inputs.size(); // add an id for the axis too
53 AddIntOperand<HalPolicy>(model, concatAxis);
54 AddOutputOperand<HalPolicy>(model, expectedOutputTensor.GetDimensions());
55
56 // make the concat operation
57 model.operations.resize(1);
58 model.operations[0].type = HalPolicy::OperationType::CONCATENATION;
59 model.operations[0].inputs = modelInputIds;
60 model.operations[0].outputs = hidl_vec<uint32_t>{static_cast<uint32_t>(inputs.size()+1)};
61
62 // make the prepared model
63 V1_0::ErrorStatus prepareStatus=V1_0::ErrorStatus::NONE;
64 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModelWithStatus(model,
65 *driver,
66 prepareStatus,
67 expectedPrepareStatus);
68 BOOST_TEST(prepareStatus == expectedPrepareStatus);
69 if (prepareStatus != V1_0::ErrorStatus::NONE)
70 {
71 // prepare failed, we cannot continue
72 return;
73 }
74
75 BOOST_TEST(preparedModel.get() != nullptr);
76 if (preparedModel.get() == nullptr)
77 {
78 // don't spoil other tests if prepare failed
79 return;
80 }
81
82 // construct the request
83 hidl_vec<RequestArgument> inputArguments;
84 hidl_vec<RequestArgument> outputArguments;
85 inputArguments.resize(inputs.size());
86 outputArguments.resize(1);
87
88 // the request's memory pools will follow the same order as
89 // the inputs
90 for (uint32_t i = 0; i<inputs.size(); ++i)
91 {
92 DataLocation inloc = {};
93 inloc.poolIndex = i;
94 inloc.offset = 0;
95 inloc.length = inputs[i]->GetNumElements() * sizeof(float);
96 RequestArgument input = {};
97 input.location = inloc;
98 input.dimensions = inputs[i]->GetDimensions();
99 inputArguments[i] = input;
100 }
101
102 // and an additional memory pool is needed for the output
103 {
104 DataLocation outloc = {};
105 outloc.poolIndex = inputs.size();
106 outloc.offset = 0;
107 outloc.length = expectedOutputTensor.GetNumElements() * sizeof(float);
108 RequestArgument output = {};
109 output.location = outloc;
110 output.dimensions = expectedOutputTensor.GetDimensions();
111 outputArguments[0] = output;
112 }
113
114 // make the request based on the arguments
115 V1_0::Request request = {};
116 request.inputs = inputArguments;
117 request.outputs = outputArguments;
118
119 // set the input data
120 for (uint32_t i = 0; i<inputs.size(); ++i)
121 {
122 AddPoolAndSetData(inputs[i]->GetNumElements(),
123 request,
124 inputs[i]->GetData());
125 }
126
127 // add memory for the output
128 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(expectedOutputTensor.GetNumElements(), request);
129 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
130
131 // run the execution
132 ARMNN_ASSERT(preparedModel.get() != nullptr);
133 auto execStatus = Execute(preparedModel, request, expectedExecStatus);
134 BOOST_TEST(execStatus == expectedExecStatus);
135
136 if (execStatus == V1_0::ErrorStatus::NONE)
137 {
138 // check the result if there was no error
139 const float * expectedOutput = expectedOutputTensor.GetData();
140 for (unsigned int i=0; i<expectedOutputTensor.GetNumElements();++i)
141 {
142 BOOST_TEST(outdata[i] == expectedOutput[i]);
143 }
144 }
145 }
146
147 } // namespace <anonymous>
148
149
BOOST_DATA_TEST_CASE(SimpleConcatAxis0,COMPUTE_DEVICES)150 BOOST_DATA_TEST_CASE(SimpleConcatAxis0, COMPUTE_DEVICES)
151 {
152 int32_t axis = 0;
153 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
154 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
155 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
156
157 TestTensor expected{armnn::TensorShape{3,1,1,1},{0,1,2}};
158
159 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
160 }
161
BOOST_DATA_TEST_CASE(ConcatAxis0_NoInterleave,COMPUTE_DEVICES)162 BOOST_DATA_TEST_CASE(ConcatAxis0_NoInterleave, COMPUTE_DEVICES)
163 {
164 int32_t axis = 0;
165 TestTensor aIn{armnn::TensorShape{2,1,2,1},{0, 1,
166 2, 3}};
167 TestTensor bIn{armnn::TensorShape{3,1,2,1},{4, 5,
168 6, 7,
169 8, 9}};
170 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}};
171
172 TestTensor expected{armnn::TensorShape{6,1,2,1},{0, 1,
173 2, 3,
174 4, 5,
175 6, 7,
176 8, 9,
177 10, 11}};
178
179 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
180 }
181
BOOST_DATA_TEST_CASE(SimpleConcatAxis1,COMPUTE_DEVICES)182 BOOST_DATA_TEST_CASE(SimpleConcatAxis1, COMPUTE_DEVICES)
183 {
184 int32_t axis = 1;
185 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
186 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
187 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
188
189 TestTensor expected{armnn::TensorShape{1,3,1,1},{0,1,2}};
190
191 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
192 }
193
BOOST_DATA_TEST_CASE(ConcatAxis1_NoInterleave,COMPUTE_DEVICES)194 BOOST_DATA_TEST_CASE(ConcatAxis1_NoInterleave, COMPUTE_DEVICES)
195 {
196 int32_t axis = 1;
197 TestTensor aIn{armnn::TensorShape{1,2,2,1},{0, 1,
198 2, 3}};
199 TestTensor bIn{armnn::TensorShape{1,3,2,1},{4, 5,
200 6, 7,
201 8, 9}};
202 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}};
203
204 TestTensor expected{armnn::TensorShape{1,6,2,1},{0, 1,
205 2, 3,
206 4, 5,
207 6, 7,
208 8, 9,
209 10, 11}};
210
211 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
212 }
213
BOOST_DATA_TEST_CASE(SimpleConcatAxis1_DoInterleave,COMPUTE_DEVICES)214 BOOST_DATA_TEST_CASE(SimpleConcatAxis1_DoInterleave, COMPUTE_DEVICES)
215 {
216 int32_t axis = 1;
217 TestTensor aIn{armnn::TensorShape{2,2,1,1},{0, 1,
218 2, 3}};
219 TestTensor bIn{armnn::TensorShape{2,3,1,1},{4, 5, 6,
220 7, 8, 9}};
221 TestTensor cIn{armnn::TensorShape{2,1,1,1},{10,
222 11}};
223
224 TestTensor expected{armnn::TensorShape{2,6,1,1},{0, 1, 4, 5, 6, 10,
225 2, 3, 7, 8, 9, 11}};
226
227 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
228 }
229
BOOST_DATA_TEST_CASE(SimpleConcatAxis2,COMPUTE_DEVICES)230 BOOST_DATA_TEST_CASE(SimpleConcatAxis2, COMPUTE_DEVICES)
231 {
232 int32_t axis = 2;
233 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
234 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
235 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
236
237 TestTensor expected{armnn::TensorShape{1,1,3,1},{0,1,2}};
238
239 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
240 }
241
BOOST_DATA_TEST_CASE(ConcatAxis2_NoInterleave,COMPUTE_DEVICES)242 BOOST_DATA_TEST_CASE(ConcatAxis2_NoInterleave, COMPUTE_DEVICES)
243 {
244 int32_t axis = 2;
245 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
246 2, 3}};
247 TestTensor bIn{armnn::TensorShape{1,1,3,2},{4, 5,
248 6, 7,
249 8, 9}};
250 TestTensor cIn{armnn::TensorShape{1,1,1,2},{10, 11}};
251
252 TestTensor expected{armnn::TensorShape{1,1,6,2},{0, 1,
253 2, 3,
254 4, 5,
255 6, 7,
256 8, 9,
257 10, 11}};
258
259 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
260 }
261
BOOST_DATA_TEST_CASE(SimpleConcatAxis2_DoInterleave,COMPUTE_DEVICES)262 BOOST_DATA_TEST_CASE(SimpleConcatAxis2_DoInterleave, COMPUTE_DEVICES)
263 {
264 int32_t axis = 2;
265 TestTensor aIn{armnn::TensorShape{1,2,2,1},{0, 1,
266 2, 3}};
267 TestTensor bIn{armnn::TensorShape{1,2,3,1},{4, 5, 6,
268 7, 8, 9}};
269 TestTensor cIn{armnn::TensorShape{1,2,1,1},{10,
270 11}};
271
272 TestTensor expected{armnn::TensorShape{1,2,6,1},{0, 1, 4, 5, 6, 10,
273 2, 3, 7, 8, 9, 11}};
274
275 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
276 }
277
BOOST_DATA_TEST_CASE(SimpleConcatAxis3,COMPUTE_DEVICES)278 BOOST_DATA_TEST_CASE(SimpleConcatAxis3, COMPUTE_DEVICES)
279 {
280 int32_t axis = 3;
281 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
282 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
283 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
284
285 TestTensor expected{armnn::TensorShape{1,1,1,3},{0,1,2}};
286
287 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
288 }
289
BOOST_DATA_TEST_CASE(SimpleConcatAxis3_DoInterleave,COMPUTE_DEVICES)290 BOOST_DATA_TEST_CASE(SimpleConcatAxis3_DoInterleave, COMPUTE_DEVICES)
291 {
292 int32_t axis = 3;
293 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
294 2, 3}};
295 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
296 7, 8, 9}};
297 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
298 11}};
299
300 TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10,
301 2, 3, 7, 8, 9, 11}};
302
303 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
304 }
305
BOOST_DATA_TEST_CASE(AxisTooBig,COMPUTE_DEVICES)306 BOOST_DATA_TEST_CASE(AxisTooBig, COMPUTE_DEVICES)
307 {
308 int32_t axis = 4;
309 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
310 TestTensor bIn{armnn::TensorShape{1,1,1,1},{0}};
311
312 // The axis must be within the range of [-rank(values), rank(values))
313 // see: https://www.tensorflow.org/api_docs/python/tf/concat
314 TestTensor uncheckedOutput{armnn::TensorShape{1,1,1,1},{0}};
315 V1_0::ErrorStatus expectedParserStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
316 ConcatTestImpl({&aIn, &bIn}, axis, uncheckedOutput, sample, expectedParserStatus);
317 }
318
BOOST_DATA_TEST_CASE(AxisTooSmall,COMPUTE_DEVICES)319 BOOST_DATA_TEST_CASE(AxisTooSmall, COMPUTE_DEVICES)
320 {
321 int32_t axis = -5;
322 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
323 TestTensor bIn{armnn::TensorShape{1,1,1,1},{0}};
324
325 // The axis must be within the range of [-rank(values), rank(values))
326 // see: https://www.tensorflow.org/api_docs/python/tf/concat
327 TestTensor uncheckedOutput{armnn::TensorShape{1,1,1,1},{0}};
328 V1_0::ErrorStatus expectedParserStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
329 ConcatTestImpl({&aIn, &bIn}, axis, uncheckedOutput, sample, expectedParserStatus);
330 }
331
BOOST_DATA_TEST_CASE(TooFewInputs,COMPUTE_DEVICES)332 BOOST_DATA_TEST_CASE(TooFewInputs, COMPUTE_DEVICES)
333 {
334 int32_t axis = 0;
335 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
336
337 // We need at least two tensors to concatenate
338 V1_0::ErrorStatus expectedParserStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
339 ConcatTestImpl({&aIn}, axis, aIn, sample, expectedParserStatus);
340 }
341
BOOST_DATA_TEST_CASE(MismatchedInputDimensions,COMPUTE_DEVICES)342 BOOST_DATA_TEST_CASE(MismatchedInputDimensions, COMPUTE_DEVICES)
343 {
344 int32_t axis = 3;
345 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
346 2, 3}};
347 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
348 7, 8, 9}};
349 TestTensor mismatched{armnn::TensorShape{1,1,1,1},{10}};
350
351 TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10,
352 2, 3, 7, 8, 9, 11}};
353
354 // The input dimensions must be compatible
355 V1_0::ErrorStatus expectedParserStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
356 ConcatTestImpl({&aIn, &bIn, &mismatched}, axis, expected, sample, expectedParserStatus);
357 }
358
BOOST_DATA_TEST_CASE(MismatchedInputRanks,COMPUTE_DEVICES)359 BOOST_DATA_TEST_CASE(MismatchedInputRanks, COMPUTE_DEVICES)
360 {
361 int32_t axis = 2;
362 TestTensor aIn{armnn::TensorShape{1,1,2},{0,1}};
363 TestTensor bIn{armnn::TensorShape{1,1},{4}};
364 TestTensor expected{armnn::TensorShape{1,1,3},{0,1,4}};
365
366 // The input dimensions must be compatible
367 V1_0::ErrorStatus expectedParserStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
368 ConcatTestImpl({&aIn, &bIn}, axis, expected, sample, expectedParserStatus);
369 }
370
BOOST_DATA_TEST_CASE(MismatchedOutputDimensions,COMPUTE_DEVICES)371 BOOST_DATA_TEST_CASE(MismatchedOutputDimensions, COMPUTE_DEVICES)
372 {
373 int32_t axis = 3;
374 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
375 2, 3}};
376 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
377 7, 8, 9}};
378 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
379 11}};
380
381 TestTensor mismatched{armnn::TensorShape{1,1,6,2},{0, 1, 4, 5, 6, 10,
382 2, 3, 7, 8, 9, 11}};
383
384 // The input and output dimensions must be compatible
385 V1_0::ErrorStatus expectedParserStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
386 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, mismatched, sample, expectedParserStatus);
387 }
388
BOOST_DATA_TEST_CASE(MismatchedOutputRank,COMPUTE_DEVICES)389 BOOST_DATA_TEST_CASE(MismatchedOutputRank, COMPUTE_DEVICES)
390 {
391 int32_t axis = 3;
392 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
393 2, 3}};
394 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
395 7, 8, 9}};
396 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
397 11}};
398
399 TestTensor mismatched{armnn::TensorShape{6,2},{0, 1, 4, 5, 6, 10,
400 2, 3, 7, 8, 9, 11}};
401
402 // The input and output ranks must match
403 V1_0::ErrorStatus expectedParserStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
404 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, mismatched, sample, expectedParserStatus);
405 }
406
BOOST_DATA_TEST_CASE(ValidNegativeAxis,COMPUTE_DEVICES)407 BOOST_DATA_TEST_CASE(ValidNegativeAxis, COMPUTE_DEVICES)
408 {
409 // this is the same as 3
410 // see: https://www.tensorflow.org/api_docs/python/tf/concat
411 int32_t axis = -1;
412 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
413 2, 3}};
414 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
415 7, 8, 9}};
416 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
417 11}};
418
419 TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10,
420 2, 3, 7, 8, 9, 11}};
421
422 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
423 }
424
BOOST_DATA_TEST_CASE(SimpleConcatAxisZero3D,COMPUTE_DEVICES)425 BOOST_DATA_TEST_CASE(SimpleConcatAxisZero3D, COMPUTE_DEVICES)
426 {
427 int32_t axis = 0;
428 TestTensor aIn{armnn::TensorShape{1,1,1},{0}};
429 TestTensor bIn{armnn::TensorShape{1,1,1},{1}};
430 TestTensor cIn{armnn::TensorShape{1,1,1},{2}};
431
432 TestTensor expected{armnn::TensorShape{3,1,1},{0,1,2}};
433
434 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
435 }
436
BOOST_DATA_TEST_CASE(SimpleConcatAxisOne3D,COMPUTE_DEVICES)437 BOOST_DATA_TEST_CASE(SimpleConcatAxisOne3D, COMPUTE_DEVICES)
438 {
439 int32_t axis = 1;
440 TestTensor aIn{armnn::TensorShape{1,1,1},{0}};
441 TestTensor bIn{armnn::TensorShape{1,1,1},{1}};
442 TestTensor cIn{armnn::TensorShape{1,1,1},{2}};
443
444 TestTensor expected{armnn::TensorShape{1,3,1},{0,1,2}};
445
446 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
447 }
448
BOOST_DATA_TEST_CASE(SimpleConcatAxisTwo3D,COMPUTE_DEVICES)449 BOOST_DATA_TEST_CASE(SimpleConcatAxisTwo3D, COMPUTE_DEVICES)
450 {
451 int32_t axis = 2;
452 TestTensor aIn{armnn::TensorShape{1,1,1},{0}};
453 TestTensor bIn{armnn::TensorShape{1,1,1},{1}};
454 TestTensor cIn{armnn::TensorShape{1,1,1},{2}};
455
456 TestTensor expected{armnn::TensorShape{1,1,3},{0,1,2}};
457
458 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
459 }
460
BOOST_DATA_TEST_CASE(SimpleConcatAxisZero2D,COMPUTE_DEVICES)461 BOOST_DATA_TEST_CASE(SimpleConcatAxisZero2D, COMPUTE_DEVICES)
462 {
463 int32_t axis = 0;
464 TestTensor aIn{armnn::TensorShape{1,1},{0}};
465 TestTensor bIn{armnn::TensorShape{1,1},{1}};
466 TestTensor cIn{armnn::TensorShape{1,1},{2}};
467
468 TestTensor expected{armnn::TensorShape{3,1},{0,1,2}};
469
470 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
471 }
472
BOOST_DATA_TEST_CASE(SimpleConcatAxisOne2D,COMPUTE_DEVICES)473 BOOST_DATA_TEST_CASE(SimpleConcatAxisOne2D, COMPUTE_DEVICES)
474 {
475 int32_t axis = 1;
476 TestTensor aIn{armnn::TensorShape{1,1},{0}};
477 TestTensor bIn{armnn::TensorShape{1,1},{1}};
478 TestTensor cIn{armnn::TensorShape{1,1},{2}};
479
480 TestTensor expected{armnn::TensorShape{1,3},{0,1,2}};
481
482 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
483 }
484
BOOST_DATA_TEST_CASE(SimpleConcatAxisZero1D,COMPUTE_DEVICES)485 BOOST_DATA_TEST_CASE(SimpleConcatAxisZero1D, COMPUTE_DEVICES)
486 {
487 int32_t axis = 0;
488 TestTensor aIn{armnn::TensorShape{1},{0}};
489 TestTensor bIn{armnn::TensorShape{1},{1}};
490 TestTensor cIn{armnn::TensorShape{1},{2}};
491
492 TestTensor expected{armnn::TensorShape{3},{0,1,2}};
493
494 ConcatTestImpl({&aIn, &bIn, &cIn}, axis, expected, sample);
495 }
496
497 BOOST_AUTO_TEST_SUITE_END()
498