2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include "kernels/Concatenation.h"
20 #include "kernels/TestUtils.h"
21 #include "luci_interpreter/TestMemoryManager.h"
23 namespace luci_interpreter
30 using namespace testing;
32 class ConcatenationTest : public ::testing::Test
35 void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
37 std::unique_ptr<IMemoryManager> _memory_manager;
40 TEST_F(ConcatenationTest, Float)
42 std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
43 std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
44 Tensor input1_tensor =
45 makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
46 Tensor input2_tensor =
47 makeInputTensor<DataType::FLOAT32>({2, 3}, input2_data, _memory_manager.get());
48 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
49 ConcatenationParams params{};
51 // Try different 'axis' and expect different results.
54 params.activation = luci::FusedActFunc::NONE;
56 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
58 for (auto t : kernel.getOutputTensors())
60 _memory_manager->allocate_memory(*t);
64 EXPECT_THAT(extractTensorData<float>(output_tensor),
65 FloatArrayNear({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}));
68 params.axis = -2; // Same as '0'.
69 params.activation = luci::FusedActFunc::NONE;
71 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
73 _memory_manager->allocate_memory(output_tensor);
76 EXPECT_THAT(extractTensorData<float>(output_tensor),
77 FloatArrayNear({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}));
81 params.activation = luci::FusedActFunc::NONE;
83 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
85 _memory_manager->allocate_memory(output_tensor);
88 EXPECT_THAT(extractTensorData<float>(output_tensor),
89 FloatArrayNear({1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12}));
92 params.axis = -1; // Same as '1'.
93 params.activation = luci::FusedActFunc::NONE;
95 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
97 _memory_manager->allocate_memory(output_tensor);
100 EXPECT_THAT(extractTensorData<float>(output_tensor),
101 FloatArrayNear({1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12}));
105 TEST_F(ConcatenationTest, Input_Number_Check_NEG)
107 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
108 ConcatenationParams params{};
111 params.activation = luci::FusedActFunc::NONE;
113 Concatenation kernel({}, &output_tensor, params);
114 EXPECT_ANY_THROW(kernel.configure());
117 TEST_F(ConcatenationTest, Invalid_Axis_NEG)
119 std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
120 std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
121 Tensor input1_tensor =
122 makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
123 Tensor input2_tensor =
124 makeInputTensor<DataType::FLOAT32>({2, 3}, input2_data, _memory_manager.get());
125 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
126 ConcatenationParams params{};
129 params.activation = luci::FusedActFunc::NONE;
131 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
132 EXPECT_ANY_THROW(kernel.configure());
135 TEST_F(ConcatenationTest, Mismatching_Input_Type_NEG)
137 std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
138 std::vector<uint8_t> input2_data{7, 8, 9, 10, 11, 12};
139 Tensor input1_tensor =
140 makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
141 Tensor input2_tensor = makeInputTensor<DataType::U8>({2, 3}, input2_data, _memory_manager.get());
142 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
143 ConcatenationParams params{};
146 params.activation = luci::FusedActFunc::NONE;
148 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
149 EXPECT_ANY_THROW(kernel.configure());
152 TEST_F(ConcatenationTest, Mismatching_Input_Dimension_Num_NEG)
154 std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
155 std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
156 Tensor input1_tensor =
157 makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
158 Tensor input2_tensor =
159 makeInputTensor<DataType::FLOAT32>({1, 2, 3}, input2_data, _memory_manager.get());
160 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
161 ConcatenationParams params{};
164 params.activation = luci::FusedActFunc::NONE;
166 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
167 EXPECT_ANY_THROW(kernel.configure());
170 TEST_F(ConcatenationTest, Mismatching_Input_Dimension_NEG)
172 std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
173 std::vector<float> input2_data{7, 8, 9, 10, 11, 12, 13, 14, 15};
174 Tensor input1_tensor =
175 makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
176 Tensor input2_tensor =
177 makeInputTensor<DataType::FLOAT32>({3, 3}, input2_data, _memory_manager.get());
178 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
179 ConcatenationParams params{};
182 params.activation = luci::FusedActFunc::NONE;
184 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
185 EXPECT_ANY_THROW(kernel.configure());
188 TEST_F(ConcatenationTest, Int8_Mismatching_Input_Type_NEG)
190 std::vector<uint8_t> input1_data{1, 2, 3, 4};
191 std::vector<int8_t> input2_data{5, 6, 7, 8};
192 Tensor input1_tensor = makeInputTensor<DataType::U8>({2, 2}, input1_data, _memory_manager.get());
193 Tensor input2_tensor = makeInputTensor<DataType::S8>({2, 2}, input2_data, _memory_manager.get());
194 Tensor output_tensor = makeOutputTensor(DataType::S8);
195 ConcatenationParams params{};
198 params.activation = luci::FusedActFunc::NONE;
200 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
201 EXPECT_ANY_THROW(kernel.configure());
204 TEST_F(ConcatenationTest, Int8_Mismatching_Input_Output_Quant_Params_NEG)
206 std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
207 std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
208 int quantized_dimension = 3;
209 std::vector<float> scales{0.1, 0.2, 0.3};
210 std::vector<int32_t> zero_points{1, -1, 1};
212 Tensor input1_tensor = makeInputTensor<DataType::S8>(
213 {1, 1, 2, 3}, scales, zero_points, quantized_dimension, input1_data, _memory_manager.get());
214 Tensor input2_tensor = makeInputTensor<DataType::S8>(
215 {1, 1, 2, 3}, scales, zero_points, quantized_dimension, input2_data, _memory_manager.get());
216 Tensor output_tensor = makeOutputTensor(DataType::S8, scales.at(0), zero_points.at(0));
217 ConcatenationParams params{};
220 params.activation = luci::FusedActFunc::NONE;
222 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
223 EXPECT_ANY_THROW(kernel.configure());
226 TEST_F(ConcatenationTest, Int8_Mismatching_Zero_Point_NEG)
228 std::vector<float> input1_data{1, 2, 3, 4};
229 std::vector<float> input2_data{5, 6, 7, 8};
231 int32_t zero_point_1 = 1;
232 int32_t zero_point_2 = -1;
234 Tensor input1_tensor =
235 makeInputTensor<DataType::S8>({2, 2}, scale, zero_point_1, input1_data, _memory_manager.get());
236 Tensor input2_tensor =
237 makeInputTensor<DataType::S8>({2, 2}, scale, zero_point_2, input2_data, _memory_manager.get());
239 Tensor output_tensor = makeOutputTensor(DataType::S8, scale, zero_point_1);
240 ConcatenationParams params{};
243 params.activation = luci::FusedActFunc::NONE;
245 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
246 EXPECT_ANY_THROW(kernel.configure());
249 // TODO: Remove this test when concat w/ fused_activation is supported
250 TEST_F(ConcatenationTest, With_Fused_Activation_NEG)
252 std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
253 std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
254 Tensor input1_tensor =
255 makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data, _memory_manager.get());
256 Tensor input2_tensor =
257 makeInputTensor<DataType::FLOAT32>({2, 3}, input2_data, _memory_manager.get());
258 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
259 ConcatenationParams params{};
262 params.activation = luci::FusedActFunc::RELU;
264 Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
265 EXPECT_ANY_THROW(kernel.configure());
269 } // namespace kernels
270 } // namespace luci_interpreter