1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gmock/gmock.h>
18 #include <gtest/gtest-death-test.h>
19 #include <gtest/gtest.h>
20 
21 #include <algorithm>
22 #include <cstddef>
23 #include <cstdint>
24 #include <iterator>
25 #include <memory>
26 #include <optional>
27 #include <set>
28 #include <sstream>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 
33 #include "NeuralNetworks.h"
34 #include "NeuralNetworksOEM.h"
35 #include "NeuralNetworksWrapper.h"
36 
37 using namespace android::nn::wrapper;
38 
39 namespace {
40 
41 static const int32_t kAvailableOperandCodes[] = {ANEURALNETWORKS_FLOAT32,
42                                                  ANEURALNETWORKS_INT32,
43                                                  ANEURALNETWORKS_UINT32,
44                                                  ANEURALNETWORKS_TENSOR_FLOAT32,
45                                                  ANEURALNETWORKS_TENSOR_INT32,
46                                                  ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
47                                                  ANEURALNETWORKS_BOOL,
48                                                  ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
49                                                  ANEURALNETWORKS_TENSOR_FLOAT16,
50                                                  ANEURALNETWORKS_TENSOR_BOOL8,
51                                                  ANEURALNETWORKS_FLOAT16,
52                                                  ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL,
53                                                  ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
54                                                  ANEURALNETWORKS_TENSOR_OEM_BYTE};
55 
getOpType(int32_t opcode,uint32_t dimCount=0,const uint32_t * dim=nullptr)56 ANeuralNetworksOperandType getOpType(int32_t opcode, uint32_t dimCount = 0,
57                                      const uint32_t* dim = nullptr) {
58     ANeuralNetworksOperandType opType = {.type = opcode,
59                                          .dimensionCount = dimCount,
60                                          .dimensions = dim,
61                                          .scale = 0.0,
62                                          .zeroPoint = 0};
63     if (opcode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
64         opcode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED ||
65         opcode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM ||
66         opcode == ANEURALNETWORKS_TENSOR_QUANT16_ASYMM ||
67         opcode == ANEURALNETWORKS_TENSOR_QUANT16_SYMM) {
68         opType.scale = 1. / 256.;
69     }
70     return opType;
71 }
72 
73 struct OperandTypeWithExtraParams {
OperandTypeWithExtraParams__anon37b312a30111::OperandTypeWithExtraParams74     OperandTypeWithExtraParams(const ANeuralNetworksOperandType& operandType)
75         : operandType(operandType), channelQuant(std::nullopt), valueModel(std::nullopt) {}
76 
77     ANeuralNetworksOperandType operandType;
78     std::optional<ANeuralNetworksSymmPerChannelQuantParams> channelQuant;
79     std::optional<const ANeuralNetworksModel*> valueModel;
80 
operator ==__anon37b312a30111::OperandTypeWithExtraParams81     bool operator==(const OperandTypeWithExtraParams& that) const {
82         if (operandType.type != that.operandType.type ||
83             operandType.scale != that.operandType.scale ||
84             operandType.zeroPoint != that.operandType.zeroPoint ||
85             operandType.dimensionCount != that.operandType.dimensionCount) {
86             return false;
87         }
88 
89         if (channelQuant.has_value() != that.channelQuant.has_value() ||
90             (channelQuant.has_value() &&
91              (channelQuant->channelDim != that.channelQuant->channelDim ||
92               channelQuant->scaleCount != that.channelQuant->scaleCount))) {
93             return false;
94         }
95 
96         if (valueModel != that.valueModel) {
97             return false;
98         }
99 
100         if (operandType.dimensions) {
101             if (!that.operandType.dimensions) {
102                 return false;
103             }
104             if (!std::equal(operandType.dimensions,
105                             operandType.dimensions + operandType.dimensionCount,
106                             that.operandType.dimensions)) {
107                 return false;
108             }
109         } else {
110             if (that.operandType.dimensions) {
111                 return false;
112             }
113         }
114 
115         if (channelQuant.has_value()) {
116             if (channelQuant->scales) {
117                 return that.channelQuant->scales &&
118                        std::equal(channelQuant->scales,
119                                   channelQuant->scales + channelQuant->scaleCount,
120                                   that.channelQuant->scales);
121             } else {
122                 return that.channelQuant->scales == nullptr;
123             }
124         }
125         return true;
126     }
127 
operator !=__anon37b312a30111::OperandTypeWithExtraParams128     bool operator!=(const OperandTypeWithExtraParams& that) const { return !(*this == that); }
129 
operator <__anon37b312a30111::OperandTypeWithExtraParams130     bool operator<(const OperandTypeWithExtraParams& that) const {
131         if (operandType.type < that.operandType.type) return true;
132         if (operandType.dimensionCount < that.operandType.dimensionCount) return true;
133         return false;
134     }
135 };  // namespace
136 
137 // Generates valid and invalid mutations of given OperandTypeWithParams
138 // instances.
139 // It is also responsible of freeing the memory allocated when creating
140 // mutations.
141 // Mutations shouldn't outlive the generating TensorRankConstraint instance.
142 class TensorRankConstraint {
143    public:
TensorRankConstraint(const TensorRankConstraint & copyFrom)144     TensorRankConstraint(const TensorRankConstraint& copyFrom) {
145         // ignoring the array of allocated dimension
146         this->mRangeMax = copyFrom.mRangeMax;
147         this->mRangeMin = copyFrom.mRangeMin;
148     }
149 
operator =(const TensorRankConstraint & copyFrom)150     TensorRankConstraint& operator=(const TensorRankConstraint& copyFrom) {
151         // ignoring the array of allocated dimension
152         this->mRangeMax = copyFrom.mRangeMax;
153         this->mRangeMin = copyFrom.mRangeMin;
154         return *this;
155     }
156 
Exactly(uint32_t rank)157     static TensorRankConstraint Exactly(uint32_t rank) {
158         return TensorRankConstraint(std::optional(rank), std::optional(rank));
159     }
160 
AtLeast(uint32_t min)161     static TensorRankConstraint AtLeast(uint32_t min) {
162         return TensorRankConstraint(std::optional(min), std::nullopt);
163     }
164 
UpTo(uint32_t max)165     static TensorRankConstraint UpTo(uint32_t max) {
166         return TensorRankConstraint(std::nullopt, std::optional(max));
167     }
168 
Between(uint32_t min,uint32_t max)169     static TensorRankConstraint Between(uint32_t min, uint32_t max) {
170         if (min == 0) {
171             return UpTo(max);
172         }
173         return TensorRankConstraint(std::optional(min), std::optional(max));
174     }
175 
MutationsWithValidRank(const std::vector<OperandTypeWithExtraParams> & operandsTypeWithParams)176     std::set<std::vector<OperandTypeWithExtraParams>> MutationsWithValidRank(
177             const std::vector<OperandTypeWithExtraParams>& operandsTypeWithParams) {
178         // can't be both nullopt
179         if (!mRangeMin) {
180             return {ModifyForRank(operandsTypeWithParams, 1),
181                     ModifyForRank(operandsTypeWithParams, *mRangeMax)};
182         } else if (!mRangeMax) {
183             return {ModifyForRank(operandsTypeWithParams, *mRangeMin),
184                     ModifyForRank(operandsTypeWithParams, *mRangeMin + 1)};
185         } else if (mRangeMax == mRangeMin) {
186             std::for_each(operandsTypeWithParams.begin(), operandsTypeWithParams.end(),
187                           [this](const OperandTypeWithExtraParams& op) {
188                               assert(op.operandType.dimensionCount == *mRangeMin);
189                           });
190             return {operandsTypeWithParams};
191         } else {
192             return {ModifyForRank(operandsTypeWithParams, *mRangeMin),
193                     ModifyForRank(operandsTypeWithParams, *mRangeMax)};
194         }
195     }
196 
MutationsWithInvalidRank(const std::vector<OperandTypeWithExtraParams> & operandsTypeWithParams)197     std::set<std::vector<OperandTypeWithExtraParams>> MutationsWithInvalidRank(
198             const std::vector<OperandTypeWithExtraParams>& operandsTypeWithParams) {
199         std::set<std::vector<OperandTypeWithExtraParams>> result;
200         if (mRangeMax) {
201             result.insert(ModifyForRank(operandsTypeWithParams, *mRangeMax + 1));
202         }
203         if (mRangeMin.value_or(0) > 1) {
204             result.insert(ModifyForRank(operandsTypeWithParams, *mRangeMin - 1));
205         }
206         return result;
207     }
208 
209    private:
ModifyForRank(const std::vector<OperandTypeWithExtraParams> & operandsTypeWithParams,uint32_t newRank)210     std::vector<OperandTypeWithExtraParams> ModifyForRank(
211             const std::vector<OperandTypeWithExtraParams>& operandsTypeWithParams,
212             uint32_t newRank) {
213         std::vector<OperandTypeWithExtraParams> result;
214         std::transform(operandsTypeWithParams.cbegin(), operandsTypeWithParams.cend(),
215                        std::back_inserter(result),
216                        [this, newRank](const OperandTypeWithExtraParams& operandTypeWithParams) {
217                            return ModifyForRank(operandTypeWithParams, newRank);
218                        });
219         return result;
220     }
221 
ModifyForRank(const OperandTypeWithExtraParams & operandTypeWithParams,uint32_t newRank)222     OperandTypeWithExtraParams ModifyForRank(
223             const OperandTypeWithExtraParams& operandTypeWithParams, uint32_t newRank) {
224         if (operandTypeWithParams.operandType.dimensionCount == newRank) {
225             return operandTypeWithParams;
226         }
227 
228         uint32_t* resultDimensions = nullptr;
229         if (newRank != 0) {
230             std::unique_ptr<uint32_t[]> dimensions = std::make_unique<uint32_t[]>(newRank);
231             resultDimensions = dimensions.get();
232             mAllocatedDimensions.insert(std::move(dimensions));
233             std::fill(resultDimensions, resultDimensions + newRank, 1);
234             const auto originDims = operandTypeWithParams.operandType.dimensions;
235             if (originDims != nullptr) {
236                 const int dimsToCopy =
237                         std::min(operandTypeWithParams.operandType.dimensionCount, newRank);
238                 std::copy(originDims, originDims + dimsToCopy, resultDimensions);
239             }
240         }
241 
242         OperandTypeWithExtraParams result = operandTypeWithParams;
243         result.operandType = {
244                 .type = operandTypeWithParams.operandType.type,
245                 .dimensionCount = newRank,
246                 .dimensions = resultDimensions,
247                 .scale = operandTypeWithParams.operandType.scale,
248                 .zeroPoint = operandTypeWithParams.operandType.zeroPoint,
249         };
250 
251         return result;
252     }
253 
TensorRankConstraint(const std::optional<uint32_t> & min,const std::optional<uint32_t> & max)254     TensorRankConstraint(const std::optional<uint32_t>& min, const std::optional<uint32_t>& max)
255         : mRangeMin(min), mRangeMax(max) {
256         if (mRangeMax.has_value()) {
257             assert(*mRangeMax >= mRangeMin.value_or(0));
258         }
259 
260         assert(mRangeMax.has_value() || mRangeMin.has_value());
261     }
262 
263     std::optional<uint32_t> mRangeMin;
264     std::optional<uint32_t> mRangeMax;
265     std::set<std::unique_ptr<uint32_t[]>> mAllocatedDimensions;
266 };
267 
268 // Mutates a set of inputs applying the same rank constraint.
269 class TensorRankMutator {
270    public:
TensorRankMutator(const TensorRankConstraint & constraint,const std::set<uint32_t> & applyToIndexes={0})271     TensorRankMutator(const TensorRankConstraint& constraint,
272                       const std::set<uint32_t>& applyToIndexes = {0})
273         : mApplyToIndexes(applyToIndexes.begin(), applyToIndexes.end()), mConstraint(constraint) {}
274 
ValidInputsMutations(const std::vector<OperandTypeWithExtraParams> & validInputs)275     std::set<std::vector<OperandTypeWithExtraParams>> ValidInputsMutations(
276             const std::vector<OperandTypeWithExtraParams>& validInputs) {
277         return InputsMutations(
278                 validInputs, [this](const std::vector<OperandTypeWithExtraParams>& inputsToMutate) {
279                     return mConstraint.MutationsWithValidRank(inputsToMutate);
280                 });
281     }
282 
InvalidInputsMutations(const std::vector<OperandTypeWithExtraParams> & validInputs)283     std::set<std::vector<OperandTypeWithExtraParams>> InvalidInputsMutations(
284             const std::vector<OperandTypeWithExtraParams>& validInputs) {
285         return InputsMutations(
286                 validInputs, [this](const std::vector<OperandTypeWithExtraParams>& inputsToMutate) {
287                     return mConstraint.MutationsWithInvalidRank(inputsToMutate);
288                 });
289     }
290 
291    private:
InputsMutations(const std::vector<OperandTypeWithExtraParams> & validInputs,std::function<std::set<std::vector<OperandTypeWithExtraParams>> (const std::vector<OperandTypeWithExtraParams> &)> operandMutator)292     std::set<std::vector<OperandTypeWithExtraParams>> InputsMutations(
293             const std::vector<OperandTypeWithExtraParams>& validInputs,
294             std::function<std::set<std::vector<OperandTypeWithExtraParams>>(
295                     const std::vector<OperandTypeWithExtraParams>&)>
296                     operandMutator) {
297         std::for_each(mApplyToIndexes.begin(), mApplyToIndexes.end(),
298                       [&validInputs](uint32_t index) { assert(index < validInputs.size()); });
299 
300         std::vector<OperandTypeWithExtraParams> toMutate;
301         std::transform(mApplyToIndexes.begin(), mApplyToIndexes.end(), std::back_inserter(toMutate),
302                        [&validInputs](int input_index) { return validInputs[input_index]; });
303 
304         // Get a series of mutation for the operands in toMutate
305         std::set<std::vector<OperandTypeWithExtraParams>> mutatedOps = operandMutator(toMutate);
306 
307         // Generate a set of mutation by replacing the mutated ops in validInputs
308         // with all the mutations in mutatedOps
309         std::set<std::vector<OperandTypeWithExtraParams>> mutatedValidInputs;
310         std::transform(
311                 mutatedOps.cbegin(), mutatedOps.cend(),
312                 std::inserter(mutatedValidInputs, mutatedValidInputs.begin()),
313                 [this, &validInputs](const std::vector<OperandTypeWithExtraParams>& opsMutation) {
314                     std::vector<OperandTypeWithExtraParams> currInputMutation(validInputs.begin(),
315                                                                               validInputs.end());
316                     for (size_t i = 0; i < mApplyToIndexes.size(); i++) {
317                         currInputMutation[mApplyToIndexes[i]] = opsMutation[i];
318                     }
319 
320                     return currInputMutation;
321                 });
322 
323         return mutatedValidInputs;
324     }
325 
326     std::vector<uint32_t> mApplyToIndexes;
327     TensorRankConstraint mConstraint;
328 };
329 
330 class OperationTestBase {
331    public:
OperationTestBase(ANeuralNetworksOperationType opCode,const std::vector<ANeuralNetworksOperandType> & validInputs,const std::vector<ANeuralNetworksOperandType> & validOutputs,const std::vector<TensorRankMutator> & inputRankMutators={})332     OperationTestBase(ANeuralNetworksOperationType opCode,
333                       const std::vector<ANeuralNetworksOperandType>& validInputs,
334                       const std::vector<ANeuralNetworksOperandType>& validOutputs,
335                       const std::vector<TensorRankMutator>& inputRankMutators = {})
336         : mOpCode(opCode), mValidInputs(), mValidOutputs(), mInputRankMutators(inputRankMutators) {
337         for (ANeuralNetworksOperandType input : validInputs) {
338             mValidInputs.push_back(input);
339         }
340         for (ANeuralNetworksOperandType output : validOutputs) {
341             mValidOutputs.push_back(output);
342         }
343     }
344 
setInputSymmPerChannelQuantParams(int32_t index,const ANeuralNetworksSymmPerChannelQuantParams & channelQuant)345     void setInputSymmPerChannelQuantParams(
346             int32_t index, const ANeuralNetworksSymmPerChannelQuantParams& channelQuant) {
347         mValidInputs[index].channelQuant = channelQuant;
348     }
349 
setOutputSymmPerChannelQuantParams(int32_t index,const ANeuralNetworksSymmPerChannelQuantParams & channelQuant)350     void setOutputSymmPerChannelQuantParams(
351             int32_t index, const ANeuralNetworksSymmPerChannelQuantParams& channelQuant) {
352         mValidOutputs[index].channelQuant = channelQuant;
353     }
354 
setInputOperandValueFromModel(int32_t index,const ANeuralNetworksModel * valueModel)355     void setInputOperandValueFromModel(int32_t index, const ANeuralNetworksModel* valueModel) {
356         mValidInputs[index].valueModel = valueModel;
357     }
358 
359     // Add each operand separately and add the operation using these operands.
360     // This function does not cover the cases that an operand is used mutiple times.
addOperation(const std::vector<OperandTypeWithExtraParams> & inputs,const std::vector<OperandTypeWithExtraParams> & outputs)361     int32_t addOperation(const std::vector<OperandTypeWithExtraParams>& inputs,
362                          const std::vector<OperandTypeWithExtraParams>& outputs) {
363         ANeuralNetworksModel* model = nullptr;
364         ANeuralNetworksModel_create(&model);
365 
366         uint32_t opIdx = 0;
367         std::vector<uint32_t> inputIds;
368         std::vector<uint32_t> outputIds;
369         for (uint32_t i = 0; i < inputs.size(); i++) {
370             ANeuralNetworksModel_addOperand(model, &inputs[i].operandType);
371             if (inputs[i].channelQuant) {
372                 ANeuralNetworksModel_setOperandSymmPerChannelQuantParams(
373                         model, opIdx, &inputs[i].channelQuant.value());
374             }
375             if (inputs[i].valueModel) {
376                 ANeuralNetworksModel_setOperandValueFromModel(model, opIdx,
377                                                               inputs[i].valueModel.value());
378             }
379             inputIds.push_back(opIdx++);
380         }
381         for (uint32_t i = 0; i < outputs.size(); i++) {
382             ANeuralNetworksModel_addOperand(model, &outputs[i].operandType);
383             if (outputs[i].channelQuant) {
384                 ANeuralNetworksModel_setOperandSymmPerChannelQuantParams(
385                         model, opIdx, &outputs[i].channelQuant.value());
386             }
387             outputIds.push_back(opIdx++);
388         }
389 
390         int32_t result = ANeuralNetworksModel_addOperation(
391                 model, mOpCode, static_cast<uint32_t>(inputIds.size()), inputIds.data(),
392                 static_cast<uint32_t>(outputIds.size()), outputIds.data());
393         ANeuralNetworksModel_free(model);
394         return result;
395     }
396 
testOpsValidations()397     void testOpsValidations() {
398         EXPECT_TRUE(testSuccess());
399         EXPECT_TRUE(testMutatingInputOperandCode());
400         EXPECT_TRUE(testMutatingInputOperandCounts());
401         EXPECT_TRUE(testMutatingOutputOperandCode());
402         EXPECT_TRUE(testMutatingOutputOperandCounts());
403         EXPECT_TRUE(testMutatingInputRanks());
404     }
405 
testFailure(int32_t expectedResult)406     void testFailure(int32_t expectedResult) {
407         int32_t result = addOperation(mValidInputs, mValidOutputs);
408         EXPECT_TRUE(expectedResult == result);
409     }
410 
testSuccess()411     bool testSuccess() {
412         int32_t result = addOperation(mValidInputs, mValidOutputs);
413         return ANEURALNETWORKS_NO_ERROR == result;
414     }
415 
testMutatingInputOperandCode()416     bool testMutatingInputOperandCode() {
417         for (uint32_t i = 0; i < mValidInputs.size(); i++) {
418             // LSH_PROJECTION's second argument is allowed to have any type.
419             // This is the only operation that currently has a type that can be
420             // anything independent from any other type. Changing the operand
421             // type to any other type will result in a valid model for
422             // LSH_PROJECTION. If this is the case, skip the test.
423             if (mOpCode == ANEURALNETWORKS_LSH_PROJECTION && i == 1) {
424                 continue;
425             }
426             // RANK can have input of any type.
427             if (mOpCode == ANEURALNETWORKS_RANK) {
428                 continue;
429             }
430             OperandTypeWithExtraParams newType = mValidInputs[i];
431             int32_t originalOperandCode = mValidInputs[i].operandType.type;
432             std::set<int32_t> operandTypesToSkip;
433             // Transposed conv can have either fully quantized or per-channel
434             // quantized filter for the quantized version of the op.
435             if ((mOpCode == ANEURALNETWORKS_TRANSPOSE_CONV_2D ||
436                  mOpCode == ANEURALNETWORKS_DEPTHWISE_CONV_2D) &&
437                 i == 1) {
438                 if (originalOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
439                     originalOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED ||
440                     originalOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
441                     operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
442                     operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
443                     operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
444                 }
445             }
446             // CAST accepts any of supported types for any of output types
447             if (mOpCode == ANEURALNETWORKS_CAST && i == 0) {
448                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT16);
449                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT32);
450                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_INT32);
451                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
452                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
453             }
454             // RANDOM_MULTINOMIAL's first input can be either of float16 or
455             // float32 type while everything else has the same types.
456             if (mOpCode == ANEURALNETWORKS_RANDOM_MULTINOMIAL && i == 0) {
457                 if (originalOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
458                     operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT32);
459                 } else if (originalOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32) {
460                     operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_FLOAT16);
461                 }
462             }
463             // DEQUANTIZE supports any of the inputs types below for any of the
464             // output types.
465             if (mOpCode == ANEURALNETWORKS_DEQUANTIZE && i == 0) {
466                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
467                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
468                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_SYMM);
469                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
470             }
471             // AXIS_ALIGNED_BBOX_TRANSFORM's second input cab be either QUANT8_ASYMM or
472             // QUANT8_ASYMM_SIGNED
473             if (mOpCode == ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM && i == 1) {
474                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
475                 operandTypesToSkip.insert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
476             }
477 
478             for (int32_t newOperandCode : kAvailableOperandCodes) {
479                 if (newOperandCode == originalOperandCode ||
480                     operandTypesToSkip.find(newOperandCode) != operandTypesToSkip.end()) {
481                     continue;
482                 }
483                 // Switch input 7 from bool to int for 10-input CONV_2d
484                 // switch between valid "implicit padding with layout param"
485                 // and valid "explicit padding without layout param"
486                 if (mOpCode == ANEURALNETWORKS_CONV_2D && i == 7 && mValidInputs.size() == 10) {
487                     if ((newOperandCode == ANEURALNETWORKS_INT32 &&
488                          originalOperandCode == ANEURALNETWORKS_BOOL) ||
489                         (newOperandCode == ANEURALNETWORKS_BOOL &&
490                          originalOperandCode == ANEURALNETWORKS_INT32)) {
491                         continue;
492                     }
493                 }
494                 // QUANTIZE supports both types below and its output type does
495                 // not depend on the input type.
496                 if (mOpCode == ANEURALNETWORKS_QUANTIZE && i == 0 &&
497                     (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
498                      newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32)) {
499                     continue;
500                 }
501 
502                 // ARGMIN/MAX supports four input types and has a fixed output type.
503                 if ((mOpCode == ANEURALNETWORKS_ARGMIN || mOpCode == ANEURALNETWORKS_ARGMAX) &&
504                     i == 0 &&
505                     (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
506                      newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ||
507                      newOperandCode == ANEURALNETWORKS_TENSOR_INT32 ||
508                      newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
509                      newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED)) {
510                     continue;
511                 }
512 
513                 // Switch input 8 from bool to int for 11-input DEPTHWISE_CONV_2D
514                 // switch between valid "implicit padding with layout param"
515                 // and valid "explicit padding without layout param"
516                 if (mOpCode == ANEURALNETWORKS_DEPTHWISE_CONV_2D && i == 8 &&
517                     mValidInputs.size() == 11) {
518                     if ((newOperandCode == ANEURALNETWORKS_INT32 &&
519                          originalOperandCode == ANEURALNETWORKS_BOOL) ||
520                         (newOperandCode == ANEURALNETWORKS_BOOL &&
521                          originalOperandCode == ANEURALNETWORKS_INT32)) {
522                         continue;
523                     }
524                 }
525 
526                 newType.operandType.type = newOperandCode;
527                 std::vector<OperandTypeWithExtraParams> inputs = mValidInputs;
528                 inputs[i] = newType;
529                 int32_t result = addOperation(inputs, mValidOutputs);
530                 if (ANEURALNETWORKS_NO_ERROR == result) {
531                     return false;
532                 }
533             }
534         }
535         return true;
536     }
537 
testMutatingOutputOperandCode()538     bool testMutatingOutputOperandCode() {
539         for (uint32_t i = 0; i < mValidOutputs.size(); i++) {
540             // LSH_PROJECTION's second argument is allowed to have any type.
541             // This is the only operation that currently has a type that can be
542             // anything independent from any other type. Changing the operand
543             // type to any other type will result in a valid model for
544             // LSH_PROJECTION. If this is the case, skip the test.
545             if (mOpCode == ANEURALNETWORKS_LSH_PROJECTION && i == 1) {
546                 continue;
547             }
548             OperandTypeWithExtraParams newType = mValidOutputs[i].operandType;
549             int32_t originalOperandCode = mValidOutputs[i].operandType.type;
550             for (int32_t newOperandCode : kAvailableOperandCodes) {
551                 if (newOperandCode == originalOperandCode) {
552                     continue;
553                 }
554                 // DEQUANTIZE's output can be either TENSOR_FLOAT16 or TENSOR_FLOAT32.
555                 if (mOpCode == ANEURALNETWORKS_DEQUANTIZE &&
556                     (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
557                      newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32)) {
558                     continue;
559                 }
560 
561                 // QUANTIZE's output can be either TENSOR_QUANT8_ASYMM or
562                 // TENSOR_QUANT8_ASYMM_SIGNED.
563                 if (mOpCode == ANEURALNETWORKS_QUANTIZE && i == 0 &&
564                     (newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
565                      newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED)) {
566                     continue;
567                 }
568 
569                 // CAST accepts any of supported types for any of input types
570                 if (mOpCode == ANEURALNETWORKS_CAST && i == 0 &&
571                     (newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16 ||
572                      newOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ||
573                      newOperandCode == ANEURALNETWORKS_TENSOR_INT32 ||
574                      newOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM)) {
575                     continue;
576                 }
577                 newType.operandType.type = newOperandCode;
578                 std::vector<OperandTypeWithExtraParams> outputs = mValidOutputs;
579                 outputs[i] = newType;
580                 int32_t result = addOperation(mValidInputs, outputs);
581                 if (ANEURALNETWORKS_NO_ERROR == result) {
582                     return false;
583                 }
584             }
585         }
586         return true;
587     }
588 
testMutatingInputOperandCounts()589     bool testMutatingInputOperandCounts() {
590         uint32_t numToAdd = 5;
591         // LSTM since API 29 supports 23 and 27 outputs.
592         if (mOpCode == ANEURALNETWORKS_LSTM) {
593             numToAdd = 3;
594         }
595         std::vector<OperandTypeWithExtraParams> inputs = mValidInputs;
596         for (uint32_t i = 0; i < numToAdd; i++) {
597             inputs.push_back(inputs[0]);
598             if (ANEURALNETWORKS_NO_ERROR == addOperation(inputs, mValidOutputs)) {
599                 return false;
600             }
601         }
602         return true;
603     }
604 
testMutatingOutputOperandCounts()605     bool testMutatingOutputOperandCounts() {
606         // SPLIT's number of outputs depends on a value of one of its inputs and
607         // are not checked during validation.
608         if (mOpCode == ANEURALNETWORKS_SPLIT) {
609             return true;
610         }
611         std::vector<OperandTypeWithExtraParams> outputs = mValidOutputs;
612         for (int i = 0; i < 6; i++) {
613             outputs.push_back(outputs[0]);
614             if (ANEURALNETWORKS_NO_ERROR == addOperation(mValidInputs, outputs)) {
615                 if (mOpCode == ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN && i < 1) {
616                     continue;
617                 }
618                 if (mOpCode == ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM && i < 3) {
619                     continue;
620                 }
621                 if (mOpCode == ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN && i < 3) {
622                     continue;
623                 }
624                 if (mOpCode == ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM && i < 5) {
625                     continue;
626                 }
627                 return false;
628             }
629         }
630         return true;
631     }
632 
testMutatingInputRanks()633     bool testMutatingInputRanks() {
634         for (auto& rankMutator : mInputRankMutators) {
635             for (const auto& validMutation : rankMutator.ValidInputsMutations(mValidInputs)) {
636                 int32_t result = addOperation(validMutation, mValidOutputs);
637                 if (ANEURALNETWORKS_NO_ERROR != result) {
638                     return false;
639                 }
640             }
641 
642             for (const auto& invalidMutation : rankMutator.InvalidInputsMutations(mValidInputs)) {
643                 int32_t result = addOperation(invalidMutation, mValidOutputs);
644                 if (ANEURALNETWORKS_NO_ERROR == result) {
645                     return false;
646                 }
647             }
648         }
649 
650         return true;
651     }
652 
653    private:
654     ANeuralNetworksOperationType mOpCode;
655     // The dimensions in the ANeuralNetworksOperandType must outlive the test object.
656     std::vector<OperandTypeWithExtraParams> mValidInputs;
657     std::vector<OperandTypeWithExtraParams> mValidOutputs;
658 
659     std::vector<TensorRankMutator> mInputRankMutators;
660 };
661 
operator <<(std::ostream & os,const OperandTypeWithExtraParams & operand)662 std::ostream& operator<<(std::ostream& os, const OperandTypeWithExtraParams& operand) {
663     const auto& operandType = operand.operandType;
664     os << "{ operand_type: { type: " << operandType.type << ", "
665        << "dimensionCount: " << operandType.dimensionCount << ", dimensions: [";
666     std::for_each(operandType.dimensions, operandType.dimensions + operandType.dimensionCount,
667                   [&os](uint32_t dimension) { os << dimension << ", "; });
668     os << "], scale: " << operandType.scale << ", zeroPoint: " << operandType.zeroPoint << " }";
669 
670     const auto& channelQuant = operand.channelQuant;
671     if (channelQuant.has_value()) {
672         os << ", channelQuant { channelDim: " << channelQuant->channelDim
673            << ", scaleCount: " << channelQuant->scaleCount << ", scales: [";
674         std::for_each(channelQuant->scales, channelQuant->scales + channelQuant->scaleCount,
675                       [&os](float scale) { os << scale << ", "; });
676         os << "] }";
677     } else {
678         os << ", channelQuant: nullopt";
679     }
680 
681     if (operand.valueModel.has_value()) {
682         os << ", valueModel: " << operand.valueModel.value();
683     } else {
684         os << ", valueModel: nullopt";
685     }
686     os << "}";
687     return os;
688 }
689 
MutationWithDimensions(const OperandTypeWithExtraParams & origin,const std::vector<uint32_t> & expectedDims)690 inline OperandTypeWithExtraParams MutationWithDimensions(
691         const OperandTypeWithExtraParams& origin, const std::vector<uint32_t>& expectedDims) {
692     OperandTypeWithExtraParams expected = origin;
693     expected.operandType.dimensionCount = expectedDims.size();
694     if (expectedDims.size() == 0) {
695         expected.operandType.dimensions = nullptr;
696     } else {
697         expected.operandType.dimensions = expectedDims.data();
698     }
699     return expected;
700 }
DescribeMutationWithDimensions(const OperandTypeWithExtraParams & origin,const std::vector<uint32_t> & expectedDims)701 std::string DescribeMutationWithDimensions(const OperandTypeWithExtraParams& origin,
702                                            const std::vector<uint32_t>& expectedDims) {
703     std::ostringstream osstream;
704     osstream << MutationWithDimensions(origin, expectedDims);
705     return osstream.str();
706 }
707 
MATCHER_P2(IsMutationWithDimensions,origin,expectedDims,DescribeMutationWithDimensions (origin,expectedDims))708 MATCHER_P2(IsMutationWithDimensions, origin, expectedDims,
709            DescribeMutationWithDimensions(origin, expectedDims)) {
710     return arg == MutationWithDimensions(origin, expectedDims);
711 }
712 
TEST(TensorRankConstraint,ExactlyWillReturnSameInputAsValidMutation)713 TEST(TensorRankConstraint, ExactlyWillReturnSameInputAsValidMutation) {
714     uint32_t opDimensions[3] = {2, 2, 2};
715     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
716             .type = ANEURALNETWORKS_TENSOR_INT32,
717             .dimensionCount = 3,
718             .dimensions = opDimensions,
719     }};
720 
721     auto constraint = TensorRankConstraint::Exactly(3);
722     auto validMutationSet = constraint.MutationsWithValidRank({operand});
723     ASSERT_EQ(validMutationSet.size(), 1u);
724     auto validMutations = *validMutationSet.begin();
725     ASSERT_EQ(validMutations.size(), 1u);
726     EXPECT_THAT(validMutations[0],
727                 IsMutationWithDimensions(operand, std::vector<uint32_t>({2, 2, 2})));
728 };
729 
TEST(TensorRankConstraint,ExactlyWillFailIfValidInputHasInvalidSize)730 TEST(TensorRankConstraint, ExactlyWillFailIfValidInputHasInvalidSize) {
731     uint32_t opDimensions[2] = {2, 2};
732     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
733             .type = ANEURALNETWORKS_TENSOR_INT32,
734             .dimensionCount = 2,
735             .dimensions = opDimensions,
736     }};
737     EXPECT_DEATH(TensorRankConstraint::Exactly(3).MutationsWithValidRank({operand}),
738                  ".*assertion.+failed.*");
739 };
740 
TEST(TensorRankConstraint,ExactlyWillReturnTwoInvalidMutationsWithLowerAndHigherRank)741 TEST(TensorRankConstraint, ExactlyWillReturnTwoInvalidMutationsWithLowerAndHigherRank) {
742     uint32_t opDimensions[3] = {2, 2, 2};
743     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
744             .type = ANEURALNETWORKS_TENSOR_INT32,
745             .dimensionCount = 3,
746             .dimensions = opDimensions,
747     }};
748 
749     auto constraint = TensorRankConstraint::Exactly(3);
750     auto invalidMutations = constraint.MutationsWithInvalidRank({operand});
751     ASSERT_EQ(invalidMutations.size(), 2u);
752     std::for_each(invalidMutations.begin(), invalidMutations.end(),
753                   [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
754                       EXPECT_EQ(mutations.size(), 1u);
755                       if (mutations.size() == 1) {
756                           EXPECT_THAT(
757                                   mutations[0],
758                                   ::testing::AnyOf(
759                                           IsMutationWithDimensions(operand,
760                                                                    std::vector<uint32_t>({2, 2})),
761                                           IsMutationWithDimensions(
762                                                   operand, std::vector<uint32_t>({2, 2, 2, 1}))));
763                       }
764                   });
765 };
766 
TEST(TensorRankConstraint,AtLeastWillReturnTwoValidMutationsAboveThreshold)767 TEST(TensorRankConstraint, AtLeastWillReturnTwoValidMutationsAboveThreshold) {
768     uint32_t opDimensions[3] = {2, 2, 2};
769     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
770             .type = ANEURALNETWORKS_TENSOR_INT32,
771             .dimensionCount = 2,
772             .dimensions = opDimensions,
773     }};
774 
775     auto constraint = TensorRankConstraint::AtLeast(1);
776     auto invalidMutations =
777             constraint.MutationsWithValidRank({(OperandTypeWithExtraParams)operand});
778     ASSERT_EQ(invalidMutations.size(), 2u);
779     std::for_each(
780             invalidMutations.begin(), invalidMutations.end(),
781             [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
782                 EXPECT_EQ(mutations.size(), 1u);
783                 if (mutations.size() == 1) {
784                     EXPECT_THAT(mutations[0],
785                                 ::testing::AnyOf(IsMutationWithDimensions(
786                                                          operand, std::vector<uint32_t>({2})),
787                                                  IsMutationWithDimensions(
788                                                          operand, std::vector<uint32_t>({2, 2}))));
789                 }
790             });
791 }
792 
TEST(TensorRankConstraint,AtLeastWillReturnOneInvalidMutationsBelowThreshold)793 TEST(TensorRankConstraint, AtLeastWillReturnOneInvalidMutationsBelowThreshold) {
794     uint32_t opDimensions[2] = {2, 2};
795     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
796             .type = ANEURALNETWORKS_TENSOR_INT32,
797             .dimensionCount = 2,
798             .dimensions = opDimensions,
799     }};
800 
801     auto constraint = TensorRankConstraint::AtLeast(2);
802     auto invalidMutations =
803             constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
804     ASSERT_EQ(invalidMutations.size(), 1u);
805     auto invalidMutationVector = *invalidMutations.begin();
806     ASSERT_EQ(invalidMutationVector.size(), 1u);
807     ASSERT_THAT(invalidMutationVector[0],
808                 IsMutationWithDimensions(operand, std::vector<uint32_t>({2})));
809 }
810 
TEST(TensorRankConstraint,AtLeastWillReturnNoInvalidMutationsIfThresholdIs1)811 TEST(TensorRankConstraint, AtLeastWillReturnNoInvalidMutationsIfThresholdIs1) {
812     uint32_t opDimensions[1] = {2};
813     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
814             .type = ANEURALNETWORKS_TENSOR_INT32,
815             .dimensionCount = 1,
816             .dimensions = opDimensions,
817     }};
818 
819     auto constraint = TensorRankConstraint::AtLeast(1);
820     auto invalidMutations =
821             constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
822     ASSERT_EQ(invalidMutations.size(), 0u);
823 }
824 
TEST(TensorRankConstraint,UpToWillReturnUpToTwoValidMutationsBelowThreshold)825 TEST(TensorRankConstraint, UpToWillReturnUpToTwoValidMutationsBelowThreshold) {
826     uint32_t opDimensions[3] = {2, 2, 2};
827     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
828             .type = ANEURALNETWORKS_TENSOR_INT32,
829             .dimensionCount = 2,
830             .dimensions = opDimensions,
831     }};
832 
833     auto constraint = TensorRankConstraint::UpTo(3);
834     auto invalidMutations =
835             constraint.MutationsWithValidRank({(OperandTypeWithExtraParams)operand});
836 
837     auto expected = std::vector<uint32_t>({7, 7});
838     ASSERT_EQ(invalidMutations.size(), 2u);
839     std::for_each(invalidMutations.begin(), invalidMutations.end(),
840                   [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
841                       EXPECT_EQ(mutations.size(), 1u);
842                       if (mutations.size() == 1) {
843                           EXPECT_THAT(mutations[0],
844                                       ::testing::AnyOf(
845                                               IsMutationWithDimensions(operand,
846                                                                        std::vector<uint32_t>({2})),
847                                               IsMutationWithDimensions(
848                                                       operand, std::vector<uint32_t>({2, 2, 1}))));
849                       }
850                   });
851 }
852 
TEST(TensorRankConstraint,UpToWillReturnOneInvalidMutationsAboveThreshold)853 TEST(TensorRankConstraint, UpToWillReturnOneInvalidMutationsAboveThreshold) {
854     uint32_t opDimensions[3] = {2, 2, 2};
855     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
856             .type = ANEURALNETWORKS_TENSOR_INT32,
857             .dimensionCount = 3,
858             .dimensions = opDimensions,
859     }};
860 
861     auto constraint = TensorRankConstraint::UpTo(3);
862     auto invalidMutations =
863             constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
864     ASSERT_EQ(invalidMutations.size(), 1u);
865     auto invalidMutationVector = *invalidMutations.begin();
866     ASSERT_EQ(invalidMutationVector.size(), 1u);
867     ASSERT_THAT(invalidMutationVector[0],
868                 IsMutationWithDimensions(operand, std::vector<uint32_t>({2, 2, 2, 1})));
869 }
870 
TEST(TensorRankConstraint,BetweenWillReturnTwoValidMutationsOnRangeBoundaries)871 TEST(TensorRankConstraint, BetweenWillReturnTwoValidMutationsOnRangeBoundaries) {
872     uint32_t opDimensions[3] = {2, 2, 2};
873     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
874             .type = ANEURALNETWORKS_TENSOR_INT32,
875             .dimensionCount = 3,
876             .dimensions = opDimensions,
877     }};
878 
879     auto constraint = TensorRankConstraint::Between(2, 4);
880     auto validMutations = constraint.MutationsWithValidRank({(OperandTypeWithExtraParams)operand});
881     ASSERT_EQ(validMutations.size(), 2u);
882     std::for_each(validMutations.begin(), validMutations.end(),
883                   [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
884                       EXPECT_EQ(mutations.size(), 1u);
885                       if (mutations.size() == 1) {
886                           EXPECT_THAT(
887                                   mutations[0],
888                                   ::testing::AnyOf(
889                                           IsMutationWithDimensions(operand,
890                                                                    std::vector<uint32_t>({2, 2})),
891                                           IsMutationWithDimensions(
892                                                   operand, std::vector<uint32_t>({2, 2, 2, 1}))));
893                       }
894                   });
895 }
896 
TEST(TensorRankConstraint,BetweenWillReturnTwoInvValidMutationsAdjacentToRangeBoundaries)897 TEST(TensorRankConstraint, BetweenWillReturnTwoInvValidMutationsAdjacentToRangeBoundaries) {
898     uint32_t opDimensions[3] = {2, 2, 2};
899     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
900             .type = ANEURALNETWORKS_TENSOR_INT32,
901             .dimensionCount = 3,
902             .dimensions = opDimensions,
903     }};
904 
905     auto constraint = TensorRankConstraint::Between(2, 4);
906     auto validMutations =
907             constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
908     ASSERT_EQ(validMutations.size(), 2u);
909     std::for_each(
910             validMutations.begin(), validMutations.end(),
911             [&operand](const std::vector<OperandTypeWithExtraParams>& mutations) {
912                 EXPECT_EQ(mutations.size(), 1u);
913                 if (mutations.size() == 1) {
914                     EXPECT_THAT(
915                             mutations[0],
916                             ::testing::AnyOf(
917                                     IsMutationWithDimensions(operand, std::vector<uint32_t>({2})),
918                                     IsMutationWithDimensions(
919                                             operand, std::vector<uint32_t>({2, 2, 2, 1, 1}))));
920                 }
921             });
922 }
923 
TEST(TensorRankConstraint,BetweenWillReturnOneInvalidMutationsOnlyIfLowerBoundIs1)924 TEST(TensorRankConstraint, BetweenWillReturnOneInvalidMutationsOnlyIfLowerBoundIs1) {
925     uint32_t opDimensions[3] = {2, 2, 2};
926     OperandTypeWithExtraParams operand{ANeuralNetworksOperandType{
927             .type = ANEURALNETWORKS_TENSOR_INT32,
928             .dimensionCount = 3,
929             .dimensions = opDimensions,
930     }};
931 
932     auto constraint = TensorRankConstraint::Between(1, 4);
933     auto invalidMutations =
934             constraint.MutationsWithInvalidRank({(OperandTypeWithExtraParams)operand});
935     ASSERT_EQ(invalidMutations.size(), 1u);
936     auto invalidMutationVector = *invalidMutations.begin();
937     ASSERT_EQ(invalidMutationVector.size(), 1u);
938     ASSERT_THAT(invalidMutationVector[0],
939                 IsMutationWithDimensions(operand, std::vector<uint32_t>({2, 2, 2, 1, 1})));
940 }
941 
TEST(TensorRankMutator,AppliesConstraintToInputsAtGivenInputsToGenerateValidMutations)942 TEST(TensorRankMutator, AppliesConstraintToInputsAtGivenInputsToGenerateValidMutations) {
943     uint32_t opDimensions0[2] = {0, 0};
944     OperandTypeWithExtraParams operand0{ANeuralNetworksOperandType{
945             .type = ANEURALNETWORKS_TENSOR_INT32,
946             .dimensionCount = 2,
947             .dimensions = opDimensions0,
948     }};
949     uint32_t opDimensions1[1] = {1};
950     OperandTypeWithExtraParams operand1{ANeuralNetworksOperandType{
951             .type = ANEURALNETWORKS_TENSOR_INT32,
952             .dimensionCount = 1,
953             .dimensions = opDimensions1,
954     }};
955     uint32_t opDimensions2[2] = {2, 2};
956     OperandTypeWithExtraParams operand2{ANeuralNetworksOperandType{
957             .type = ANEURALNETWORKS_TENSOR_INT32,
958             .dimensionCount = 2,
959             .dimensions = opDimensions2,
960     }};
961     TensorRankMutator mutator{TensorRankConstraint::AtLeast(2), {0, 2}};
962 
963     const auto mutationSet = mutator.ValidInputsMutations({operand0, operand1, operand2});
964     ASSERT_EQ(mutationSet.size(), 2u);
965     std::for_each(mutationSet.begin(), mutationSet.end(),
966                   [&](const std::vector<OperandTypeWithExtraParams>& mutatedInputs) {
967                       EXPECT_EQ(mutatedInputs.size(), 3u);
968                       if (mutatedInputs.size() == 3) {
969                           EXPECT_EQ(mutatedInputs[0].operandType.dimensionCount,
970                                     mutatedInputs[2].operandType.dimensionCount);
971                           EXPECT_THAT(mutatedInputs[0],
972                                       ::testing::AnyOf(
973                                               IsMutationWithDimensions(
974                                                       operand0, std::vector<uint32_t>({0, 0})),
975                                               IsMutationWithDimensions(
976                                                       operand0, std::vector<uint32_t>({0, 0, 1}))));
977 
978                           EXPECT_EQ(mutatedInputs[1], operand1);
979 
980                           EXPECT_THAT(mutatedInputs[2],
981                                       ::testing::AnyOf(
982                                               IsMutationWithDimensions(
983                                                       operand2, std::vector<uint32_t>({2, 2})),
984                                               IsMutationWithDimensions(
985                                                       operand2, std::vector<uint32_t>({2, 2, 1}))));
986                       }
987                   });
988 }
989 
TEST(TensorRankMutator,AppliesConstraintToInputsAtGivenInputsToGenerateInvalidMutations)990 TEST(TensorRankMutator, AppliesConstraintToInputsAtGivenInputsToGenerateInvalidMutations) {
991     uint32_t opDimensions0[2] = {0, 0};
992     OperandTypeWithExtraParams operand0{ANeuralNetworksOperandType{
993             .type = ANEURALNETWORKS_TENSOR_INT32,
994             .dimensionCount = 2,
995             .dimensions = opDimensions0,
996     }};
997     uint32_t opDimensions1[1] = {1};
998     OperandTypeWithExtraParams operand1{ANeuralNetworksOperandType{
999             .type = ANEURALNETWORKS_TENSOR_INT32,
1000             .dimensionCount = 1,
1001             .dimensions = opDimensions1,
1002     }};
1003     uint32_t opDimensions2[2] = {2, 2};
1004     OperandTypeWithExtraParams operand2{ANeuralNetworksOperandType{
1005             .type = ANEURALNETWORKS_TENSOR_INT32,
1006             .dimensionCount = 2,
1007             .dimensions = opDimensions2,
1008     }};
1009     TensorRankMutator mutator{TensorRankConstraint::AtLeast(2), {0, 2}};
1010 
1011     const auto mutationSet = mutator.InvalidInputsMutations({operand0, operand1, operand2});
1012     ASSERT_EQ(mutationSet.size(), 1u);
1013     std::for_each(
1014             mutationSet.begin(), mutationSet.end(),
1015             [&](const std::vector<OperandTypeWithExtraParams>& mutatedInputs) {
1016                 EXPECT_EQ(mutatedInputs.size(), 3u);
1017                 if (mutatedInputs.size() == 3) {
1018                     EXPECT_THAT(mutatedInputs[0],
1019                                 IsMutationWithDimensions(operand0, std::vector<uint32_t>({0})));
1020 
1021                     EXPECT_EQ(mutatedInputs[1], operand1);
1022 
1023                     EXPECT_THAT(mutatedInputs[2],
1024                                 IsMutationWithDimensions(operand2, std::vector<uint32_t>({2})));
1025                 }
1026             });
1027 }
1028 
argMinMaxTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)1029 void argMinMaxTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
1030     SCOPED_TRACE(inputOperandType);
1031     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1032     ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1033     ANeuralNetworksOperandType axis = {
1034             .type = ANEURALNETWORKS_INT32,
1035             .dimensionCount = 0,
1036             .dimensions = nullptr,
1037     };
1038     uint32_t outputDimensions[3] = {2, 2, 2};
1039     ANeuralNetworksOperandType output = {
1040             .type = ANEURALNETWORKS_TENSOR_INT32,
1041             .dimensionCount = 3,
1042             .dimensions = outputDimensions,
1043     };
1044     OperationTestBase test(operationCode, {input0, axis}, {output});
1045     test.testOpsValidations();
1046 }
1047 
TEST(OperationValidationTest,ARGMIN)1048 TEST(OperationValidationTest, ARGMIN) {
1049     argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_FLOAT16);
1050     argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_FLOAT32);
1051     argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_INT32);
1052     argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1053     argMinMaxTest(ANEURALNETWORKS_ARGMIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1054 }
1055 
TEST(OperationValidationTest,ARGMAX)1056 TEST(OperationValidationTest, ARGMAX) {
1057     argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_FLOAT16);
1058     argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_FLOAT32);
1059     argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_INT32);
1060     argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1061     argMinMaxTest(ANEURALNETWORKS_ARGMAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1062 }
1063 
dequantizeOpTest(int32_t inputOperandType,int32_t outputOperandType)1064 void dequantizeOpTest(int32_t inputOperandType, int32_t outputOperandType) {
1065     SCOPED_TRACE(testing::Message()
1066                  << "inputType: " << inputOperandType << ", outputType: " << outputOperandType);
1067     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1068     ANeuralNetworksOperandType input = getOpType(inputOperandType, 4, inputDimensions);
1069     ANeuralNetworksOperandType output = getOpType(outputOperandType, 4, inputDimensions);
1070     OperationTestBase dequantizeTest(ANEURALNETWORKS_DEQUANTIZE, {input}, {output},
1071                                      {{TensorRankConstraint::UpTo(4)}});
1072     dequantizeTest.testOpsValidations();
1073 }
1074 
TEST(OperationValidationTest,DEQUANTIZE)1075 TEST(OperationValidationTest, DEQUANTIZE) {
1076     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT16);
1077     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT32);
1078     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM, ANEURALNETWORKS_TENSOR_FLOAT16);
1079     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM, ANEURALNETWORKS_TENSOR_FLOAT32);
1080     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL,
1081                      ANEURALNETWORKS_TENSOR_FLOAT16);
1082     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL,
1083                      ANEURALNETWORKS_TENSOR_FLOAT32);
1084     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_TENSOR_FLOAT16);
1085     dequantizeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_TENSOR_FLOAT32);
1086 }
1087 
expandDimsTest(int32_t inputOperandType)1088 void expandDimsTest(int32_t inputOperandType) {
1089     SCOPED_TRACE(inputOperandType);
1090     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1091     ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1092     ANeuralNetworksOperandType axis = {
1093             .type = ANEURALNETWORKS_INT32,
1094             .dimensionCount = 0,
1095             .dimensions = nullptr,
1096     };
1097     uint32_t outputDimensions[5] = {2, 2, 2, 2, 2};
1098     ANeuralNetworksOperandType output = getOpType(inputOperandType, 5, outputDimensions);
1099     OperationTestBase test(ANEURALNETWORKS_EXPAND_DIMS, {input0, axis}, {output});
1100     test.testOpsValidations();
1101 }
1102 
TEST(OperationValidationTest,EXPAND_DIMS)1103 TEST(OperationValidationTest, EXPAND_DIMS) {
1104     expandDimsTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1105     expandDimsTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1106     expandDimsTest(ANEURALNETWORKS_TENSOR_INT32);
1107     expandDimsTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1108     expandDimsTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1109 }
1110 
gatherTest(int32_t inputOperandType)1111 void gatherTest(int32_t inputOperandType) {
1112     SCOPED_TRACE(inputOperandType);
1113     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1114     ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1115     ANeuralNetworksOperandType axis = {
1116             .type = ANEURALNETWORKS_INT32,
1117             .dimensionCount = 0,
1118             .dimensions = nullptr,
1119     };
1120     ANeuralNetworksOperandType input2 = {
1121             .type = ANEURALNETWORKS_TENSOR_INT32,
1122             .dimensionCount = 4,
1123             .dimensions = inputDimensions,
1124     };
1125     uint32_t outputDimensions[7] = {2, 2, 2, 2, 2, 2, 2};
1126     ANeuralNetworksOperandType output = getOpType(inputOperandType, 7, outputDimensions);
1127     OperationTestBase test(ANEURALNETWORKS_GATHER, {input0, axis, input2}, {output});
1128     test.testOpsValidations();
1129 }
1130 
TEST(OperationValidationTest,GATHER)1131 TEST(OperationValidationTest, GATHER) {
1132     gatherTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1133     gatherTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1134     gatherTest(ANEURALNETWORKS_TENSOR_INT32);
1135     gatherTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1136     gatherTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1137 }
1138 
quantizeOpTest(int32_t inputOperandCode,int32_t outputOperandCode)1139 void quantizeOpTest(int32_t inputOperandCode, int32_t outputOperandCode) {
1140     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1141     ANeuralNetworksOperandType input = {
1142             .type = inputOperandCode, .dimensionCount = 4, .dimensions = inputDimensions};
1143     ANeuralNetworksOperandType output = {.type = outputOperandCode,
1144                                          .dimensionCount = 4,
1145                                          .dimensions = inputDimensions,
1146                                          .scale = 1.0f,
1147                                          .zeroPoint = 0};
1148     OperationTestBase test(ANEURALNETWORKS_QUANTIZE, {input}, {output});
1149     test.testOpsValidations();
1150 }
1151 
TEST(OperationValidationTest,QUANTIZE_float16)1152 TEST(OperationValidationTest, QUANTIZE_float16) {
1153     quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1154     quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1155 }
1156 
TEST(OperationValidationTest,QUANTIZE_float32)1157 TEST(OperationValidationTest, QUANTIZE_float32) {
1158     quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1159     quantizeOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1160 }
1161 
TEST(OperationValidationTest,QUANTIZED_16BIT_LSTM)1162 TEST(OperationValidationTest, QUANTIZED_16BIT_LSTM) {
1163     uint32_t oneDimensional[1] = {5};
1164     uint32_t twoDimensional[2] = {5, 5};
1165 
1166     ANeuralNetworksOperandType int32Tensor1D = {
1167             .type = ANEURALNETWORKS_TENSOR_INT32,
1168             .dimensionCount = 1,
1169             .dimensions = oneDimensional,
1170             .scale = 0.0000318,
1171             .zeroPoint = 0,
1172     };
1173     ANeuralNetworksOperandType quant8Tensor2D = {
1174             .type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
1175             .dimensionCount = 2,
1176             .dimensions = twoDimensional,
1177             .scale = 0.00408021,
1178             .zeroPoint = 100,
1179     };
1180     ANeuralNetworksOperandType quant16Tensor2D = {
1181             .type = ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
1182             .dimensionCount = 2,
1183             .dimensions = twoDimensional,
1184             .scale = 1.0 / 2048,
1185             .zeroPoint = 0,
1186     };
1187 
1188     ANeuralNetworksOperandType input = quant8Tensor2D;
1189     ANeuralNetworksOperandType input_to_input_weights = quant8Tensor2D;
1190     ANeuralNetworksOperandType input_to_forget_weights = quant8Tensor2D;
1191     ANeuralNetworksOperandType input_to_cell_weights = quant8Tensor2D;
1192     ANeuralNetworksOperandType input_to_output_weights = quant8Tensor2D;
1193     ANeuralNetworksOperandType recurrent_to_input_weights = quant8Tensor2D;
1194     ANeuralNetworksOperandType recurrent_to_forget_weights = quant8Tensor2D;
1195     ANeuralNetworksOperandType recurrent_to_cell_weights = quant8Tensor2D;
1196     ANeuralNetworksOperandType recurrent_to_output_weights = quant8Tensor2D;
1197     ANeuralNetworksOperandType input_gate_bias = int32Tensor1D;
1198     ANeuralNetworksOperandType forget_gate_bias = int32Tensor1D;
1199     ANeuralNetworksOperandType cell_gate_bias = int32Tensor1D;
1200     ANeuralNetworksOperandType output_gate_bias = int32Tensor1D;
1201     ANeuralNetworksOperandType prev_cell_state = quant16Tensor2D;
1202     ANeuralNetworksOperandType prev_output = quant8Tensor2D;
1203 
1204     ANeuralNetworksOperandType cell_state_out = quant16Tensor2D;
1205     ANeuralNetworksOperandType output = quant8Tensor2D;
1206 
1207     OperationTestBase test(
1208             ANEURALNETWORKS_QUANTIZED_16BIT_LSTM,
1209             {input, input_to_input_weights, input_to_forget_weights, input_to_cell_weights,
1210              input_to_output_weights, recurrent_to_input_weights, recurrent_to_forget_weights,
1211              recurrent_to_cell_weights, recurrent_to_output_weights, input_gate_bias,
1212              forget_gate_bias, cell_gate_bias, output_gate_bias, prev_cell_state, prev_output},
1213             {cell_state_out, output});
1214     test.testOpsValidations();
1215 }
1216 
splitTest(int32_t inputOperandType)1217 void splitTest(int32_t inputOperandType) {
1218     SCOPED_TRACE(inputOperandType);
1219     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1220     ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1221     ANeuralNetworksOperandType axis = {
1222             .type = ANEURALNETWORKS_INT32,
1223             .dimensionCount = 0,
1224             .dimensions = nullptr,
1225     };
1226     ANeuralNetworksOperandType count = {
1227             .type = ANEURALNETWORKS_INT32,
1228             .dimensionCount = 0,
1229             .dimensions = nullptr,
1230     };
1231     uint32_t outputDimensions[2] = {2, 2};
1232     ANeuralNetworksOperandType output0 = getOpType(inputOperandType, 2, outputDimensions);
1233     ANeuralNetworksOperandType output1 = getOpType(inputOperandType, 2, outputDimensions);
1234     OperationTestBase test(ANEURALNETWORKS_SPLIT, {input0, axis, count}, {output0, output1});
1235     test.testOpsValidations();
1236 }
1237 
TEST(OperationValidationTest,SPLIT)1238 TEST(OperationValidationTest, SPLIT) {
1239     splitTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1240     splitTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1241     splitTest(ANEURALNETWORKS_TENSOR_INT32);
1242     splitTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1243     splitTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1244 }
1245 
tileTest(int32_t inputOperandType)1246 void tileTest(int32_t inputOperandType) {
1247     SCOPED_TRACE(inputOperandType);
1248     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1249     ANeuralNetworksOperandType input0 = getOpType(inputOperandType, 4, inputDimensions);
1250     uint32_t multiplesDimensions[1] = {4};
1251     ANeuralNetworksOperandType multiples = {
1252             .type = ANEURALNETWORKS_TENSOR_INT32,
1253             .dimensionCount = 1,
1254             .dimensions = multiplesDimensions,
1255     };
1256     uint32_t outputDimensions[8] = {2, 2, 2, 2, 2, 2, 2, 2};
1257     ANeuralNetworksOperandType output0 = getOpType(inputOperandType, 8, outputDimensions);
1258     OperationTestBase test(ANEURALNETWORKS_TILE, {input0, multiples}, {output0});
1259     test.testOpsValidations();
1260 }
1261 
TEST(OperationValidationTest,TILE)1262 TEST(OperationValidationTest, TILE) {
1263     tileTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1264     tileTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1265     tileTest(ANEURALNETWORKS_TENSOR_INT32);
1266     tileTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1267     tileTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1268 }
1269 
topkV2Test(int32_t inputOperandType)1270 void topkV2Test(int32_t inputOperandType) {
1271     SCOPED_TRACE(inputOperandType);
1272     uint32_t inputDimensions[4] = {4, 5, 6, 7};
1273     ANeuralNetworksOperandType input = getOpType(inputOperandType, 4, inputDimensions);
1274     ANeuralNetworksOperandType k = getOpType(ANEURALNETWORKS_INT32);
1275     uint32_t outputDimensions[4] = {4, 5, 6, 3};
1276     ANeuralNetworksOperandType outputValues = getOpType(inputOperandType, 4, outputDimensions);
1277     ANeuralNetworksOperandType outputIndices =
1278             getOpType(ANEURALNETWORKS_TENSOR_INT32, 4, outputDimensions);
1279     OperationTestBase test(ANEURALNETWORKS_TOPK_V2, {input, k}, {outputValues, outputIndices});
1280     test.testOpsValidations();
1281 }
1282 
TEST(OperationValidationTest,TOPK_V2)1283 TEST(OperationValidationTest, TOPK_V2) {
1284     topkV2Test(ANEURALNETWORKS_TENSOR_FLOAT16);
1285     topkV2Test(ANEURALNETWORKS_TENSOR_FLOAT32);
1286     topkV2Test(ANEURALNETWORKS_TENSOR_INT32);
1287     topkV2Test(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1288     topkV2Test(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1289 }
1290 
simpleMathOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1291 void simpleMathOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1292     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1293     ANeuralNetworksOperandType input1 = getOpType(operandCode, 4, inputDimensions);
1294 
1295     ANeuralNetworksOperandType input2 = input1;
1296     ANeuralNetworksOperandType output = input1;
1297     ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
1298                                              .dimensionCount = 0,
1299                                              .dimensions = nullptr,
1300                                              .scale = 0.0f,
1301                                              .zeroPoint = 0};
1302 
1303     OperationTestBase simpleMathTest(
1304             operationCode, {input1, input2, activation}, {output},
1305             {{TensorRankConstraint::UpTo(4), {0}}, {TensorRankConstraint::UpTo(4), {1}}});
1306     simpleMathTest.testOpsValidations();
1307 }
1308 
TEST(OperationValidationTest,ADD_float16)1309 TEST(OperationValidationTest, ADD_float16) {
1310     simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_FLOAT16);
1311 }
1312 
TEST(OperationValidationTest,ADD_float32)1313 TEST(OperationValidationTest, ADD_float32) {
1314     simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_FLOAT32);
1315 }
1316 
TEST(OperationValidationTest,ADD_quant8)1317 TEST(OperationValidationTest, ADD_quant8) {
1318     simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1319 }
1320 
TEST(OperationValidationTest,ADD_quant8_signed)1321 TEST(OperationValidationTest, ADD_quant8_signed) {
1322     simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1323 }
1324 
TEST(OperationValidationTest,ADD_int32)1325 TEST(OperationValidationTest, ADD_int32) {
1326     simpleMathOpTest(ANEURALNETWORKS_ADD, ANEURALNETWORKS_TENSOR_INT32);
1327 }
1328 
TEST(OperationValidationTest,MUL_float16)1329 TEST(OperationValidationTest, MUL_float16) {
1330     simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_FLOAT16);
1331 }
1332 
TEST(OperationValidationTest,MUL_float32)1333 TEST(OperationValidationTest, MUL_float32) {
1334     simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_FLOAT32);
1335 }
1336 
TEST(OperationValidationTest,MUL_quant8)1337 TEST(OperationValidationTest, MUL_quant8) {
1338     simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1339 }
1340 
TEST(OperationValidationTest,MUL_quant8_signed)1341 TEST(OperationValidationTest, MUL_quant8_signed) {
1342     simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1343 }
1344 
TEST(OperationValidationTest,MUL_int32)1345 TEST(OperationValidationTest, MUL_int32) {
1346     simpleMathOpTest(ANEURALNETWORKS_MUL, ANEURALNETWORKS_TENSOR_INT32);
1347 }
1348 
TEST(OperationValidationTest,SUB_float16)1349 TEST(OperationValidationTest, SUB_float16) {
1350     simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_FLOAT16);
1351 }
1352 
TEST(OperationValidationTest,SUB_float32)1353 TEST(OperationValidationTest, SUB_float32) {
1354     simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_FLOAT32);
1355 }
1356 
TEST(OperationValidationTest,SUB_quant8)1357 TEST(OperationValidationTest, SUB_quant8) {
1358     simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1359 }
1360 
TEST(OperationValidationTest,SUB_quant8_signed)1361 TEST(OperationValidationTest, SUB_quant8_signed) {
1362     simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1363 }
1364 
TEST(OperationValidationTest,SUB_int32)1365 TEST(OperationValidationTest, SUB_int32) {
1366     simpleMathOpTest(ANEURALNETWORKS_SUB, ANEURALNETWORKS_TENSOR_INT32);
1367 }
1368 
TEST(OperationValidationTest,DIV_float16)1369 TEST(OperationValidationTest, DIV_float16) {
1370     simpleMathOpTest(ANEURALNETWORKS_DIV, ANEURALNETWORKS_TENSOR_FLOAT16);
1371 }
1372 
TEST(OperationValidationTest,DIV_float32)1373 TEST(OperationValidationTest, DIV_float32) {
1374     simpleMathOpTest(ANEURALNETWORKS_DIV, ANEURALNETWORKS_TENSOR_FLOAT32);
1375 }
1376 
TEST(OperationValidationTest,DIV_int32)1377 TEST(OperationValidationTest, DIV_int32) {
1378     simpleMathOpTest(ANEURALNETWORKS_DIV, ANEURALNETWORKS_TENSOR_INT32);
1379 }
1380 
TEST(OperationValidationTest,MUL_quant8_bad_output_scale)1381 TEST(OperationValidationTest, MUL_quant8_bad_output_scale) {
1382     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1383     ANeuralNetworksOperandType input1 =
1384             getOpType(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, 4, inputDimensions);
1385     ANeuralNetworksOperandType input2 = input1;
1386     ANeuralNetworksOperandType output = input1;
1387     input1.scale = 1.0f;
1388     input2.scale = 1.0f;
1389     output.scale = 0.5f;
1390     ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
1391                                              .dimensionCount = 0,
1392                                              .dimensions = nullptr,
1393                                              .scale = 0.0f,
1394                                              .zeroPoint = 0};
1395 
1396     OperationTestBase mulTest(ANEURALNETWORKS_MUL, {input1, input2, activation}, {output});
1397     mulTest.testFailure(ANEURALNETWORKS_BAD_DATA);
1398 }
1399 
binaryOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1400 void binaryOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1401     uint32_t inputDimensions[] = {2, 2, 2, 2, 2};
1402     ANeuralNetworksOperandType input1 = getOpType(operandCode, 5, inputDimensions);
1403 
1404     ANeuralNetworksOperandType input2 = input1;
1405     ANeuralNetworksOperandType output = input1;
1406 
1407     OperationTestBase test(operationCode, {input1, input2}, {output});
1408     test.testOpsValidations();
1409 }
1410 
TEST(OperationValidationTest,MAXIMUM_float16)1411 TEST(OperationValidationTest, MAXIMUM_float16) {
1412     binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_FLOAT16);
1413 }
1414 
TEST(OperationValidationTest,MAXIMUM_float32)1415 TEST(OperationValidationTest, MAXIMUM_float32) {
1416     binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_FLOAT32);
1417 }
1418 
TEST(OperationValidationTest,MAXIMUM_int32)1419 TEST(OperationValidationTest, MAXIMUM_int32) {
1420     binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_INT32);
1421 }
1422 
TEST(OperationValidationTest,MAXIMUM_quant8)1423 TEST(OperationValidationTest, MAXIMUM_quant8) {
1424     binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1425 }
1426 
TEST(OperationValidationTest,MAXIMUM_quant8signed)1427 TEST(OperationValidationTest, MAXIMUM_quant8signed) {
1428     binaryOpTest(ANEURALNETWORKS_MAXIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1429 }
1430 
TEST(OperationValidationTest,MINIMUM_float16)1431 TEST(OperationValidationTest, MINIMUM_float16) {
1432     binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_FLOAT16);
1433 }
1434 
TEST(OperationValidationTest,MINIMUM_float32)1435 TEST(OperationValidationTest, MINIMUM_float32) {
1436     binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_FLOAT32);
1437 }
1438 
TEST(OperationValidationTest,MINIMUM_int32)1439 TEST(OperationValidationTest, MINIMUM_int32) {
1440     binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_INT32);
1441 }
1442 
TEST(OperationValidationTest,MINIMUM_quant8)1443 TEST(OperationValidationTest, MINIMUM_quant8) {
1444     binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1445 }
1446 
TEST(OperationValidationTest,MINIMUM_quant8signed)1447 TEST(OperationValidationTest, MINIMUM_quant8signed) {
1448     binaryOpTest(ANEURALNETWORKS_MINIMUM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1449 }
1450 
activationOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1451 void activationOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1452     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1453     ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1454 
1455     ANeuralNetworksOperandType output = input;
1456     std::vector<TensorRankMutator> inputRankMutators;
1457     if (operationCode == ANEURALNETWORKS_FLOOR || operationCode == ANEURALNETWORKS_LOGISTIC ||
1458         operationCode == ANEURALNETWORKS_RELU || operationCode == ANEURALNETWORKS_RELU1 ||
1459         operationCode == ANEURALNETWORKS_RELU6 || operationCode == ANEURALNETWORKS_TANH) {
1460         inputRankMutators.push_back({TensorRankConstraint::UpTo(4)});
1461     }
1462     OperationTestBase test(operationCode, {input}, {output}, inputRankMutators);
1463     test.testOpsValidations();
1464 }
1465 
TEST(OperationValidationTest,ABS_float16)1466 TEST(OperationValidationTest, ABS_float16) {
1467     activationOpTest(ANEURALNETWORKS_ABS, ANEURALNETWORKS_TENSOR_FLOAT16);
1468 }
1469 
TEST(OperationValidationTest,ABS_float32)1470 TEST(OperationValidationTest, ABS_float32) {
1471     activationOpTest(ANEURALNETWORKS_ABS, ANEURALNETWORKS_TENSOR_FLOAT32);
1472 }
1473 
TEST(OperationValidationTest,ABS_int32)1474 TEST(OperationValidationTest, ABS_int32) {
1475     activationOpTest(ANEURALNETWORKS_ABS, ANEURALNETWORKS_TENSOR_INT32);
1476 }
1477 
TEST(OperationValidationTest,EXP_float16)1478 TEST(OperationValidationTest, EXP_float16) {
1479     activationOpTest(ANEURALNETWORKS_EXP, ANEURALNETWORKS_TENSOR_FLOAT16);
1480 }
1481 
TEST(OperationValidationTest,EXP_float32)1482 TEST(OperationValidationTest, EXP_float32) {
1483     activationOpTest(ANEURALNETWORKS_EXP, ANEURALNETWORKS_TENSOR_FLOAT32);
1484 }
1485 
TEST(OperationValidationTest,LOG_float16)1486 TEST(OperationValidationTest, LOG_float16) {
1487     activationOpTest(ANEURALNETWORKS_LOG, ANEURALNETWORKS_TENSOR_FLOAT16);
1488 }
1489 
TEST(OperationValidationTest,LOG_float32)1490 TEST(OperationValidationTest, LOG_float32) {
1491     activationOpTest(ANEURALNETWORKS_LOG, ANEURALNETWORKS_TENSOR_FLOAT32);
1492 }
1493 
TEST(OperationValidationTest,RSQRT_float16)1494 TEST(OperationValidationTest, RSQRT_float16) {
1495     activationOpTest(ANEURALNETWORKS_RSQRT, ANEURALNETWORKS_TENSOR_FLOAT16);
1496 }
1497 
TEST(OperationValidationTest,RSQRT_float32)1498 TEST(OperationValidationTest, RSQRT_float32) {
1499     activationOpTest(ANEURALNETWORKS_RSQRT, ANEURALNETWORKS_TENSOR_FLOAT32);
1500 }
1501 
TEST(OperationValidationTest,SIN_float16)1502 TEST(OperationValidationTest, SIN_float16) {
1503     activationOpTest(ANEURALNETWORKS_SIN, ANEURALNETWORKS_TENSOR_FLOAT16);
1504 }
1505 
TEST(OperationValidationTest,SIN_float32)1506 TEST(OperationValidationTest, SIN_float32) {
1507     activationOpTest(ANEURALNETWORKS_SIN, ANEURALNETWORKS_TENSOR_FLOAT32);
1508 }
1509 
TEST(OperationValidationTest,SQRT_float16)1510 TEST(OperationValidationTest, SQRT_float16) {
1511     activationOpTest(ANEURALNETWORKS_SQRT, ANEURALNETWORKS_TENSOR_FLOAT16);
1512 }
1513 
TEST(OperationValidationTest,SQRT_float32)1514 TEST(OperationValidationTest, SQRT_float32) {
1515     activationOpTest(ANEURALNETWORKS_SQRT, ANEURALNETWORKS_TENSOR_FLOAT32);
1516 }
1517 
TEST(OperationValidationTest,NEG_float16)1518 TEST(OperationValidationTest, NEG_float16) {
1519     activationOpTest(ANEURALNETWORKS_NEG, ANEURALNETWORKS_TENSOR_FLOAT16);
1520 }
1521 
TEST(OperationValidationTest,NEG_float32)1522 TEST(OperationValidationTest, NEG_float32) {
1523     activationOpTest(ANEURALNETWORKS_NEG, ANEURALNETWORKS_TENSOR_FLOAT32);
1524 }
1525 
TEST(OperationValidationTest,NEG_int32)1526 TEST(OperationValidationTest, NEG_int32) {
1527     activationOpTest(ANEURALNETWORKS_NEG, ANEURALNETWORKS_TENSOR_INT32);
1528 }
1529 
TEST(OperationValidationTest,FLOOR_float16)1530 TEST(OperationValidationTest, FLOOR_float16) {
1531     activationOpTest(ANEURALNETWORKS_FLOOR, ANEURALNETWORKS_TENSOR_FLOAT16);
1532 }
1533 
TEST(OperationValidationTest,FLOOR_float32)1534 TEST(OperationValidationTest, FLOOR_float32) {
1535     activationOpTest(ANEURALNETWORKS_FLOOR, ANEURALNETWORKS_TENSOR_FLOAT32);
1536 }
1537 
TEST(OperationValidationTest,LOGICAL_NOT_bool)1538 TEST(OperationValidationTest, LOGICAL_NOT_bool) {
1539     activationOpTest(ANEURALNETWORKS_LOGICAL_NOT, ANEURALNETWORKS_TENSOR_BOOL8);
1540 }
1541 
TEST(OperationValidationTest,TANH_float16)1542 TEST(OperationValidationTest, TANH_float16) {
1543     activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_FLOAT16);
1544 }
1545 
TEST(OperationValidationTest,TANH_float32)1546 TEST(OperationValidationTest, TANH_float32) {
1547     activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_FLOAT32);
1548 }
1549 
TEST(OperationValidationTest,TANH_quant8)1550 TEST(OperationValidationTest, TANH_quant8) {
1551     activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1552 }
1553 
TEST(OperationValidationTest,TANH_quant8_signed)1554 TEST(OperationValidationTest, TANH_quant8_signed) {
1555     activationOpTest(ANEURALNETWORKS_TANH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1556 }
1557 
TEST(OperationValidationTest,RELU_float16)1558 TEST(OperationValidationTest, RELU_float16) {
1559     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT16);
1560 }
1561 
TEST(OperationValidationTest,RELU1_float16)1562 TEST(OperationValidationTest, RELU1_float16) {
1563     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT16);
1564 }
1565 
TEST(OperationValidationTest,RELU6_float16)1566 TEST(OperationValidationTest, RELU6_float16) {
1567     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT16);
1568 }
1569 
TEST(OperationValidationTest,RELU_float32)1570 TEST(OperationValidationTest, RELU_float32) {
1571     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32);
1572 }
1573 
TEST(OperationValidationTest,RELU1_float32)1574 TEST(OperationValidationTest, RELU1_float32) {
1575     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32);
1576 }
1577 
TEST(OperationValidationTest,RELU6_float32)1578 TEST(OperationValidationTest, RELU6_float32) {
1579     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_FLOAT32);
1580 }
1581 
TEST(OperationValidationTest,RELU_quant8)1582 TEST(OperationValidationTest, RELU_quant8) {
1583     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1584 }
1585 
TEST(OperationValidationTest,RELU1_quant8)1586 TEST(OperationValidationTest, RELU1_quant8) {
1587     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1588 }
1589 
TEST(OperationValidationTest,RELU6_quant8)1590 TEST(OperationValidationTest, RELU6_quant8) {
1591     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1592 }
1593 
TEST(OperationValidationTest,RELU_quant8_signed)1594 TEST(OperationValidationTest, RELU_quant8_signed) {
1595     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1596 }
1597 
TEST(OperationValidationTest,RELU1_quant8_signed)1598 TEST(OperationValidationTest, RELU1_quant8_signed) {
1599     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1600 }
1601 
TEST(OperationValidationTest,RELU6_quant8_signed)1602 TEST(OperationValidationTest, RELU6_quant8_signed) {
1603     activationOpTest(ANEURALNETWORKS_RELU, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1604 }
1605 
TEST(OperationValidationTest,LOGISTIC_float16)1606 TEST(OperationValidationTest, LOGISTIC_float16) {
1607     activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_FLOAT16);
1608 }
1609 
TEST(OperationValidationTest,LOGISTIC_float32)1610 TEST(OperationValidationTest, LOGISTIC_float32) {
1611     activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_FLOAT32);
1612 }
1613 
TEST(OperationValidationTest,LOGISTIC_quant8)1614 TEST(OperationValidationTest, LOGISTIC_quant8) {
1615     activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1616 }
1617 
TEST(OperationValidationTest,LOGISTIC_quant8_signed)1618 TEST(OperationValidationTest, LOGISTIC_quant8_signed) {
1619     activationOpTest(ANEURALNETWORKS_LOGISTIC, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1620 }
1621 
TEST(OperationValidationTest,HARD_SWISH_float16)1622 TEST(OperationValidationTest, HARD_SWISH_float16) {
1623     activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_FLOAT16);
1624 }
1625 
TEST(OperationValidationTest,HARD_SWISH_float32)1626 TEST(OperationValidationTest, HARD_SWISH_float32) {
1627     activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_FLOAT32);
1628 }
1629 
TEST(OperationValidationTest,HARD_SWISH_quant8)1630 TEST(OperationValidationTest, HARD_SWISH_quant8) {
1631     activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1632 }
1633 
TEST(OperationValidationTest,HARD_SWISH_quant8_signed)1634 TEST(OperationValidationTest, HARD_SWISH_quant8_signed) {
1635     activationOpTest(ANEURALNETWORKS_HARD_SWISH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1636 }
1637 
eluOpTest(int32_t operandCode)1638 void eluOpTest(int32_t operandCode) {
1639     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1640     ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1641     ANeuralNetworksOperandType alpha = (operandCode == ANEURALNETWORKS_TENSOR_FLOAT32)
1642                                                ? getOpType(ANEURALNETWORKS_FLOAT32)
1643                                                : getOpType(ANEURALNETWORKS_FLOAT16);
1644 
1645     ANeuralNetworksOperandType output = input;
1646     OperationTestBase test(ANEURALNETWORKS_ELU, {input, alpha}, {output});
1647     test.testOpsValidations();
1648 }
1649 
TEST(OperationValidationTest,ELU_float16)1650 TEST(OperationValidationTest, ELU_float16) {
1651     eluOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1652 }
1653 
TEST(OperationValidationTest,ELU_float32)1654 TEST(OperationValidationTest, ELU_float32) {
1655     eluOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1656 }
1657 
reshapeOpTest(int32_t inputOperandCode)1658 void reshapeOpTest(int32_t inputOperandCode) {
1659     SCOPED_TRACE(inputOperandCode);
1660     uint32_t inputDimensions[3] = {2, 3, 4};
1661     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDimensions);
1662     uint32_t shapeDims[1] = {2};
1663     ANeuralNetworksOperandType shape = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, shapeDims);
1664     uint32_t outputDimensions[2] = {4, 6};
1665     ANeuralNetworksOperandType output = getOpType(inputOperandCode, 2, outputDimensions);
1666     OperationTestBase test(ANEURALNETWORKS_RESHAPE, {input, shape}, {output},
1667                            {{TensorRankConstraint::UpTo(4)}});
1668     test.testOpsValidations();
1669 }
1670 
TEST(OperationValidationTest,RESHAPE)1671 TEST(OperationValidationTest, RESHAPE) {
1672     reshapeOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1673     reshapeOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1674     reshapeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1675     reshapeOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1676 }
1677 
logSoftmaxOpTest(int32_t inputOperandCode)1678 void logSoftmaxOpTest(int32_t inputOperandCode) {
1679     uint32_t inputDimensions[3] = {2, 2, 2};
1680     ANeuralNetworksOperandType input = {.type = inputOperandCode,
1681                                         .dimensionCount = 3,
1682                                         .dimensions = inputDimensions,
1683                                         .scale = 0.0f,
1684                                         .zeroPoint = 0};
1685     ANeuralNetworksOperandType beta = {.type = (inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32)
1686                                                        ? ANEURALNETWORKS_FLOAT32
1687                                                        : ANEURALNETWORKS_FLOAT16,
1688                                        .dimensionCount = 0,
1689                                        .dimensions = nullptr,
1690                                        .scale = 0.0f,
1691                                        .zeroPoint = 0};
1692     ANeuralNetworksOperandType axis = {.type = ANEURALNETWORKS_INT32,
1693                                        .dimensionCount = 0,
1694                                        .dimensions = nullptr,
1695                                        .scale = 0.0f,
1696                                        .zeroPoint = 0};
1697 
1698     ANeuralNetworksOperandType output = {.type = inputOperandCode,
1699                                          .dimensionCount = 3,
1700                                          .dimensions = inputDimensions,
1701                                          .scale = 0.0f,
1702                                          .zeroPoint = 0};
1703 
1704     OperationTestBase test(ANEURALNETWORKS_LOG_SOFTMAX, {input, beta, axis}, {output});
1705     test.testOpsValidations();
1706 }
1707 
TEST(OperationValidationTest,LOG_SOFTMAX_float16)1708 TEST(OperationValidationTest, LOG_SOFTMAX_float16) {
1709     logSoftmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1710 }
1711 
TEST(OperationValidationTest,LOG_SOFTMAX_float32)1712 TEST(OperationValidationTest, LOG_SOFTMAX_float32) {
1713     logSoftmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1714 }
1715 
meanOpTest(int32_t inputOperandCode)1716 void meanOpTest(int32_t inputOperandCode) {
1717     uint32_t inputDimensions[3] = {2, 2, 2};
1718     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDimensions);
1719     ANeuralNetworksOperandType dims = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, inputDimensions);
1720     ANeuralNetworksOperandType keepDims = getOpType(ANEURALNETWORKS_INT32);
1721     ANeuralNetworksOperandType output = getOpType(inputOperandCode, 3, inputDimensions);
1722 
1723     OperationTestBase test(ANEURALNETWORKS_MEAN, {input, dims, keepDims}, {output},
1724                            {{TensorRankConstraint::UpTo(4)}});
1725     test.testOpsValidations();
1726 }
1727 
TEST(OperationValidationTest,MEAN_float16)1728 TEST(OperationValidationTest, MEAN_float16) {
1729     meanOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1730 }
1731 
TEST(OperationValidationTest,MEAN_float32)1732 TEST(OperationValidationTest, MEAN_float32) {
1733     meanOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1734 }
1735 
TEST(OperationValidationTest,MEAN_quant8)1736 TEST(OperationValidationTest, MEAN_quant8) {
1737     meanOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1738 }
1739 
TEST(OperationValidationTest,MEAN_quant8_signed)1740 TEST(OperationValidationTest, MEAN_quant8_signed) {
1741     meanOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1742 }
1743 
padOpTest(int32_t inputOperandCode)1744 void padOpTest(int32_t inputOperandCode) {
1745     SCOPED_TRACE(inputOperandCode);
1746     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1747     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
1748     uint32_t padSizeDimensions[1] = {4};
1749     ANeuralNetworksOperandType padSize =
1750             getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, padSizeDimensions);
1751     uint32_t outputDimensions[4] = {4, 3, 4, 3};
1752     ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outputDimensions);
1753     OperationTestBase test(ANEURALNETWORKS_PAD, {input, padSize}, {output},
1754                            {{TensorRankConstraint::UpTo(4)}});
1755     test.testOpsValidations();
1756 }
1757 
TEST(OperationValidationTest,PAD)1758 TEST(OperationValidationTest, PAD) {
1759     padOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1760     padOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1761     padOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1762     padOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1763 }
1764 
padV2OpTest(int32_t inputOperandCode)1765 void padV2OpTest(int32_t inputOperandCode) {
1766     SCOPED_TRACE(inputOperandCode);
1767     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1768     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
1769     uint32_t padSizeDimensions[1] = {4};
1770     ANeuralNetworksOperandType padSize =
1771             getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, padSizeDimensions);
1772     ANeuralNetworksOperandType padValue = getOpType(ANEURALNETWORKS_FLOAT32);
1773     if (inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
1774         padValue = getOpType(ANEURALNETWORKS_FLOAT16);
1775     } else if (inputOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
1776                inputOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
1777         padValue = getOpType(ANEURALNETWORKS_INT32);
1778     }
1779     uint32_t outputDimensions[4] = {4, 3, 4, 3};
1780     ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outputDimensions);
1781     OperationTestBase test(ANEURALNETWORKS_PAD_V2, {input, padSize, padValue}, {output},
1782                            {{TensorRankConstraint::UpTo(4)}});
1783     test.testOpsValidations();
1784 }
1785 
TEST(OperationValidationTest,PAD_V2)1786 TEST(OperationValidationTest, PAD_V2) {
1787     padV2OpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1788     padV2OpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1789     padV2OpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1790     padV2OpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1791 }
1792 
softmaxOpTest(int32_t operandCode)1793 void softmaxOpTest(int32_t operandCode) {
1794     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1795     ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1796 
1797     ANeuralNetworksOperandType output = input;
1798     ANeuralNetworksOperandType beta = getOpType(ANEURALNETWORKS_FLOAT32);
1799     if (operandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
1800         beta = getOpType(ANEURALNETWORKS_FLOAT16);
1801     }
1802 
1803     OperationTestBase softmaxTest(ANEURALNETWORKS_SOFTMAX, {input, beta}, {output},
1804                                   {{TensorRankConstraint::UpTo(4)}});
1805     softmaxTest.testOpsValidations();
1806 
1807     ANeuralNetworksOperandType axis = getOpType(ANEURALNETWORKS_INT32);
1808     OperationTestBase softmaxAxisTest(ANEURALNETWORKS_SOFTMAX, {input, beta, axis}, {output},
1809                                       {{TensorRankConstraint::UpTo(4)}});
1810     softmaxAxisTest.testOpsValidations();
1811 }
1812 
TEST(OperationValidationTest,SOFTMAX_float16)1813 TEST(OperationValidationTest, SOFTMAX_float16) {
1814     softmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
1815 }
1816 
TEST(OperationValidationTest,SOFTMAX_float32)1817 TEST(OperationValidationTest, SOFTMAX_float32) {
1818     softmaxOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
1819 }
1820 
TEST(OperationValidationTest,SOFTMAX_quant8)1821 TEST(OperationValidationTest, SOFTMAX_quant8) {
1822     softmaxOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1823 }
1824 
TEST(OperationValidationTest,SOFTMAX_quant8_signed)1825 TEST(OperationValidationTest, SOFTMAX_quant8_signed) {
1826     softmaxOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1827 }
1828 
poolingOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1829 void poolingOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1830     uint32_t inputDimensions[4] = {2, 4, 4, 2};
1831     ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1832     ANeuralNetworksOperandType output = input;
1833 
1834     ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32,
1835                                          .dimensionCount = 0,
1836                                          .dimensions = nullptr,
1837                                          .scale = 0.0f,
1838                                          .zeroPoint = 0};
1839     ANeuralNetworksOperandType padLeft = scalar;
1840     ANeuralNetworksOperandType padRight = scalar;
1841     ANeuralNetworksOperandType padTop = scalar;
1842     ANeuralNetworksOperandType padBottom = scalar;
1843     ANeuralNetworksOperandType strideWidth = scalar;
1844     ANeuralNetworksOperandType strideHeight = scalar;
1845     ANeuralNetworksOperandType filterWidth = scalar;
1846     ANeuralNetworksOperandType filterHeight = scalar;
1847     ANeuralNetworksOperandType activation = scalar;
1848 
1849     OperationTestBase explicitPoolingTest(operationCode,
1850                                           {input, padLeft, padRight, padTop, padBottom, strideWidth,
1851                                            strideHeight, filterWidth, filterHeight, activation},
1852                                           {output});
1853     explicitPoolingTest.testOpsValidations();
1854 
1855     ANeuralNetworksOperandType padImplicit = scalar;
1856     OperationTestBase implicitPoolingTest(
1857             operationCode,
1858             {input, padImplicit, strideWidth, strideHeight, filterWidth, filterHeight, activation},
1859             {output});
1860     implicitPoolingTest.testOpsValidations();
1861 
1862     ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
1863                                          .dimensionCount = 0,
1864                                          .dimensions = nullptr,
1865                                          .scale = 0.0f,
1866                                          .zeroPoint = 0};
1867 
1868     OperationTestBase explicitNchwPoolingTest(
1869             operationCode,
1870             {input, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight, filterWidth,
1871              filterHeight, activation, layout},
1872             {output});
1873     explicitNchwPoolingTest.testOpsValidations();
1874 
1875     OperationTestBase implicitNchwPoolingTest(operationCode,
1876                                               {input, padImplicit, strideWidth, strideHeight,
1877                                                filterWidth, filterHeight, activation, layout},
1878                                               {output});
1879     implicitNchwPoolingTest.testOpsValidations();
1880 }
1881 
TEST(OperationValidationTest,AVERAGE_POOL_2D_float16)1882 TEST(OperationValidationTest, AVERAGE_POOL_2D_float16) {
1883     poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT16);
1884 }
1885 
TEST(OperationValidationTest,AVERAGE_POOL_2D_float32)1886 TEST(OperationValidationTest, AVERAGE_POOL_2D_float32) {
1887     poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32);
1888 }
1889 
TEST(OperationValidationTest,AVERAGE_POOL_2D_quant8)1890 TEST(OperationValidationTest, AVERAGE_POOL_2D_quant8) {
1891     poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1892 }
1893 
TEST(OperationValidationTest,AVERAGE_POOL_2D_quant8_signed)1894 TEST(OperationValidationTest, AVERAGE_POOL_2D_quant8_signed) {
1895     poolingOpTest(ANEURALNETWORKS_AVERAGE_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1896 }
1897 
TEST(OperationValidationTest,MAX_POOL_2D_float32)1898 TEST(OperationValidationTest, MAX_POOL_2D_float32) {
1899     poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32);
1900 }
1901 
TEST(OperationValidationTest,MAX_POOL_2D_float16)1902 TEST(OperationValidationTest, MAX_POOL_2D_float16) {
1903     poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT16);
1904 }
1905 
TEST(OperationValidationTest,MAX_POOL_2D_quant8)1906 TEST(OperationValidationTest, MAX_POOL_2D_quant8) {
1907     poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1908 }
1909 
TEST(OperationValidationTest,MAX_POOL_2D_quant8_signed)1910 TEST(OperationValidationTest, MAX_POOL_2D_quant8_signed) {
1911     poolingOpTest(ANEURALNETWORKS_MAX_POOL_2D, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1912 }
1913 
TEST(OperationValidationTest,L2_POOL_2D_float16)1914 TEST(OperationValidationTest, L2_POOL_2D_float16) {
1915     poolingOpTest(ANEURALNETWORKS_L2_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT16);
1916 }
1917 
TEST(OperationValidationTest,L2_POOL_2D_float32)1918 TEST(OperationValidationTest, L2_POOL_2D_float32) {
1919     poolingOpTest(ANEURALNETWORKS_L2_POOL_2D, ANEURALNETWORKS_TENSOR_FLOAT32);
1920 }
1921 
spaceDepthOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1922 void spaceDepthOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1923     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1924     ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1925 
1926     ANeuralNetworksOperandType block_size = {.type = ANEURALNETWORKS_INT32,
1927                                              .dimensionCount = 0,
1928                                              .dimensions = nullptr,
1929                                              .scale = 0.0f,
1930                                              .zeroPoint = 0};
1931     ANeuralNetworksOperandType output = input;
1932 
1933     OperationTestBase spaceDepthTest(operationCode, {input, block_size}, {output});
1934     spaceDepthTest.testOpsValidations();
1935 
1936     ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
1937                                          .dimensionCount = 0,
1938                                          .dimensions = nullptr,
1939                                          .scale = 0.0f,
1940                                          .zeroPoint = 0};
1941     OperationTestBase spaceDepthNchwTest(operationCode, {input, block_size, layout}, {output});
1942     spaceDepthNchwTest.testOpsValidations();
1943 }
1944 
TEST(OperationValidationTest,SPACE_TO_DEPTH_float16)1945 TEST(OperationValidationTest, SPACE_TO_DEPTH_float16) {
1946     spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_FLOAT16);
1947 }
1948 
TEST(OperationValidationTest,DEPTH_TO_SPACE_float16)1949 TEST(OperationValidationTest, DEPTH_TO_SPACE_float16) {
1950     spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_FLOAT16);
1951 }
1952 
TEST(OperationValidationTest,SPACE_TO_DEPTH_float32)1953 TEST(OperationValidationTest, SPACE_TO_DEPTH_float32) {
1954     spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_FLOAT32);
1955 }
1956 
TEST(OperationValidationTest,DEPTH_TO_SPACE_float32)1957 TEST(OperationValidationTest, DEPTH_TO_SPACE_float32) {
1958     spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_FLOAT32);
1959 }
1960 
TEST(OperationValidationTest,SPACE_TO_DEPTH_quant8)1961 TEST(OperationValidationTest, SPACE_TO_DEPTH_quant8) {
1962     spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1963 }
1964 
TEST(OperationValidationTest,DEPTH_TO_SPACE_quant8)1965 TEST(OperationValidationTest, DEPTH_TO_SPACE_quant8) {
1966     spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
1967 }
1968 
TEST(OperationValidationTest,SPACE_TO_DEPTH_quant8signed)1969 TEST(OperationValidationTest, SPACE_TO_DEPTH_quant8signed) {
1970     spaceDepthOpTest(ANEURALNETWORKS_SPACE_TO_DEPTH, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1971 }
1972 
TEST(OperationValidationTest,DEPTH_TO_SPACE_quant8signed)1973 TEST(OperationValidationTest, DEPTH_TO_SPACE_quant8signed) {
1974     spaceDepthOpTest(ANEURALNETWORKS_DEPTH_TO_SPACE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
1975 }
1976 
spaceBatchOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)1977 void spaceBatchOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
1978     uint32_t inputDimensions[4] = {2, 2, 2, 2};
1979     ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
1980 
1981     uint32_t blockDimensions[1] = {2};
1982     ANeuralNetworksOperandType blockShape = {.type = ANEURALNETWORKS_TENSOR_INT32,
1983                                              .dimensionCount = 1,
1984                                              .dimensions = blockDimensions,
1985                                              .scale = 0.0f,
1986                                              .zeroPoint = 0};
1987     ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
1988                                          .dimensionCount = 0,
1989                                          .dimensions = nullptr,
1990                                          .scale = 0.0f,
1991                                          .zeroPoint = 0};
1992 
1993     ANeuralNetworksOperandType padding = blockShape;
1994     ANeuralNetworksOperandType output = input;
1995     if (operationCode == ANEURALNETWORKS_SPACE_TO_BATCH_ND) {
1996         OperationTestBase spaceBatchTest(operationCode, {input, blockShape, padding}, {output});
1997         spaceBatchTest.testOpsValidations();
1998 
1999         OperationTestBase spaceBatchNchwTest(operationCode, {input, blockShape, padding, layout},
2000                                              {output});
2001         spaceBatchNchwTest.testOpsValidations();
2002     } else {
2003         OperationTestBase spaceBatchTest(operationCode, {input, blockShape}, {output});
2004         spaceBatchTest.testOpsValidations();
2005 
2006         OperationTestBase spaceBatchNchwTest(operationCode, {input, blockShape, layout}, {output});
2007         spaceBatchNchwTest.testOpsValidations();
2008     }
2009 }
2010 
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_float16)2011 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_float16) {
2012     spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_FLOAT16);
2013 }
2014 
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_float16)2015 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_float16) {
2016     spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_FLOAT16);
2017 }
2018 
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_float32)2019 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_float32) {
2020     spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_FLOAT32);
2021 }
2022 
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_float32)2023 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_float32) {
2024     spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_FLOAT32);
2025 }
2026 
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_quant8)2027 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_quant8) {
2028     spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2029 }
2030 
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_quant8)2031 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_quant8) {
2032     spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2033 }
2034 
TEST(OperationValidationTest,SPACE_TO_BATCH_ND_quant8signed)2035 TEST(OperationValidationTest, SPACE_TO_BATCH_ND_quant8signed) {
2036     spaceBatchOpTest(ANEURALNETWORKS_SPACE_TO_BATCH_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2037 }
2038 
TEST(OperationValidationTest,BATCH_TO_SPACE_ND_quant8signed)2039 TEST(OperationValidationTest, BATCH_TO_SPACE_ND_quant8signed) {
2040     spaceBatchOpTest(ANEURALNETWORKS_BATCH_TO_SPACE_ND, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2041 }
2042 
transposeAndSqueezeOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)2043 void transposeAndSqueezeOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
2044     uint32_t inputDimensions[4] = {2, 2, 2, 2};
2045     ANeuralNetworksOperandType input = getOpType(operandCode, 4, inputDimensions);
2046 
2047     uint32_t blockDimensions[1] = {4};
2048     ANeuralNetworksOperandType dims = {.type = ANEURALNETWORKS_TENSOR_INT32,
2049                                        .dimensionCount = 1,
2050                                        .dimensions = blockDimensions,
2051                                        .scale = 0.0f,
2052                                        .zeroPoint = 0};
2053 
2054     ANeuralNetworksOperandType output = input;
2055     OperationTestBase transposeAndSqueezeTest(operationCode, {input, dims}, {output},
2056                                               {{TensorRankConstraint::UpTo(4)}});
2057     transposeAndSqueezeTest.testOpsValidations();
2058 }
2059 
TEST(OperationValidationTest,TRANSPOSE_float16)2060 TEST(OperationValidationTest, TRANSPOSE_float16) {
2061     transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_FLOAT16);
2062 }
2063 
TEST(OperationValidationTest,SQUEEZE_float16)2064 TEST(OperationValidationTest, SQUEEZE_float16) {
2065     transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_FLOAT16);
2066 }
2067 
TEST(OperationValidationTest,TRANSPOSE_float32)2068 TEST(OperationValidationTest, TRANSPOSE_float32) {
2069     transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_FLOAT32);
2070 }
2071 
TEST(OperationValidationTest,SQUEEZE_float32)2072 TEST(OperationValidationTest, SQUEEZE_float32) {
2073     transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_FLOAT32);
2074 }
2075 
TEST(OperationValidationTest,TRANSPOSE_quant8)2076 TEST(OperationValidationTest, TRANSPOSE_quant8) {
2077     transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2078 }
2079 
TEST(OperationValidationTest,TRANSPOSE_quant8signed)2080 TEST(OperationValidationTest, TRANSPOSE_quant8signed) {
2081     transposeAndSqueezeOpTest(ANEURALNETWORKS_TRANSPOSE,
2082                               ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2083 }
2084 
TEST(OperationValidationTest,SQUEEZE_quant8)2085 TEST(OperationValidationTest, SQUEEZE_quant8) {
2086     transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2087 }
2088 
TEST(OperationValidationTest,SQUEEZE_quant8_signed)2089 TEST(OperationValidationTest, SQUEEZE_quant8_signed) {
2090     transposeAndSqueezeOpTest(ANEURALNETWORKS_SQUEEZE, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2091 }
2092 
convOpTest(int32_t inputOperandCode,int32_t filterOperandCode)2093 void convOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
2094     uint32_t inputDimensions[4] = {2, 4, 4, 2};
2095     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
2096     ANeuralNetworksOperandType output = input;
2097 
2098     float filterScales[2] = {0.5f, 1.0f};
2099     ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, inputDimensions);
2100     ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
2101             .channelDim = 0,
2102             .scaleCount = 2,
2103             .scales = filterScales,
2104     };
2105 
2106     uint32_t biasDimensions[1] = {2};
2107     ANeuralNetworksOperandType bias = {.type = inputOperandCode,
2108                                        .dimensionCount = 1,
2109                                        .dimensions = biasDimensions,
2110                                        .scale = 0.0f,
2111                                        .zeroPoint = 0};
2112     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM) {
2113         bias.type = ANEURALNETWORKS_TENSOR_INT32;
2114         bias.scale = 0.25f;
2115     }
2116     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
2117         bias.type = ANEURALNETWORKS_TENSOR_INT32;
2118         bias.scale = 0.25f;
2119     }
2120     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2121         bias.type = ANEURALNETWORKS_TENSOR_INT32;
2122         bias.scale = 0.0f;
2123     }
2124 
2125     ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32,
2126                                          .dimensionCount = 0,
2127                                          .dimensions = nullptr,
2128                                          .scale = 0.0f,
2129                                          .zeroPoint = 0};
2130     ANeuralNetworksOperandType padLeft = scalar;
2131     ANeuralNetworksOperandType padRight = scalar;
2132     ANeuralNetworksOperandType padTop = scalar;
2133     ANeuralNetworksOperandType padBottom = scalar;
2134     ANeuralNetworksOperandType strideWidth = scalar;
2135     ANeuralNetworksOperandType strideHeight = scalar;
2136     ANeuralNetworksOperandType dilationHeightFactor = scalar;
2137     ANeuralNetworksOperandType dilationWidthFactor = scalar;
2138     ANeuralNetworksOperandType activation = scalar;
2139 
2140     OperationTestBase explicitConvTest(ANEURALNETWORKS_CONV_2D,
2141                                        {input, filter, bias, padLeft, padRight, padTop, padBottom,
2142                                         strideWidth, strideHeight, activation},
2143                                        {output});
2144     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2145         explicitConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2146     }
2147     explicitConvTest.testOpsValidations();
2148 
2149     ANeuralNetworksOperandType padImplicit = scalar;
2150     OperationTestBase implicitConvTest(
2151             ANEURALNETWORKS_CONV_2D,
2152             {input, filter, bias, padImplicit, strideWidth, strideHeight, activation}, {output},
2153             {{TensorRankConstraint::Exactly(4), {0, 1}}});
2154     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2155         implicitConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2156     }
2157     implicitConvTest.testOpsValidations();
2158 
2159     ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
2160                                          .dimensionCount = 0,
2161                                          .dimensions = nullptr,
2162                                          .scale = 0.0f,
2163                                          .zeroPoint = 0};
2164 
2165     OperationTestBase explicitNchwConvTest(
2166             ANEURALNETWORKS_CONV_2D,
2167             {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2168              activation, layout},
2169             {output});
2170     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2171         explicitNchwConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2172     }
2173     explicitNchwConvTest.testOpsValidations();
2174 
2175     OperationTestBase implicitNchwConvTest(
2176             ANEURALNETWORKS_CONV_2D,
2177             {input, filter, bias, padImplicit, strideWidth, strideHeight, activation, layout},
2178             {output});
2179     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2180         implicitNchwConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2181     }
2182     implicitNchwConvTest.testOpsValidations();
2183 
2184     OperationTestBase explicitDilateConvTest(
2185             ANEURALNETWORKS_CONV_2D,
2186             {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2187              activation, layout, dilationWidthFactor, dilationHeightFactor},
2188             {output});
2189     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2190         explicitDilateConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2191     }
2192     explicitDilateConvTest.testOpsValidations();
2193 
2194     OperationTestBase implicitDilateConvTest(
2195             ANEURALNETWORKS_CONV_2D,
2196             {input, filter, bias, padImplicit, strideWidth, strideHeight, activation, layout,
2197              dilationWidthFactor, dilationHeightFactor},
2198             {output});
2199     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2200         implicitDilateConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2201     }
2202     implicitDilateConvTest.testOpsValidations();
2203 }
2204 
TEST(OperationValidationTest,CONV_2D_float16)2205 TEST(OperationValidationTest, CONV_2D_float16) {
2206     convOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
2207 }
2208 
TEST(OperationValidationTest,CONV_2D_float32)2209 TEST(OperationValidationTest, CONV_2D_float32) {
2210     convOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2211 }
2212 
TEST(OperationValidationTest,CONV_2D_quant8)2213 TEST(OperationValidationTest, CONV_2D_quant8) {
2214     convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2215 }
2216 
TEST(OperationValidationTest,CONV_2D_quant8_per_channel)2217 TEST(OperationValidationTest, CONV_2D_quant8_per_channel) {
2218     convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2219 }
2220 
TEST(OperationValidationTest,CONV_2D_quant8_signed)2221 TEST(OperationValidationTest, CONV_2D_quant8_signed) {
2222     convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2223                ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2224 }
2225 
TEST(OperationValidationTest,CONV_2D_quant8_signed_per_channel)2226 TEST(OperationValidationTest, CONV_2D_quant8_signed_per_channel) {
2227     convOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2228                ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2229 }
2230 
depthwiseConvOpTest(int32_t inputOperandCode,int32_t filterOperandCode)2231 void depthwiseConvOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
2232     uint32_t inputDimensions[4] = {1, 2, 2, 2};
2233     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
2234     ANeuralNetworksOperandType output = input;
2235 
2236     float filterScales[2] = {0.5f, 1.0f};
2237     ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, inputDimensions);
2238     ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
2239             .channelDim = 3,
2240             .scaleCount = 2,
2241             .scales = filterScales,
2242     };
2243 
2244     uint32_t biasDimensions[1] = {2};
2245     ANeuralNetworksOperandType bias = {.type = inputOperandCode,
2246                                        .dimensionCount = 1,
2247                                        .dimensions = biasDimensions,
2248                                        .scale = 0.0f,
2249                                        .zeroPoint = 0};
2250     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
2251         filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
2252         bias.type = ANEURALNETWORKS_TENSOR_INT32;
2253         bias.scale = 0.25f;
2254     }
2255     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2256         bias.type = ANEURALNETWORKS_TENSOR_INT32;
2257         bias.scale = 0.0f;
2258     }
2259 
2260     ANeuralNetworksOperandType scalar = {.type = ANEURALNETWORKS_INT32,
2261                                          .dimensionCount = 0,
2262                                          .dimensions = nullptr,
2263                                          .scale = 0.0f,
2264                                          .zeroPoint = 0};
2265     ANeuralNetworksOperandType padLeft = scalar;
2266     ANeuralNetworksOperandType padRight = scalar;
2267     ANeuralNetworksOperandType padTop = scalar;
2268     ANeuralNetworksOperandType padBottom = scalar;
2269     ANeuralNetworksOperandType strideWidth = scalar;
2270     ANeuralNetworksOperandType strideHeight = scalar;
2271     ANeuralNetworksOperandType multiplier = scalar;
2272     ANeuralNetworksOperandType activation = scalar;
2273 
2274     OperationTestBase explicitDepthwiseConvTest(
2275             ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2276             {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2277              multiplier, activation},
2278             {output});
2279     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2280         explicitDepthwiseConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2281     }
2282     explicitDepthwiseConvTest.testOpsValidations();
2283 
2284     ANeuralNetworksOperandType padImplicit = scalar;
2285     OperationTestBase implicitDepthwiseConvTest(
2286             ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2287             {input, filter, bias, padImplicit, strideWidth, strideHeight, multiplier, activation},
2288             {output});
2289     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2290         implicitDepthwiseConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
2291     }
2292     implicitDepthwiseConvTest.testOpsValidations();
2293 
2294     ANeuralNetworksOperandType layout = {.type = ANEURALNETWORKS_BOOL,
2295                                          .dimensionCount = 0,
2296                                          .dimensions = nullptr,
2297                                          .scale = 0.0f,
2298                                          .zeroPoint = 0};
2299 
2300     OperationTestBase explicitNchwDepthwiseConvTest(
2301             ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2302             {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2303              multiplier, activation, layout},
2304             {output});
2305     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2306         explicitNchwDepthwiseConvTest.setInputSymmPerChannelQuantParams(1,
2307                                                                         filterChannelQuantParams);
2308     }
2309     explicitNchwDepthwiseConvTest.testOpsValidations();
2310 
2311     OperationTestBase implicitNchwDepthwiseConvTest(ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2312                                                     {input, filter, bias, padImplicit, strideWidth,
2313                                                      strideHeight, multiplier, activation, layout},
2314                                                     {output});
2315     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2316         implicitNchwDepthwiseConvTest.setInputSymmPerChannelQuantParams(1,
2317                                                                         filterChannelQuantParams);
2318     }
2319     implicitNchwDepthwiseConvTest.testOpsValidations();
2320 
2321     ANeuralNetworksOperandType dilationHeightFactor = scalar;
2322     ANeuralNetworksOperandType dilationWidthFactor = scalar;
2323 
2324     OperationTestBase explicitDilationDepthwiseConvTest(
2325             ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2326             {input, filter, bias, padLeft, padRight, padTop, padBottom, strideWidth, strideHeight,
2327              multiplier, activation, layout, dilationWidthFactor, dilationHeightFactor},
2328             {output});
2329     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2330         explicitDilationDepthwiseConvTest.setInputSymmPerChannelQuantParams(
2331                 1, filterChannelQuantParams);
2332     }
2333     explicitDilationDepthwiseConvTest.testOpsValidations();
2334 
2335     OperationTestBase implicitDilationDepthwiseConvTest(
2336             ANEURALNETWORKS_DEPTHWISE_CONV_2D,
2337             {input, filter, bias, padImplicit, strideWidth, strideHeight, multiplier, activation,
2338              layout, dilationWidthFactor, dilationHeightFactor},
2339             {output});
2340     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
2341         implicitDilationDepthwiseConvTest.setInputSymmPerChannelQuantParams(
2342                 1, filterChannelQuantParams);
2343     }
2344     implicitDilationDepthwiseConvTest.testOpsValidations();
2345 }
2346 
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_float32)2347 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_float32) {
2348     depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2349 }
2350 
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_float16)2351 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_float16) {
2352     depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
2353 }
2354 
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8)2355 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8) {
2356     depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2357 }
2358 
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8_per_channel)2359 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8_per_channel) {
2360     depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
2361                         ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2362 }
2363 
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8_signed)2364 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8_signed) {
2365     depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2366                         ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2367 }
2368 
TEST(OperationValidationTest,DEPTHWISE_CONV_2D_quant8_signed_per_channel)2369 TEST(OperationValidationTest, DEPTHWISE_CONV_2D_quant8_signed_per_channel) {
2370     depthwiseConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
2371                         ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
2372 }
2373 
fullyConnectedOpTest(int32_t operandCode)2374 void fullyConnectedOpTest(int32_t operandCode) {
2375     uint32_t inputDimensions[2] = {5, 5};
2376     ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
2377 
2378     ANeuralNetworksOperandType weights = input;
2379     ANeuralNetworksOperandType output = input;
2380 
2381     uint32_t biasDimensions[1] = {5};
2382     ANeuralNetworksOperandType bias = {.type = operandCode,
2383                                        .dimensionCount = 1,
2384                                        .dimensions = biasDimensions,
2385                                        .scale = 0.0f,
2386                                        .zeroPoint = 0};
2387     if (operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
2388         operandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
2389         bias.type = ANEURALNETWORKS_TENSOR_INT32;
2390         bias.scale = 0.25f;
2391     }
2392 
2393     ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
2394                                              .dimensionCount = 0,
2395                                              .dimensions = nullptr,
2396                                              .scale = 0.0f,
2397                                              .zeroPoint = 0};
2398 
2399     OperationTestBase fullyConnectedTest(ANEURALNETWORKS_FULLY_CONNECTED,
2400                                          {input, weights, bias, activation}, {output},
2401                                          {{TensorRankConstraint::Between(2, 4), {0}},
2402                                           {TensorRankConstraint::Exactly(2), {1}},
2403                                           {TensorRankConstraint::Exactly(1), {2}}});
2404     fullyConnectedTest.testOpsValidations();
2405 }
2406 
TEST(OperationValidationTest,FULLY_CONNECTED_float16)2407 TEST(OperationValidationTest, FULLY_CONNECTED_float16) {
2408     fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
2409 }
2410 
TEST(OperationValidationTest,FULLY_CONNECTED_float32)2411 TEST(OperationValidationTest, FULLY_CONNECTED_float32) {
2412     fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2413 }
2414 
TEST(OperationValidationTest,FULLY_CONNECTED_quant8)2415 TEST(OperationValidationTest, FULLY_CONNECTED_quant8) {
2416     fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2417 }
2418 
TEST(OperationValidationTest,FULLY_CONNECTED_quant8_signed)2419 TEST(OperationValidationTest, FULLY_CONNECTED_quant8_signed) {
2420     fullyConnectedOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2421 }
2422 
concatenationTest(int32_t operandCode)2423 void concatenationTest(int32_t operandCode) {
2424     uint32_t inputDimensions[2] = {5, 5};
2425     ANeuralNetworksOperandType input1 = getOpType(operandCode, 2, inputDimensions);
2426     ANeuralNetworksOperandType input2 = input1;
2427     ANeuralNetworksOperandType output = input1;
2428 
2429     ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
2430                                              .dimensionCount = 0,
2431                                              .dimensions = nullptr,
2432                                              .scale = 0.0f,
2433                                              .zeroPoint = 0};
2434 
2435     OperationTestBase concat2Test(ANEURALNETWORKS_CONCATENATION, {input1, input2, activation},
2436                                   {output}, {{TensorRankConstraint::UpTo(4), {0, 1}}});
2437     concat2Test.testOpsValidations();
2438 
2439     OperationTestBase concat1Test(ANEURALNETWORKS_CONCATENATION, {input1, activation}, {output},
2440                                   {{TensorRankConstraint::UpTo(4)}});
2441     concat1Test.testOpsValidations();
2442 }
2443 
TEST(OperationValidationTest,CONCATENATION_float16)2444 TEST(OperationValidationTest, CONCATENATION_float16) {
2445     concatenationTest(ANEURALNETWORKS_TENSOR_FLOAT16);
2446 }
2447 
TEST(OperationValidationTest,CONCATENATION_float32)2448 TEST(OperationValidationTest, CONCATENATION_float32) {
2449     concatenationTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2450 }
2451 
TEST(OperationValidationTest,CONCATENATION_quant8)2452 TEST(OperationValidationTest, CONCATENATION_quant8) {
2453     concatenationTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2454 }
2455 
TEST(OperationValidationTest,CONCATENATION_quant8_signed)2456 TEST(OperationValidationTest, CONCATENATION_quant8_signed) {
2457     concatenationTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2458 }
2459 
resizeBilinearOpTest(int32_t inputOperandCode,int32_t scalarOperandCode)2460 void resizeBilinearOpTest(int32_t inputOperandCode, int32_t scalarOperandCode) {
2461     SCOPED_TRACE(inputOperandCode);
2462     uint32_t inputDimensions[4] = {2, 2, 2, 2};
2463     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inputDimensions);
2464     ANeuralNetworksOperandType height = getOpType(scalarOperandCode);
2465     ANeuralNetworksOperandType width = height;
2466     ANeuralNetworksOperandType output = input;
2467 
2468     OperationTestBase resizeTest(ANEURALNETWORKS_RESIZE_BILINEAR, {input, height, width}, {output});
2469     resizeTest.testOpsValidations();
2470 
2471     ANeuralNetworksOperandType layout = getOpType(ANEURALNETWORKS_BOOL);
2472     OperationTestBase resizeNchwTest(ANEURALNETWORKS_RESIZE_BILINEAR,
2473                                      {input, height, width, layout}, {output});
2474     resizeNchwTest.testOpsValidations();
2475 }
2476 
TEST(OperationValidationTest,RESIZE_BILINEAR)2477 TEST(OperationValidationTest, RESIZE_BILINEAR) {
2478     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_INT32);
2479     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_INT32);
2480     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_INT32);
2481     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_INT32);
2482     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_FLOAT16);
2483     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_FLOAT32);
2484     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_FLOAT32);
2485     resizeBilinearOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_FLOAT32);
2486 }
2487 
embeddingLookupTest(int32_t operandCode)2488 void embeddingLookupTest(int32_t operandCode) {
2489     uint32_t lookupDimensions[1] = {5};
2490     ANeuralNetworksOperandType lookup = {.type = ANEURALNETWORKS_TENSOR_INT32,
2491                                          .dimensionCount = 1,
2492                                          .dimensions = lookupDimensions,
2493                                          .scale = 0.0f,
2494                                          .zeroPoint = 0};
2495 
2496     uint32_t inputDimensions[2] = {5, 5};
2497     ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
2498     ANeuralNetworksOperandType output = input;
2499 
2500     OperationTestBase embedLookupTest(ANEURALNETWORKS_EMBEDDING_LOOKUP, {lookup, input}, {output});
2501     embedLookupTest.testOpsValidations();
2502 }
2503 
TEST(OperationValidationTest,EMBEDDING_LOOKUP_float32)2504 TEST(OperationValidationTest, EMBEDDING_LOOKUP_float32) {
2505     embeddingLookupTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2506 }
2507 
TEST(OperationValidationTest,EMBEDDING_LOOKUP_int32)2508 TEST(OperationValidationTest, EMBEDDING_LOOKUP_int32) {
2509     embeddingLookupTest(ANEURALNETWORKS_TENSOR_INT32);
2510 }
2511 
TEST(OperationValidationTest,EMBEDDING_LOOKUP_quant8)2512 TEST(OperationValidationTest, EMBEDDING_LOOKUP_quant8) {
2513     embeddingLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2514 }
2515 
TEST(OperationValidationTest,EMBEDDING_LOOKUP_quant8_signed)2516 TEST(OperationValidationTest, EMBEDDING_LOOKUP_quant8_signed) {
2517     embeddingLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
2518 }
2519 
hashtableLookupTest(int32_t operandCode)2520 void hashtableLookupTest(int32_t operandCode) {
2521     uint32_t lookupDimensions[1] = {5};
2522     ANeuralNetworksOperandType lookup = {.type = ANEURALNETWORKS_TENSOR_INT32,
2523                                          .dimensionCount = 1,
2524                                          .dimensions = lookupDimensions,
2525                                          .scale = 0.0f,
2526                                          .zeroPoint = 0};
2527     ANeuralNetworksOperandType keys = lookup;
2528 
2529     uint32_t valuesDimensions[2] = {5, 5};
2530     ANeuralNetworksOperandType values = getOpType(operandCode, 2, valuesDimensions);
2531     ANeuralNetworksOperandType output = values;
2532 
2533     ANeuralNetworksOperandType hits = lookup;
2534     hits.type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM;
2535     hits.scale = 1.0f;
2536 
2537     OperationTestBase hashLookupTest(ANEURALNETWORKS_HASHTABLE_LOOKUP, {lookup, keys, values},
2538                                      {output, hits});
2539     hashLookupTest.testOpsValidations();
2540 }
2541 
TEST(OperationValidationTest,HASHTABLE_LOOKUP_float32)2542 TEST(OperationValidationTest, HASHTABLE_LOOKUP_float32) {
2543     hashtableLookupTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2544 }
2545 
TEST(OperationValidationTest,HASHTABLE_LOOKUP_int32)2546 TEST(OperationValidationTest, HASHTABLE_LOOKUP_int32) {
2547     hashtableLookupTest(ANEURALNETWORKS_TENSOR_INT32);
2548 }
2549 
TEST(OperationValidationTest,HASHTABLE_LOOKUP_quant8)2550 TEST(OperationValidationTest, HASHTABLE_LOOKUP_quant8) {
2551     hashtableLookupTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
2552 }
2553 
lshProjectionTest(int32_t operandCode,int32_t hashAndWeightOperandCode)2554 void lshProjectionTest(int32_t operandCode, int32_t hashAndWeightOperandCode) {
2555     uint32_t inputDimensions[2] = {5, 5};
2556     ANeuralNetworksOperandType hash = getOpType(hashAndWeightOperandCode, 2, inputDimensions);
2557     ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
2558 
2559     uint32_t weightDimensions[1] = {5};
2560     ANeuralNetworksOperandType weight = getOpType(hashAndWeightOperandCode, 1, weightDimensions);
2561 
2562     ANeuralNetworksOperandType type = {.type = ANEURALNETWORKS_INT32,
2563                                        .dimensionCount = 0,
2564                                        .dimensions = nullptr,
2565                                        .scale = 0.0f,
2566                                        .zeroPoint = 0};
2567 
2568     ANeuralNetworksOperandType output = weight;
2569     output.type = ANEURALNETWORKS_TENSOR_INT32;
2570 
2571     OperationTestBase lshProjTest(ANEURALNETWORKS_LSH_PROJECTION, {hash, input, weight, type},
2572                                   {output});
2573     lshProjTest.testOpsValidations();
2574 }
2575 
TEST(OperationValidationTest,LSH_PROJECTION_float16)2576 TEST(OperationValidationTest, LSH_PROJECTION_float16) {
2577     lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT32);
2578     lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
2579 }
2580 
TEST(OperationValidationTest,LSH_PROJECTION_float32)2581 TEST(OperationValidationTest, LSH_PROJECTION_float32) {
2582     lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2583     lshProjectionTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT16);
2584 }
2585 
TEST(OperationValidationTest,LSH_PROJECTION_quant8)2586 TEST(OperationValidationTest, LSH_PROJECTION_quant8) {
2587     lshProjectionTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT32);
2588     lshProjectionTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_FLOAT16);
2589 }
2590 
TEST(OperationValidationTest,LSH_PROJECTION_int32)2591 TEST(OperationValidationTest, LSH_PROJECTION_int32) {
2592     lshProjectionTest(ANEURALNETWORKS_TENSOR_INT32, ANEURALNETWORKS_TENSOR_FLOAT32);
2593     lshProjectionTest(ANEURALNETWORKS_TENSOR_INT32, ANEURALNETWORKS_TENSOR_FLOAT16);
2594 }
2595 
TEST(OperationValidationTest,LSTM_float32)2596 TEST(OperationValidationTest, LSTM_float32) {
2597     uint32_t oneDimensional[1] = {5};
2598     uint32_t twoDimensional[2] = {5, 5};
2599     ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
2600                                                 .dimensionCount = 1,
2601                                                 .dimensions = oneDimensional,
2602                                                 .scale = 0.0f,
2603                                                 .zeroPoint = 0};
2604     ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
2605                                                 .dimensionCount = 2,
2606                                                 .dimensions = twoDimensional,
2607                                                 .scale = 0.0f,
2608                                                 .zeroPoint = 0};
2609     ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
2610                                             .dimensionCount = 0,
2611                                             .dimensions = nullptr,
2612                                             .scale = 0.0f,
2613                                             .zeroPoint = 0};
2614     ANeuralNetworksOperandType floatScalar = {.type = ANEURALNETWORKS_FLOAT32,
2615                                               .dimensionCount = 0,
2616                                               .dimensions = nullptr,
2617                                               .scale = 0.0f,
2618                                               .zeroPoint = 0};
2619 
2620     ANeuralNetworksOperandType input = floatTensor2D;
2621     ANeuralNetworksOperandType inputToInput = floatTensor2D;
2622     ANeuralNetworksOperandType inputToForget = floatTensor2D;
2623     ANeuralNetworksOperandType inputToCell = floatTensor2D;
2624     ANeuralNetworksOperandType inputToOutput = floatTensor2D;
2625     ANeuralNetworksOperandType recurrentToInput = floatTensor2D;
2626     ANeuralNetworksOperandType recurrentToForget = floatTensor2D;
2627     ANeuralNetworksOperandType recurrentToCell = floatTensor2D;
2628     ANeuralNetworksOperandType recurrentToOutput = floatTensor2D;
2629     ANeuralNetworksOperandType cellToInput = floatTensor1D;
2630     ANeuralNetworksOperandType cellToForget = floatTensor1D;
2631     ANeuralNetworksOperandType cellToOutput = floatTensor1D;
2632     ANeuralNetworksOperandType inputGateBias = floatTensor1D;
2633     ANeuralNetworksOperandType forgetGateBias = floatTensor1D;
2634     ANeuralNetworksOperandType cellBias = floatTensor1D;
2635     ANeuralNetworksOperandType outputGateBias = floatTensor1D;
2636     ANeuralNetworksOperandType projWeights = floatTensor2D;
2637     ANeuralNetworksOperandType projBias = floatTensor1D;
2638     ANeuralNetworksOperandType outputStateIn = floatTensor2D;
2639     ANeuralNetworksOperandType cellStateIn = floatTensor2D;
2640     ANeuralNetworksOperandType activation = intScalar;
2641     ANeuralNetworksOperandType clipCellState = floatScalar;
2642     ANeuralNetworksOperandType clipProjLayer = floatScalar;
2643 
2644     ANeuralNetworksOperandType scratch = floatTensor2D;
2645     ANeuralNetworksOperandType outputStateOut = floatTensor2D;
2646     ANeuralNetworksOperandType cellStateOut = floatTensor2D;
2647     ANeuralNetworksOperandType output = floatTensor2D;
2648 
2649     OperationTestBase lstmTest(ANEURALNETWORKS_LSTM,
2650                                {input,
2651                                 inputToInput,
2652                                 inputToForget,
2653                                 inputToCell,
2654                                 inputToOutput,
2655                                 recurrentToInput,
2656                                 recurrentToForget,
2657                                 recurrentToCell,
2658                                 recurrentToOutput,
2659                                 cellToInput,
2660                                 cellToForget,
2661                                 cellToOutput,
2662                                 inputGateBias,
2663                                 forgetGateBias,
2664                                 cellBias,
2665                                 outputGateBias,
2666                                 projWeights,
2667                                 projBias,
2668                                 outputStateIn,
2669                                 cellStateIn,
2670                                 activation,
2671                                 clipCellState,
2672                                 clipProjLayer},
2673                                {scratch, outputStateOut, cellStateOut, output});
2674     lstmTest.testOpsValidations();
2675 }
2676 
lstmTestV1_2(int32_t operandCode)2677 void lstmTestV1_2(int32_t operandCode) {
2678     SCOPED_TRACE(operandCode);
2679     uint32_t oneDimensional[1] = {5};
2680     uint32_t twoDimensional[2] = {5, 5};
2681     ANeuralNetworksOperandType floatTensor1D = {.type = operandCode,
2682                                                 .dimensionCount = 1,
2683                                                 .dimensions = oneDimensional,
2684                                                 .scale = 0.0f,
2685                                                 .zeroPoint = 0};
2686     ANeuralNetworksOperandType floatTensor2D = {.type = operandCode,
2687                                                 .dimensionCount = 2,
2688                                                 .dimensions = twoDimensional,
2689                                                 .scale = 0.0f,
2690                                                 .zeroPoint = 0};
2691     ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
2692                                             .dimensionCount = 0,
2693                                             .dimensions = nullptr,
2694                                             .scale = 0.0f,
2695                                             .zeroPoint = 0};
2696     ANeuralNetworksOperandType floatScalar = {
2697             .type = (operandCode == ANEURALNETWORKS_TENSOR_FLOAT32) ? ANEURALNETWORKS_FLOAT32
2698                                                                     : ANEURALNETWORKS_FLOAT16,
2699             .dimensionCount = 0,
2700             .dimensions = nullptr,
2701             .scale = 0.0f,
2702             .zeroPoint = 0};
2703 
2704     ANeuralNetworksOperandType input = floatTensor2D;
2705     ANeuralNetworksOperandType inputToInput = floatTensor2D;
2706     ANeuralNetworksOperandType inputToForget = floatTensor2D;
2707     ANeuralNetworksOperandType inputToCell = floatTensor2D;
2708     ANeuralNetworksOperandType inputToOutput = floatTensor2D;
2709     ANeuralNetworksOperandType recurrentToInput = floatTensor2D;
2710     ANeuralNetworksOperandType recurrentToForget = floatTensor2D;
2711     ANeuralNetworksOperandType recurrentToCell = floatTensor2D;
2712     ANeuralNetworksOperandType recurrentToOutput = floatTensor2D;
2713     ANeuralNetworksOperandType cellToInput = floatTensor1D;
2714     ANeuralNetworksOperandType cellToForget = floatTensor1D;
2715     ANeuralNetworksOperandType cellToOutput = floatTensor1D;
2716     ANeuralNetworksOperandType inputGateBias = floatTensor1D;
2717     ANeuralNetworksOperandType forgetGateBias = floatTensor1D;
2718     ANeuralNetworksOperandType cellBias = floatTensor1D;
2719     ANeuralNetworksOperandType outputGateBias = floatTensor1D;
2720     ANeuralNetworksOperandType projWeights = floatTensor2D;
2721     ANeuralNetworksOperandType projBias = floatTensor1D;
2722     ANeuralNetworksOperandType outputStateIn = floatTensor2D;
2723     ANeuralNetworksOperandType cellStateIn = floatTensor2D;
2724     ANeuralNetworksOperandType activation = intScalar;
2725     ANeuralNetworksOperandType clipCellState = floatScalar;
2726     ANeuralNetworksOperandType clipProjLayer = floatScalar;
2727     ANeuralNetworksOperandType inputLayerNormWeights = floatTensor1D;
2728     ANeuralNetworksOperandType forgetLayerNormWeights = floatTensor1D;
2729     ANeuralNetworksOperandType cellLayerNormWeights = floatTensor1D;
2730     ANeuralNetworksOperandType outputLayerNormWeights = floatTensor1D;
2731 
2732     ANeuralNetworksOperandType scratch = floatTensor2D;
2733     ANeuralNetworksOperandType outputStateOut = floatTensor2D;
2734     ANeuralNetworksOperandType cellStateOut = floatTensor2D;
2735     ANeuralNetworksOperandType output = floatTensor2D;
2736 
2737     OperationTestBase lstmTest(ANEURALNETWORKS_LSTM,
2738                                {input,
2739                                 inputToInput,
2740                                 inputToForget,
2741                                 inputToCell,
2742                                 inputToOutput,
2743                                 recurrentToInput,
2744                                 recurrentToForget,
2745                                 recurrentToCell,
2746                                 recurrentToOutput,
2747                                 cellToInput,
2748                                 cellToForget,
2749                                 cellToOutput,
2750                                 inputGateBias,
2751                                 forgetGateBias,
2752                                 cellBias,
2753                                 outputGateBias,
2754                                 projWeights,
2755                                 projBias,
2756                                 outputStateIn,
2757                                 cellStateIn,
2758                                 activation,
2759                                 clipCellState,
2760                                 clipProjLayer,
2761                                 inputLayerNormWeights,
2762                                 forgetLayerNormWeights,
2763                                 cellLayerNormWeights,
2764                                 outputLayerNormWeights},
2765                                {scratch, outputStateOut, cellStateOut, output});
2766     lstmTest.testOpsValidations();
2767 }
2768 
TEST(OperationValidationTest,LSTM_V1_2)2769 TEST(OperationValidationTest, LSTM_V1_2) {
2770     lstmTestV1_2(ANEURALNETWORKS_TENSOR_FLOAT32);
2771     lstmTestV1_2(ANEURALNETWORKS_TENSOR_FLOAT16);
2772 }
2773 
lstmBidirectionalSequence(int32_t operandCode)2774 void lstmBidirectionalSequence(int32_t operandCode) {
2775     uint32_t oneDimensional[1] = {5};
2776     uint32_t twoDimensional[2] = {5, 5};
2777     uint32_t threeDimensional[3] = {5, 5, 5};
2778     ANeuralNetworksOperandType floatTensor1D = {
2779             .type = operandCode,
2780             .dimensionCount = 1,
2781             .dimensions = oneDimensional,
2782             .scale = 0.0f,
2783             .zeroPoint = 0,
2784     };
2785     ANeuralNetworksOperandType floatTensor2D = {
2786             .type = operandCode,
2787             .dimensionCount = 2,
2788             .dimensions = twoDimensional,
2789             .scale = 0.0f,
2790             .zeroPoint = 0,
2791     };
2792     ANeuralNetworksOperandType floatTensor3D = {
2793             .type = operandCode,
2794             .dimensionCount = 3,
2795             .dimensions = threeDimensional,
2796             .scale = 0.0f,
2797             .zeroPoint = 0,
2798     };
2799     ANeuralNetworksOperandType intScalar = {
2800             .type = ANEURALNETWORKS_INT32,
2801             .dimensionCount = 0,
2802             .dimensions = nullptr,
2803             .scale = 0.0f,
2804             .zeroPoint = 0,
2805     };
2806     ANeuralNetworksOperandType floatScalar = {
2807             .type = operandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ? ANEURALNETWORKS_FLOAT32
2808                                                                   : ANEURALNETWORKS_FLOAT16,
2809             .dimensionCount = 0,
2810             .dimensions = nullptr,
2811             .scale = 0.0f,
2812             .zeroPoint = 0,
2813     };
2814     ANeuralNetworksOperandType boolScalar = {.type = ANEURALNETWORKS_BOOL,
2815                                              .dimensionCount = 0,
2816                                              .dimensions = nullptr,
2817                                              .scale = 0.0f,
2818                                              .zeroPoint = 0};
2819 
2820     ANeuralNetworksOperandType input = floatTensor3D;
2821     ANeuralNetworksOperandType inputToInputFw = floatTensor2D;
2822     ANeuralNetworksOperandType inputToForgetFw = floatTensor2D;
2823     ANeuralNetworksOperandType inputToCellFw = floatTensor2D;
2824     ANeuralNetworksOperandType inputToOutputFw = floatTensor2D;
2825     ANeuralNetworksOperandType recurrentToInputFw = floatTensor2D;
2826     ANeuralNetworksOperandType recurrentToForgetFw = floatTensor2D;
2827     ANeuralNetworksOperandType recurrentToCellFw = floatTensor2D;
2828     ANeuralNetworksOperandType recurrentToOutputFw = floatTensor2D;
2829     ANeuralNetworksOperandType cellToInputFw = floatTensor1D;
2830     ANeuralNetworksOperandType cellToForgetFw = floatTensor1D;
2831     ANeuralNetworksOperandType cellToOutputFw = floatTensor1D;
2832     ANeuralNetworksOperandType inputGateBiasFw = floatTensor1D;
2833     ANeuralNetworksOperandType forgetGateBiasFw = floatTensor1D;
2834     ANeuralNetworksOperandType cellBiasFw = floatTensor1D;
2835     ANeuralNetworksOperandType outputGateBiasFw = floatTensor1D;
2836     ANeuralNetworksOperandType projWeightsFw = floatTensor2D;
2837     ANeuralNetworksOperandType projBiasFw = floatTensor1D;
2838     ANeuralNetworksOperandType outputStateInFw = floatTensor2D;
2839     ANeuralNetworksOperandType cellStateInFw = floatTensor2D;
2840     ANeuralNetworksOperandType inputToInputBw = floatTensor2D;
2841     ANeuralNetworksOperandType inputToForgetBw = floatTensor2D;
2842     ANeuralNetworksOperandType inputToCellBw = floatTensor2D;
2843     ANeuralNetworksOperandType inputToOutputBw = floatTensor2D;
2844     ANeuralNetworksOperandType recurrentToInputBw = floatTensor2D;
2845     ANeuralNetworksOperandType recurrentToForgetBw = floatTensor2D;
2846     ANeuralNetworksOperandType recurrentToCellBw = floatTensor2D;
2847     ANeuralNetworksOperandType recurrentToOutputBw = floatTensor2D;
2848     ANeuralNetworksOperandType cellToInputBw = floatTensor1D;
2849     ANeuralNetworksOperandType cellToForgetBw = floatTensor1D;
2850     ANeuralNetworksOperandType cellToOutputBw = floatTensor1D;
2851     ANeuralNetworksOperandType inputGateBiasBw = floatTensor1D;
2852     ANeuralNetworksOperandType forgetGateBiasBw = floatTensor1D;
2853     ANeuralNetworksOperandType cellBiasBw = floatTensor1D;
2854     ANeuralNetworksOperandType outputGateBiasBw = floatTensor1D;
2855     ANeuralNetworksOperandType projWeightsBw = floatTensor2D;
2856     ANeuralNetworksOperandType projBiasBw = floatTensor1D;
2857     ANeuralNetworksOperandType outputStateInBw = floatTensor2D;
2858     ANeuralNetworksOperandType cellStateInBw = floatTensor2D;
2859     ANeuralNetworksOperandType auxInput = floatTensor3D;
2860     ANeuralNetworksOperandType auxInputToInputFw = floatTensor2D;
2861     ANeuralNetworksOperandType auxInputToForgetFw = floatTensor2D;
2862     ANeuralNetworksOperandType auxInputToCellFw = floatTensor2D;
2863     ANeuralNetworksOperandType auxInputToOutputFw = floatTensor2D;
2864     ANeuralNetworksOperandType auxInputToInputBw = floatTensor2D;
2865     ANeuralNetworksOperandType auxInputToForgetBw = floatTensor2D;
2866     ANeuralNetworksOperandType auxInputToCellBw = floatTensor2D;
2867     ANeuralNetworksOperandType auxInputToOutputBw = floatTensor2D;
2868     ANeuralNetworksOperandType activation = intScalar;
2869     ANeuralNetworksOperandType clipCellState = floatScalar;
2870     ANeuralNetworksOperandType clipProjLayer = floatScalar;
2871     ANeuralNetworksOperandType mergeOutputs = boolScalar;
2872     ANeuralNetworksOperandType timeMajor = boolScalar;
2873     ANeuralNetworksOperandType inputLayerNormWeightsFw = floatTensor1D;
2874     ANeuralNetworksOperandType forgetLayerNormWeightsFw = floatTensor1D;
2875     ANeuralNetworksOperandType cellLayerNormWeightsFw = floatTensor1D;
2876     ANeuralNetworksOperandType outputLayerNormWeightsFw = floatTensor1D;
2877     ANeuralNetworksOperandType inputLayerNormWeightsBw = floatTensor1D;
2878     ANeuralNetworksOperandType forgetLayerNormWeightsBw = floatTensor1D;
2879     ANeuralNetworksOperandType cellLayerNormWeightsBw = floatTensor1D;
2880     ANeuralNetworksOperandType outputLayerNormWeightsBw = floatTensor1D;
2881 
2882     ANeuralNetworksOperandType outputFw = floatTensor2D;
2883     ANeuralNetworksOperandType outputBw = floatTensor2D;
2884 
2885     OperationTestBase lstmTest(ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM,
2886                                {
2887                                        input,
2888                                        inputToInputFw,
2889                                        inputToForgetFw,
2890                                        inputToCellFw,
2891                                        inputToOutputFw,
2892                                        recurrentToInputFw,
2893                                        recurrentToForgetFw,
2894                                        recurrentToCellFw,
2895                                        recurrentToOutputFw,
2896                                        cellToInputFw,
2897                                        cellToForgetFw,
2898                                        cellToOutputFw,
2899                                        inputGateBiasFw,
2900                                        forgetGateBiasFw,
2901                                        cellBiasFw,
2902                                        outputGateBiasFw,
2903                                        projWeightsFw,
2904                                        projBiasFw,
2905                                        outputStateInFw,
2906                                        cellStateInFw,
2907                                        inputToInputBw,
2908                                        inputToForgetBw,
2909                                        inputToCellBw,
2910                                        inputToOutputBw,
2911                                        recurrentToInputBw,
2912                                        recurrentToForgetBw,
2913                                        recurrentToCellBw,
2914                                        recurrentToOutputBw,
2915                                        cellToInputBw,
2916                                        cellToForgetBw,
2917                                        cellToOutputBw,
2918                                        inputGateBiasBw,
2919                                        forgetGateBiasBw,
2920                                        cellBiasBw,
2921                                        outputGateBiasBw,
2922                                        projWeightsBw,
2923                                        projBiasBw,
2924                                        outputStateInBw,
2925                                        cellStateInBw,
2926                                        auxInput,
2927                                        auxInputToInputFw,
2928                                        auxInputToForgetFw,
2929                                        auxInputToCellFw,
2930                                        auxInputToOutputFw,
2931                                        auxInputToInputBw,
2932                                        auxInputToForgetBw,
2933                                        auxInputToCellBw,
2934                                        auxInputToOutputBw,
2935                                        activation,
2936                                        clipCellState,
2937                                        clipProjLayer,
2938                                        mergeOutputs,
2939                                        timeMajor,
2940                                        inputLayerNormWeightsFw,
2941                                        forgetLayerNormWeightsFw,
2942                                        cellLayerNormWeightsFw,
2943                                        outputLayerNormWeightsFw,
2944                                        inputLayerNormWeightsBw,
2945                                        forgetLayerNormWeightsBw,
2946                                        cellLayerNormWeightsBw,
2947                                        outputLayerNormWeightsBw,
2948                                },
2949                                {
2950                                        outputFw,
2951                                        outputBw,
2952                                });
2953 
2954     lstmTest.testOpsValidations();
2955 }
2956 
TEST(OperationValidationTest,LSTM_BIDIRECTIONAL_SEQUENCE)2957 TEST(OperationValidationTest, LSTM_BIDIRECTIONAL_SEQUENCE) {
2958     lstmBidirectionalSequence(ANEURALNETWORKS_TENSOR_FLOAT32);
2959     lstmBidirectionalSequence(ANEURALNETWORKS_TENSOR_FLOAT16);
2960 }
2961 
randomMultinomialOpTest(int32_t operandCode)2962 void randomMultinomialOpTest(int32_t operandCode) {
2963     uint32_t inputDims[2] = {5, 5};
2964     ANeuralNetworksOperandType input = {.type = operandCode,
2965                                         .dimensionCount = 2,
2966                                         .dimensions = inputDims,
2967                                         .scale = 0.0f,
2968                                         .zeroPoint = 0};
2969     ANeuralNetworksOperandType sample_count = {.type = ANEURALNETWORKS_INT32,
2970                                                .dimensionCount = 0,
2971                                                .dimensions = nullptr,
2972                                                .scale = 0.0f,
2973                                                .zeroPoint = 0};
2974     uint32_t seedDims[1] = {2};
2975     ANeuralNetworksOperandType seed = {.type = ANEURALNETWORKS_TENSOR_INT32,
2976                                        .dimensionCount = 1,
2977                                        .dimensions = seedDims,
2978                                        .scale = 0.0f,
2979                                        .zeroPoint = 0};
2980     uint32_t outputDims[2] = {5, 7};
2981     ANeuralNetworksOperandType output = {.type = ANEURALNETWORKS_TENSOR_INT32,
2982                                          .dimensionCount = 2,
2983                                          .dimensions = outputDims,
2984                                          .scale = 0.0f,
2985                                          .zeroPoint = 0};
2986 
2987     OperationTestBase multinomialTest(ANEURALNETWORKS_RANDOM_MULTINOMIAL,
2988                                       {input, sample_count, seed}, {output});
2989     multinomialTest.testOpsValidations();
2990 }
2991 
TEST(OperationValidationTest,RANDOM_MULTINOMIAL_float16)2992 TEST(OperationValidationTest, RANDOM_MULTINOMIAL_float16) {
2993     randomMultinomialOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
2994 }
2995 
TEST(OperationValidationTest,RANDOM_MULTINOMIAL_float32)2996 TEST(OperationValidationTest, RANDOM_MULTINOMIAL_float32) {
2997     randomMultinomialOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
2998 }
2999 
TEST(OperationValidationTest,RNN_float16)3000 TEST(OperationValidationTest, RNN_float16) {
3001     uint32_t oneDimensional[1] = {5};
3002     uint32_t twoDimensional[2] = {5, 5};
3003     ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3004                                                 .dimensionCount = 1,
3005                                                 .dimensions = oneDimensional,
3006                                                 .scale = 0.0f,
3007                                                 .zeroPoint = 0};
3008     ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3009                                                 .dimensionCount = 2,
3010                                                 .dimensions = twoDimensional,
3011                                                 .scale = 0.0f,
3012                                                 .zeroPoint = 0};
3013     ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3014                                             .dimensionCount = 0,
3015                                             .dimensions = nullptr,
3016                                             .scale = 0.0f,
3017                                             .zeroPoint = 0};
3018 
3019     ANeuralNetworksOperandType input = floatTensor2D;
3020     ANeuralNetworksOperandType weights = floatTensor2D;
3021     ANeuralNetworksOperandType recurrentWeights = floatTensor2D;
3022     ANeuralNetworksOperandType bias = floatTensor1D;
3023     ANeuralNetworksOperandType hiddenStateIn = floatTensor2D;
3024     ANeuralNetworksOperandType activation = intScalar;
3025 
3026     ANeuralNetworksOperandType hiddenStateOut = floatTensor2D;
3027     ANeuralNetworksOperandType output = floatTensor2D;
3028 
3029     OperationTestBase rnnTest(ANEURALNETWORKS_RNN,
3030                               {input, weights, recurrentWeights, bias, hiddenStateIn, activation},
3031                               {hiddenStateOut, output});
3032     rnnTest.testOpsValidations();
3033 }
3034 
TEST(OperationValidationTest,RNN_float32)3035 TEST(OperationValidationTest, RNN_float32) {
3036     uint32_t oneDimensional[1] = {5};
3037     uint32_t twoDimensional[2] = {5, 5};
3038     ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3039                                                 .dimensionCount = 1,
3040                                                 .dimensions = oneDimensional,
3041                                                 .scale = 0.0f,
3042                                                 .zeroPoint = 0};
3043     ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3044                                                 .dimensionCount = 2,
3045                                                 .dimensions = twoDimensional,
3046                                                 .scale = 0.0f,
3047                                                 .zeroPoint = 0};
3048     ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3049                                             .dimensionCount = 0,
3050                                             .dimensions = nullptr,
3051                                             .scale = 0.0f,
3052                                             .zeroPoint = 0};
3053 
3054     ANeuralNetworksOperandType input = floatTensor2D;
3055     ANeuralNetworksOperandType weights = floatTensor2D;
3056     ANeuralNetworksOperandType recurrentWeights = floatTensor2D;
3057     ANeuralNetworksOperandType bias = floatTensor1D;
3058     ANeuralNetworksOperandType hiddenStateIn = floatTensor2D;
3059     ANeuralNetworksOperandType activation = intScalar;
3060 
3061     ANeuralNetworksOperandType hiddenStateOut = floatTensor2D;
3062     ANeuralNetworksOperandType output = floatTensor2D;
3063 
3064     OperationTestBase rnnTest(ANEURALNETWORKS_RNN,
3065                               {input, weights, recurrentWeights, bias, hiddenStateIn, activation},
3066                               {hiddenStateOut, output});
3067     rnnTest.testOpsValidations();
3068 }
3069 
TEST(OperationValidationTest,SVDF_float32)3070 TEST(OperationValidationTest, SVDF_float32) {
3071     uint32_t oneDimensional[1] = {5};
3072     uint32_t twoDimensional[2] = {5, 5};
3073     ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3074                                                 .dimensionCount = 1,
3075                                                 .dimensions = oneDimensional,
3076                                                 .scale = 0.0f,
3077                                                 .zeroPoint = 0};
3078     ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT32,
3079                                                 .dimensionCount = 2,
3080                                                 .dimensions = twoDimensional,
3081                                                 .scale = 0.0f,
3082                                                 .zeroPoint = 0};
3083     ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3084                                             .dimensionCount = 0,
3085                                             .dimensions = nullptr,
3086                                             .scale = 0.0f,
3087                                             .zeroPoint = 0};
3088 
3089     ANeuralNetworksOperandType input = floatTensor2D;
3090     ANeuralNetworksOperandType weightsFeature = floatTensor2D;
3091     ANeuralNetworksOperandType weightsTime = floatTensor2D;
3092     ANeuralNetworksOperandType bias = floatTensor1D;
3093     ANeuralNetworksOperandType stateIn = floatTensor2D;
3094     ANeuralNetworksOperandType rank = intScalar;
3095     ANeuralNetworksOperandType activation = intScalar;
3096 
3097     ANeuralNetworksOperandType stateOut = floatTensor2D;
3098     ANeuralNetworksOperandType output = floatTensor2D;
3099 
3100     OperationTestBase svdfTest(
3101             ANEURALNETWORKS_SVDF,
3102             {input, weightsFeature, weightsTime, bias, stateIn, rank, activation},
3103             {stateOut, output});
3104     svdfTest.testOpsValidations();
3105 }
3106 
TEST(OperationValidationTest,SVDF_float16)3107 TEST(OperationValidationTest, SVDF_float16) {
3108     uint32_t oneDimensional[1] = {5};
3109     uint32_t twoDimensional[2] = {5, 5};
3110     ANeuralNetworksOperandType floatTensor1D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3111                                                 .dimensionCount = 1,
3112                                                 .dimensions = oneDimensional,
3113                                                 .scale = 0.0f,
3114                                                 .zeroPoint = 0};
3115     ANeuralNetworksOperandType floatTensor2D = {.type = ANEURALNETWORKS_TENSOR_FLOAT16,
3116                                                 .dimensionCount = 2,
3117                                                 .dimensions = twoDimensional,
3118                                                 .scale = 0.0f,
3119                                                 .zeroPoint = 0};
3120     ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
3121                                             .dimensionCount = 0,
3122                                             .dimensions = nullptr,
3123                                             .scale = 0.0f,
3124                                             .zeroPoint = 0};
3125 
3126     ANeuralNetworksOperandType input = floatTensor2D;
3127     ANeuralNetworksOperandType weightsFeature = floatTensor2D;
3128     ANeuralNetworksOperandType weightsTime = floatTensor2D;
3129     ANeuralNetworksOperandType bias = floatTensor1D;
3130     ANeuralNetworksOperandType stateIn = floatTensor2D;
3131     ANeuralNetworksOperandType rank = intScalar;
3132     ANeuralNetworksOperandType activation = intScalar;
3133 
3134     ANeuralNetworksOperandType stateOut = floatTensor2D;
3135     ANeuralNetworksOperandType output = floatTensor2D;
3136 
3137     OperationTestBase svdfTest(
3138             ANEURALNETWORKS_SVDF,
3139             {input, weightsFeature, weightsTime, bias, stateIn, rank, activation},
3140             {stateOut, output});
3141     svdfTest.testOpsValidations();
3142 }
3143 
stridedSliceOpTest(int32_t operandCode)3144 void stridedSliceOpTest(int32_t operandCode) {
3145     uint32_t inputDimensions[2] = {5, 5};
3146     ANeuralNetworksOperandType input = getOpType(operandCode, 2, inputDimensions);
3147     ANeuralNetworksOperandType output = input;
3148 
3149     uint32_t beginsDimensions[1] = {2};
3150     ANeuralNetworksOperandType begins = {.type = ANEURALNETWORKS_TENSOR_INT32,
3151                                          .dimensionCount = 1,
3152                                          .dimensions = beginsDimensions,
3153                                          .scale = 0.0f,
3154                                          .zeroPoint = 0};
3155 
3156     ANeuralNetworksOperandType ends = begins;
3157     ANeuralNetworksOperandType strides = begins;
3158 
3159     ANeuralNetworksOperandType beginMask = {.type = ANEURALNETWORKS_INT32,
3160                                             .dimensionCount = 0,
3161                                             .dimensions = nullptr,
3162                                             .scale = 0.0f,
3163                                             .zeroPoint = 0};
3164     ANeuralNetworksOperandType endMask = beginMask;
3165     ANeuralNetworksOperandType shrinkAxisMask = beginMask;
3166 
3167     OperationTestBase stridedSliceTest(
3168             ANEURALNETWORKS_STRIDED_SLICE,
3169             {input, begins, ends, strides, beginMask, endMask, shrinkAxisMask}, {output},
3170             {{TensorRankConstraint::UpTo(4)}});
3171     stridedSliceTest.testOpsValidations();
3172 }
3173 
TEST(OperationValidationTest,STRIDED_SLICE_float32)3174 TEST(OperationValidationTest, STRIDED_SLICE_float32) {
3175     stridedSliceOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3176 }
3177 
TEST(OperationValidationTest,STRIDED_SLICE_float16)3178 TEST(OperationValidationTest, STRIDED_SLICE_float16) {
3179     stridedSliceOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3180 }
3181 
TEST(OperationValidationTest,STRIDED_SLICE_quant8)3182 TEST(OperationValidationTest, STRIDED_SLICE_quant8) {
3183     stridedSliceOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3184 }
3185 
TEST(OperationValidationTest,STRIDED_SLICE_quant8_signed)3186 TEST(OperationValidationTest, STRIDED_SLICE_quant8_signed) {
3187     stridedSliceOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3188 }
3189 
roiAlignOpTest(int32_t inputOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)3190 void roiAlignOpTest(int32_t inputOperandCode, int32_t roiOperandCode, int32_t scalarOperandCode) {
3191     uint32_t inDim[] = {1, 4, 4, 1}, roiDim[] = {4, 4}, batchSplitDim[] = {1};
3192     uint32_t outDim[] = {4, 2, 2, 1};
3193     OperationTestBase roiAlignTest(
3194             ANEURALNETWORKS_ROI_ALIGN,
3195             {getOpType(inputOperandCode, 4, inDim), getOpType(roiOperandCode, 2, roiDim),
3196              getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, batchSplitDim),
3197              getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3198              getOpType(scalarOperandCode), getOpType(scalarOperandCode),
3199              getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3200              getOpType(ANEURALNETWORKS_BOOL)},
3201             {getOpType(inputOperandCode, 4, outDim)});
3202     roiAlignTest.testOpsValidations();
3203 }
3204 
TEST(OperationValidationTest,ROI_ALIGN_float16)3205 TEST(OperationValidationTest, ROI_ALIGN_float16) {
3206     roiAlignOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
3207                    ANEURALNETWORKS_FLOAT16);
3208 }
3209 
TEST(OperationValidationTest,ROI_ALIGN_float32)3210 TEST(OperationValidationTest, ROI_ALIGN_float32) {
3211     roiAlignOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
3212                    ANEURALNETWORKS_FLOAT32);
3213 }
3214 
TEST(OperationValidationTest,ROI_ALIGN_quant8)3215 TEST(OperationValidationTest, ROI_ALIGN_quant8) {
3216     roiAlignOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3217                    ANEURALNETWORKS_FLOAT32);
3218 }
3219 
TEST(OperationValidationTest,ROI_ALIGN_quant8signed)3220 TEST(OperationValidationTest, ROI_ALIGN_quant8signed) {
3221     roiAlignOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3222                    ANEURALNETWORKS_FLOAT32);
3223 }
3224 
roiPoolingOpTest(int32_t inputOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)3225 void roiPoolingOpTest(int32_t inputOperandCode, int32_t roiOperandCode, int32_t scalarOperandCode) {
3226     uint32_t inDim[] = {1, 4, 4, 1}, roiDim[] = {4, 4}, batchSplitDim[] = {1};
3227     uint32_t outDim[] = {4, 2, 2, 1};
3228     OperationTestBase roiPoolingTest(
3229             ANEURALNETWORKS_ROI_POOLING,
3230             {getOpType(inputOperandCode, 4, inDim), getOpType(roiOperandCode, 2, roiDim),
3231              getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, batchSplitDim),
3232              getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3233              getOpType(scalarOperandCode), getOpType(scalarOperandCode),
3234              getOpType(ANEURALNETWORKS_BOOL)},
3235             {getOpType(inputOperandCode, 4, outDim)});
3236     roiPoolingTest.testOpsValidations();
3237 }
3238 
TEST(OperationValidationTest,ROI_POOLING_float16)3239 TEST(OperationValidationTest, ROI_POOLING_float16) {
3240     roiPoolingOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
3241                      ANEURALNETWORKS_FLOAT16);
3242 }
3243 
TEST(OperationValidationTest,ROI_POOLING_float32)3244 TEST(OperationValidationTest, ROI_POOLING_float32) {
3245     roiPoolingOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
3246                      ANEURALNETWORKS_FLOAT32);
3247 }
3248 
TEST(OperationValidationTest,ROI_POOLING_quant8)3249 TEST(OperationValidationTest, ROI_POOLING_quant8) {
3250     roiPoolingOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3251                      ANEURALNETWORKS_FLOAT32);
3252 }
3253 
TEST(OperationValidationTest,ROI_POOLING_quant8signed)3254 TEST(OperationValidationTest, ROI_POOLING_quant8signed) {
3255     roiPoolingOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3256                      ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
3257 }
3258 
heatmapMaxKeypointOpTest(int32_t heatmapOperandCode,int32_t roiOperandCode)3259 void heatmapMaxKeypointOpTest(int32_t heatmapOperandCode, int32_t roiOperandCode) {
3260     uint32_t heatmapDim[] = {6, 4, 4, 1}, boxDim[] = {6, 4}, outScoreDim[] = {6, 1},
3261              outKeypointDim[] = {6, 1, 2};
3262     OperationTestBase heatmapMaxKeypointTest(
3263             ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT,
3264             {getOpType(heatmapOperandCode, 4, heatmapDim), getOpType(roiOperandCode, 2, boxDim),
3265              getOpType(ANEURALNETWORKS_BOOL)},
3266             {getOpType(heatmapOperandCode, 2, outScoreDim),
3267              getOpType(roiOperandCode, 3, outKeypointDim)});
3268     heatmapMaxKeypointTest.testOpsValidations();
3269 }
3270 
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_float16)3271 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_float16) {
3272     heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3273 }
3274 
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_float32)3275 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_float32) {
3276     heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3277 }
3278 
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_quant)3279 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_quant) {
3280     heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3281                              ANEURALNETWORKS_TENSOR_QUANT16_ASYMM);
3282 }
3283 
TEST(OperationValidationTest,HEATMAP_MAX_KEYPOINT_quant_signed)3284 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_quant_signed) {
3285     heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3286                              ANEURALNETWORKS_TENSOR_QUANT16_ASYMM);
3287 }
3288 
instanceNormalizationOpTest(int32_t inputOperandType)3289 void instanceNormalizationOpTest(int32_t inputOperandType) {
3290     SCOPED_TRACE(inputOperandType);
3291     uint32_t inputDims[4] = {4, 4, 4, 4};
3292     ANeuralNetworksOperandType input = getOpType(inputOperandType, 4, inputDims);
3293     ANeuralNetworksOperandType floatScalar = getOpType(ANEURALNETWORKS_FLOAT32);
3294     if (inputOperandType == ANEURALNETWORKS_TENSOR_FLOAT16) {
3295         floatScalar = getOpType(ANEURALNETWORKS_FLOAT16);
3296     }
3297     ANeuralNetworksOperandType gamma = floatScalar;
3298     ANeuralNetworksOperandType beta = floatScalar;
3299     ANeuralNetworksOperandType epsilon = floatScalar;
3300     ANeuralNetworksOperandType isNCHW = getOpType(ANEURALNETWORKS_BOOL);
3301     ANeuralNetworksOperandType output = input;
3302 
3303     OperationTestBase test(ANEURALNETWORKS_INSTANCE_NORMALIZATION,
3304                            {input, gamma, beta, epsilon, isNCHW}, {output});
3305     test.testOpsValidations();
3306 }
3307 
TEST(OperationValidationTest,INSTANCE_NORMALIZATION)3308 TEST(OperationValidationTest, INSTANCE_NORMALIZATION) {
3309     instanceNormalizationOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3310     instanceNormalizationOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3311 }
3312 
groupedConvOpTest(int32_t inputOperandCode,int32_t filterOperandCode)3313 void groupedConvOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
3314     uint32_t inDim[] = {1, 3, 3, 2}, filterDim[] = {2, 2, 2, 1}, biasDim[] = {2};
3315     uint32_t outDim[] = {1, 2, 2, 2};
3316     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inDim);
3317 
3318     float filterScales[2] = {0.5f, 1.0f};
3319     ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, filterDim);
3320 
3321     ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
3322             .channelDim = 0,
3323             .scaleCount = 2,
3324             .scales = filterScales,
3325     };
3326 
3327     ANeuralNetworksOperandType bias = getOpType(inputOperandCode, 1, biasDim);
3328     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
3329         filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
3330         bias.type = ANEURALNETWORKS_TENSOR_INT32;
3331         bias.scale = 0.25f;
3332     }
3333     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3334         bias.type = ANEURALNETWORKS_TENSOR_INT32;
3335         bias.scale = 0.0f;
3336     }
3337 
3338     ANeuralNetworksOperandType scalar = getOpType(ANEURALNETWORKS_INT32);
3339     ANeuralNetworksOperandType layout = getOpType(ANEURALNETWORKS_BOOL);
3340 
3341     ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outDim);
3342 
3343     OperationTestBase explicitGroupedConvTest(ANEURALNETWORKS_GROUPED_CONV_2D,
3344                                               {input, filter, bias, scalar, scalar, scalar, scalar,
3345                                                scalar, scalar, scalar, scalar, layout},
3346                                               {output});
3347     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3348         explicitGroupedConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3349     }
3350     explicitGroupedConvTest.testOpsValidations();
3351 
3352     OperationTestBase implicitGroupedConvTest(
3353             ANEURALNETWORKS_GROUPED_CONV_2D,
3354             {input, filter, bias, scalar, scalar, scalar, scalar, scalar, layout}, {output});
3355     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3356         implicitGroupedConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3357     }
3358     implicitGroupedConvTest.testOpsValidations();
3359 }
3360 
TEST(OperationValidationTest,GROUPED_CONV_2D_float16)3361 TEST(OperationValidationTest, GROUPED_CONV_2D_float16) {
3362     groupedConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3363 }
3364 
TEST(OperationValidationTest,GROUPED_CONV_2D_float32)3365 TEST(OperationValidationTest, GROUPED_CONV_2D_float32) {
3366     groupedConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3367 }
3368 
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8)3369 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8) {
3370     groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3371 }
3372 
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8_per_channel)3373 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8_per_channel) {
3374     groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3375                       ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3376 }
3377 
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8signed)3378 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8signed) {
3379     groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3380                       ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3381 }
3382 
TEST(OperationValidationTest,GROUPED_CONV_2D_quant8signed_per_channel)3383 TEST(OperationValidationTest, GROUPED_CONV_2D_quant8signed_per_channel) {
3384     groupedConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3385                       ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3386 }
3387 
transposeConvOpTest(int32_t inputOperandCode,int32_t filterOperandCode)3388 void transposeConvOpTest(int32_t inputOperandCode, int32_t filterOperandCode) {
3389     uint32_t inDim[] = {1, 2, 2, 2}, filterDim[] = {2, 3, 3, 1}, biasDim[] = {2};
3390     uint32_t outDim[] = {1, 5, 5, 2}, outShapeDim[] = {4};
3391     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 4, inDim);
3392     ANeuralNetworksOperandType filter = getOpType(filterOperandCode, 4, filterDim);
3393 
3394     float filterScales[2] = {0.5f, 1.0f};
3395     ANeuralNetworksSymmPerChannelQuantParams filterChannelQuantParams = {
3396             .channelDim = 0,
3397             .scaleCount = 2,
3398             .scales = filterScales,
3399     };
3400 
3401     ANeuralNetworksOperandType bias = getOpType(inputOperandCode, 1, biasDim);
3402     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM ||
3403         filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED) {
3404         bias.type = ANEURALNETWORKS_TENSOR_INT32;
3405         bias.scale = 0.25f;
3406     }
3407     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3408         bias.type = ANEURALNETWORKS_TENSOR_INT32;
3409         bias.scale = 0.0f;
3410     }
3411 
3412     ANeuralNetworksOperandType scalar = getOpType(ANEURALNETWORKS_INT32);
3413     ANeuralNetworksOperandType layout = getOpType(ANEURALNETWORKS_BOOL);
3414     ANeuralNetworksOperandType output = getOpType(inputOperandCode, 4, outDim);
3415 
3416     OperationTestBase explicitTransposeConvTest(
3417             ANEURALNETWORKS_TRANSPOSE_CONV_2D,
3418             {input, filter, bias, scalar, scalar, scalar, scalar, scalar, scalar, scalar, layout},
3419             {output});
3420     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3421         explicitTransposeConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3422     }
3423     explicitTransposeConvTest.testOpsValidations();
3424 
3425     OperationTestBase implicitTransposeConvTest(
3426             ANEURALNETWORKS_TRANSPOSE_CONV_2D,
3427             {input, filter, bias, getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outShapeDim), scalar,
3428              scalar, scalar, scalar, layout},
3429             {output});
3430     if (filterOperandCode == ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL) {
3431         implicitTransposeConvTest.setInputSymmPerChannelQuantParams(1, filterChannelQuantParams);
3432     }
3433     implicitTransposeConvTest.testOpsValidations();
3434 }
3435 
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_float16)3436 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_float16) {
3437     transposeConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3438 }
3439 
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_float32)3440 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_float32) {
3441     transposeConvOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3442 }
3443 
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8)3444 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8) {
3445     transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3446 }
3447 
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8_per_channel)3448 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8_per_channel) {
3449     transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3450                         ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3451 }
3452 
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8_signed)3453 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8_signed) {
3454     transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3455                         ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3456 }
3457 
TEST(OperationValidationTest,TRANSPOSE_CONV_2D_quant8_signed_per_channel)3458 TEST(OperationValidationTest, TRANSPOSE_CONV_2D_quant8_signed_per_channel) {
3459     transposeConvOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3460                         ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL);
3461 }
3462 
channelShuffleOpTest(int32_t operandCode)3463 void channelShuffleOpTest(int32_t operandCode) {
3464     uint32_t inoutDim[] = {2, 2, 3, 12};
3465     OperationTestBase channelShuffleTest(
3466             ANEURALNETWORKS_CHANNEL_SHUFFLE,
3467             {getOpType(operandCode, 2, inoutDim), getOpType(ANEURALNETWORKS_INT32),
3468              getOpType(ANEURALNETWORKS_INT32)},
3469             {getOpType(operandCode, 2, inoutDim)}, {{TensorRankConstraint::UpTo(4)}});
3470     channelShuffleTest.testOpsValidations();
3471 }
3472 
TEST(OperationValidationTest,CHANNEL_SHUFFLE_float16)3473 TEST(OperationValidationTest, CHANNEL_SHUFFLE_float16) {
3474     channelShuffleOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3475 }
3476 
TEST(OperationValidationTest,CHANNEL_SHUFFLE_float32)3477 TEST(OperationValidationTest, CHANNEL_SHUFFLE_float32) {
3478     channelShuffleOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3479 }
3480 
TEST(OperationValidationTest,CHANNEL_SHUFFLE_quant8)3481 TEST(OperationValidationTest, CHANNEL_SHUFFLE_quant8) {
3482     channelShuffleOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3483 }
3484 
TEST(OperationValidationTest,CHANNEL_SHUFFLE_quant8signed)3485 TEST(OperationValidationTest, CHANNEL_SHUFFLE_quant8signed) {
3486     channelShuffleOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3487 }
3488 
detectionPostprocessingOpTest(int32_t inputOperandCode)3489 void detectionPostprocessingOpTest(int32_t inputOperandCode) {
3490     SCOPED_TRACE(inputOperandCode);
3491     const int numBatches = 2;
3492     const int numAnchors = 10;
3493     const int numClasses = 5;
3494     const int lengthBoxEncoding = 4;
3495 
3496     uint32_t inputDims[3] = {numBatches, numAnchors, numClasses};
3497     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDims);
3498     uint32_t deltasDims[3] = {numBatches, numAnchors, lengthBoxEncoding};
3499     ANeuralNetworksOperandType deltas = getOpType(inputOperandCode, 3, deltasDims);
3500     uint32_t anchorsDims[2] = {numAnchors, 4};
3501     ANeuralNetworksOperandType anchors = getOpType(inputOperandCode, 2, anchorsDims);
3502     ANeuralNetworksOperandType scaleScalar = getOpType(ANEURALNETWORKS_FLOAT32);
3503     if (inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT16) {
3504         scaleScalar = getOpType(ANEURALNETWORKS_FLOAT16);
3505     }
3506     ANeuralNetworksOperandType isRegularNMS = getOpType(ANEURALNETWORKS_BOOL);
3507     ANeuralNetworksOperandType maxNumDetections = getOpType(ANEURALNETWORKS_INT32);
3508     ANeuralNetworksOperandType numOfClassesPerDetection = maxNumDetections;
3509     ANeuralNetworksOperandType numOfDetections = numOfClassesPerDetection;
3510     ANeuralNetworksOperandType scoreThreshold = scaleScalar;
3511     ANeuralNetworksOperandType iouThreshold = scaleScalar;
3512     ANeuralNetworksOperandType includeBackground = getOpType(ANEURALNETWORKS_BOOL);
3513     // Outputs
3514     const int maxNumDetectionsValue = 5;
3515     uint32_t outputScoreDims[2] = {numBatches, maxNumDetectionsValue};
3516     ANeuralNetworksOperandType outputScore = getOpType(inputOperandCode, 2, outputScoreDims);
3517     uint32_t boundingBoxesDims[3] = {numBatches, maxNumDetectionsValue, 4};
3518     ANeuralNetworksOperandType boundingBoxes = getOpType(inputOperandCode, 3, boundingBoxesDims);
3519     ANeuralNetworksOperandType classLabel =
3520             getOpType(ANEURALNETWORKS_TENSOR_INT32, 2, outputScoreDims);
3521     uint32_t numValidDims[1] = {numBatches};
3522     ANeuralNetworksOperandType numValid = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, numValidDims);
3523 
3524     OperationTestBase test(ANEURALNETWORKS_DETECTION_POSTPROCESSING,
3525                            {input, deltas, anchors, scaleScalar, scaleScalar, scaleScalar,
3526                             scaleScalar, isRegularNMS, maxNumDetections, numOfClassesPerDetection,
3527                             numOfDetections, scoreThreshold, iouThreshold, includeBackground},
3528                            {outputScore, boundingBoxes, classLabel, numValid});
3529     test.testOpsValidations();
3530 }
3531 
TEST(OperationValidationTest,DETECTION_POSTPROCESSING)3532 TEST(OperationValidationTest, DETECTION_POSTPROCESSING) {
3533     detectionPostprocessingOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3534     detectionPostprocessingOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3535 }
3536 
preluOpTest(int32_t operandCode)3537 void preluOpTest(int32_t operandCode) {
3538     uint32_t inoutDim[] = {1, 2, 2, 3}, alphaDim[] = {1, 1, 3};
3539     OperationTestBase preluTest(
3540             ANEURALNETWORKS_PRELU,
3541             {getOpType(operandCode, 4, inoutDim), getOpType(operandCode, 3, alphaDim)},
3542             {getOpType(operandCode, 4, inoutDim)});
3543     preluTest.testOpsValidations();
3544 }
3545 
TEST(OperationValidationTest,PRELU_float16)3546 TEST(OperationValidationTest, PRELU_float16) {
3547     preluOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3548 }
3549 
TEST(OperationValidationTest,PRELU_float32)3550 TEST(OperationValidationTest, PRELU_float32) {
3551     preluOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3552 }
3553 
TEST(OperationValidationTest,PRELU_quant8)3554 TEST(OperationValidationTest, PRELU_quant8) {
3555     preluOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3556 }
3557 
TEST(OperationValidationTest,PRELU_quant8signed)3558 TEST(OperationValidationTest, PRELU_quant8signed) {
3559     preluOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3560 }
3561 
normalizationOpTest(ANeuralNetworksOperationType operationCode,int32_t operandCode)3562 void normalizationOpTest(ANeuralNetworksOperationType operationCode, int32_t operandCode) {
3563     uint32_t inputDim[] = {2, 2, 2, 2};
3564     OperationTestBase normalizationTest(operationCode, {getOpType(operandCode, 4, inputDim)},
3565                                         {getOpType(operandCode, 4, inputDim)});
3566     normalizationTest.testOpsValidations();
3567 
3568     OperationTestBase normalizationAxisTest(
3569             operationCode, {getOpType(operandCode, 4, inputDim), getOpType(ANEURALNETWORKS_INT32)},
3570             {getOpType(operandCode, 4, inputDim)}, {{TensorRankConstraint::UpTo(4)}});
3571     normalizationAxisTest.testOpsValidations();
3572 }
3573 
TEST(OperationValidationTest,L2_NORMALIZATION_float16)3574 TEST(OperationValidationTest, L2_NORMALIZATION_float16) {
3575     normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION, ANEURALNETWORKS_TENSOR_FLOAT16);
3576 }
3577 
TEST(OperationValidationTest,L2_NORMALIZATION_float32)3578 TEST(OperationValidationTest, L2_NORMALIZATION_float32) {
3579     normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION, ANEURALNETWORKS_TENSOR_FLOAT32);
3580 }
3581 
TEST(OperationValidationTest,L2_NORMALIZATION_quant8)3582 TEST(OperationValidationTest, L2_NORMALIZATION_quant8) {
3583     normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3584 }
3585 
TEST(OperationValidationTest,L2_NORMALIZATION_quant8_signed)3586 TEST(OperationValidationTest, L2_NORMALIZATION_quant8_signed) {
3587     normalizationOpTest(ANEURALNETWORKS_L2_NORMALIZATION,
3588                         ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3589 }
3590 
localResponseNormOpTest(int32_t operandCode)3591 void localResponseNormOpTest(int32_t operandCode) {
3592     int32_t floatScalarType = (operandCode == ANEURALNETWORKS_TENSOR_FLOAT32)
3593                                       ? ANEURALNETWORKS_FLOAT32
3594                                       : ANEURALNETWORKS_FLOAT16;
3595     uint32_t inputDim[] = {2, 2, 2, 6};
3596     OperationTestBase lrnTest(
3597             ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION,
3598             {getOpType(operandCode, 4, inputDim), getOpType(ANEURALNETWORKS_INT32),
3599              getOpType(floatScalarType), getOpType(floatScalarType), getOpType(floatScalarType)},
3600             {getOpType(operandCode, 4, inputDim)}, {{TensorRankConstraint::UpTo(4), {0}}});
3601     lrnTest.testOpsValidations();
3602 
3603     OperationTestBase lrnAxisTest(
3604             ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION,
3605             {getOpType(operandCode, 4, inputDim), getOpType(ANEURALNETWORKS_INT32),
3606              getOpType(floatScalarType), getOpType(floatScalarType), getOpType(floatScalarType),
3607              getOpType(ANEURALNETWORKS_INT32)},
3608             {getOpType(operandCode, 4, inputDim)}, {{TensorRankConstraint::UpTo(4), {0}}});
3609     lrnAxisTest.testOpsValidations();
3610 }
3611 
TEST(OperationValidationTest,LOCAL_RESPONSE_NORMALIZATION_float16)3612 TEST(OperationValidationTest, LOCAL_RESPONSE_NORMALIZATION_float16) {
3613     localResponseNormOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3614 }
3615 
TEST(OperationValidationTest,LOCAL_RESPONSE_NORMALIZATION_float32)3616 TEST(OperationValidationTest, LOCAL_RESPONSE_NORMALIZATION_float32) {
3617     localResponseNormOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3618 }
3619 
axisAlignedBBoxTransformOpTest(int32_t roiOperandCode,int32_t deltaOperandCode)3620 void axisAlignedBBoxTransformOpTest(int32_t roiOperandCode, int32_t deltaOperandCode) {
3621     uint32_t roiDim[] = {5, 4}, deltaDim[] = {5, 8}, bsDim[] = {5}, imageDim[] = {5, 2};
3622     uint32_t outDim[] = {5, 8};
3623     OperationTestBase axisAlignedBBoxTransformTest(
3624             ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM,
3625             {getOpType(roiOperandCode, 2, roiDim), getOpType(deltaOperandCode, 2, deltaDim),
3626              getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, bsDim),
3627              getOpType(roiOperandCode, 2, imageDim)},
3628             {getOpType(roiOperandCode, 2, outDim)});
3629     axisAlignedBBoxTransformTest.testOpsValidations();
3630 }
3631 
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_float16)3632 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_float16) {
3633     axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
3634 }
3635 
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_float32)3636 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_float32) {
3637     axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
3638 }
3639 
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_quant)3640 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_quant) {
3641     axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3642                                    ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3643 }
3644 
TEST(OperationValidationTest,AXIS_ALIGNED_BBOX_TRANSFORM_quant_signed)3645 TEST(OperationValidationTest, AXIS_ALIGNED_BBOX_TRANSFORM_quant_signed) {
3646     axisAlignedBBoxTransformOpTest(ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3647                                    ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3648 }
3649 
sliceTest(int32_t operandCode)3650 void sliceTest(int32_t operandCode) {
3651     uint32_t inputDim[] = {3, 3, 3};
3652     uint32_t startDim[] = {3};
3653     uint32_t sizeDim[] = {3};
3654     uint32_t outputDim[] = {1, 2, 3};
3655 
3656     OperationTestBase sliceTest(ANEURALNETWORKS_SLICE,
3657                                 {getOpType(operandCode, 3, inputDim),
3658                                  getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, startDim),
3659                                  getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, sizeDim)},
3660                                 {getOpType(operandCode, 3, outputDim)});
3661     sliceTest.testOpsValidations();
3662 }
3663 
TEST(OperationValidationTest,SLICE_float32)3664 TEST(OperationValidationTest, SLICE_float32) {
3665     sliceTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3666 }
TEST(OperationValidationTest,SLICE_int32)3667 TEST(OperationValidationTest, SLICE_int32) {
3668     sliceTest(ANEURALNETWORKS_TENSOR_INT32);
3669 }
TEST(OperationValidationTest,SLICE_uint8)3670 TEST(OperationValidationTest, SLICE_uint8) {
3671     sliceTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3672 }
TEST(OperationValidationTest,SLICE_int8)3673 TEST(OperationValidationTest, SLICE_int8) {
3674     sliceTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3675 }
TEST(OperationValidationTest,SLICE_float16)3676 TEST(OperationValidationTest, SLICE_float16) {
3677     sliceTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3678 }
3679 
logicalTest(ANeuralNetworksOperationType operationCode)3680 void logicalTest(ANeuralNetworksOperationType operationCode) {
3681     uint32_t inputDimensions[4] = {2, 2, 2, 2};
3682     ANeuralNetworksOperandType input1 = {.type = ANEURALNETWORKS_TENSOR_BOOL8,
3683                                          .dimensionCount = 4,
3684                                          .dimensions = inputDimensions,
3685                                          .scale = 0.0f,
3686                                          .zeroPoint = 0};
3687     ANeuralNetworksOperandType input2 = input1;
3688     ANeuralNetworksOperandType output = input1;
3689 
3690     OperationTestBase test(operationCode, {input1, input2}, {output});
3691     test.testOpsValidations();
3692 }
3693 
TEST(OperationValidationTest,LOGICAL_AND)3694 TEST(OperationValidationTest, LOGICAL_AND) {
3695     logicalTest(ANEURALNETWORKS_LOGICAL_AND);
3696 }
3697 
TEST(OperationValidationTest,LOGICAL_OR)3698 TEST(OperationValidationTest, LOGICAL_OR) {
3699     logicalTest(ANEURALNETWORKS_LOGICAL_OR);
3700 }
3701 
comparisonTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)3702 void comparisonTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
3703     uint32_t inputDimensions[4] = {2, 2, 2, 2};
3704     ANeuralNetworksOperandType input1 = getOpType(inputOperandType, 4, inputDimensions);
3705     ANeuralNetworksOperandType input2 = input1;
3706     ANeuralNetworksOperandType output = {.type = ANEURALNETWORKS_TENSOR_BOOL8,
3707                                          .dimensionCount = 4,
3708                                          .dimensions = inputDimensions,
3709                                          .scale = 0.0f,
3710                                          .zeroPoint = 0};
3711     OperationTestBase test(operationCode, {input1, input2}, {output});
3712     test.testOpsValidations();
3713 }
3714 
TEST(OperationValidationTest,LESS)3715 TEST(OperationValidationTest, LESS) {
3716     comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_BOOL8);
3717     comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_FLOAT16);
3718     comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_FLOAT32);
3719     comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_INT32);
3720     comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3721     comparisonTest(ANEURALNETWORKS_LESS, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3722 }
3723 
TEST(OperationValidationTest,LESS_EQUAL)3724 TEST(OperationValidationTest, LESS_EQUAL) {
3725     comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3726     comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3727     comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3728     comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3729     comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3730     comparisonTest(ANEURALNETWORKS_LESS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3731 }
3732 
TEST(OperationValidationTest,EQUAL)3733 TEST(OperationValidationTest, EQUAL) {
3734     comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3735     comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3736     comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3737     comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3738     comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3739     comparisonTest(ANEURALNETWORKS_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3740 }
3741 
TEST(OperationValidationTest,NOT_EQUAL)3742 TEST(OperationValidationTest, NOT_EQUAL) {
3743     comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3744     comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3745     comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3746     comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3747     comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3748     comparisonTest(ANEURALNETWORKS_NOT_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3749 }
3750 
TEST(OperationValidationTest,GREATER)3751 TEST(OperationValidationTest, GREATER) {
3752     comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_BOOL8);
3753     comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_FLOAT16);
3754     comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_FLOAT32);
3755     comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_INT32);
3756     comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3757     comparisonTest(ANEURALNETWORKS_GREATER, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3758 }
3759 
TEST(OperationValidationTest,GREATER_EQUAL)3760 TEST(OperationValidationTest, GREATER_EQUAL) {
3761     comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_BOOL8);
3762     comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT16);
3763     comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_FLOAT32);
3764     comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_INT32);
3765     comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3766     comparisonTest(ANEURALNETWORKS_GREATER_EQUAL, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3767 }
3768 
reduceOpTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)3769 void reduceOpTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
3770     uint32_t inputDimensions[4] = {2, 2, 2, 2};
3771     ANeuralNetworksOperandType input1 = getOpType(inputOperandType, 4, inputDimensions);
3772     uint32_t axesDimensions[1] = {2};
3773     ANeuralNetworksOperandType input2 = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, axesDimensions);
3774     ANeuralNetworksOperandType input3 = getOpType(ANEURALNETWORKS_BOOL, 0);
3775     ANeuralNetworksOperandType output = getOpType(inputOperandType, 4, inputDimensions);
3776     OperationTestBase test(operationCode, {input1, input2, input3}, {output},
3777                            {{TensorRankConstraint::UpTo(4)}});
3778     test.testOpsValidations();
3779 }
3780 
TEST(OperationValidationTest,REDUCE_PROD)3781 TEST(OperationValidationTest, REDUCE_PROD) {
3782     reduceOpTest(ANEURALNETWORKS_REDUCE_PROD, ANEURALNETWORKS_TENSOR_FLOAT16);
3783     reduceOpTest(ANEURALNETWORKS_REDUCE_PROD, ANEURALNETWORKS_TENSOR_FLOAT32);
3784 }
3785 
TEST(OperationValidationTest,REDUCE_SUM)3786 TEST(OperationValidationTest, REDUCE_SUM) {
3787     reduceOpTest(ANEURALNETWORKS_REDUCE_SUM, ANEURALNETWORKS_TENSOR_FLOAT16);
3788     reduceOpTest(ANEURALNETWORKS_REDUCE_SUM, ANEURALNETWORKS_TENSOR_FLOAT32);
3789 }
3790 
TEST(OperationValidationTest,REDUCE_MAX)3791 TEST(OperationValidationTest, REDUCE_MAX) {
3792     reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_FLOAT16);
3793     reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_FLOAT32);
3794     reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3795     reduceOpTest(ANEURALNETWORKS_REDUCE_MAX, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3796 }
3797 
TEST(OperationValidationTest,REDUCE_MIN)3798 TEST(OperationValidationTest, REDUCE_MIN) {
3799     reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_FLOAT16);
3800     reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_FLOAT32);
3801     reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3802     reduceOpTest(ANEURALNETWORKS_REDUCE_MIN, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3803 }
3804 
TEST(OperationValidationTest,REDUCE_ANY)3805 TEST(OperationValidationTest, REDUCE_ANY) {
3806     reduceOpTest(ANEURALNETWORKS_REDUCE_ANY, ANEURALNETWORKS_TENSOR_BOOL8);
3807 }
3808 
TEST(OperationValidationTest,REDUCE_ALL)3809 TEST(OperationValidationTest, REDUCE_ALL) {
3810     reduceOpTest(ANEURALNETWORKS_REDUCE_ALL, ANEURALNETWORKS_TENSOR_BOOL8);
3811 }
3812 
selectTest(ANeuralNetworksOperationType operationCode,int32_t inputOperandType)3813 void selectTest(ANeuralNetworksOperationType operationCode, int32_t inputOperandType) {
3814     uint32_t inputDimensions[4] = {2, 2, 2, 2};
3815     ANeuralNetworksOperandType input0 = getOpType(ANEURALNETWORKS_TENSOR_BOOL8, 4, inputDimensions);
3816     ANeuralNetworksOperandType input1 = getOpType(inputOperandType, 4, inputDimensions);
3817     ANeuralNetworksOperandType input2 = input1;
3818     ANeuralNetworksOperandType output = input1;
3819 
3820     OperationTestBase test(operationCode, {input0, input1, input2}, {output});
3821     test.testOpsValidations();
3822 }
3823 
TEST(OperationValidationTest,SELECT)3824 TEST(OperationValidationTest, SELECT) {
3825     selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_FLOAT16);
3826     selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_FLOAT32);
3827     selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_INT32);
3828     selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
3829     selectTest(ANEURALNETWORKS_SELECT, ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
3830 }
3831 
powTest(int32_t inputOperandType)3832 void powTest(int32_t inputOperandType) {
3833     const uint32_t inputDimensions[] = {3, 3};
3834     ANeuralNetworksOperandType inputType = {.type = inputOperandType,
3835                                             .dimensionCount = 2,
3836                                             .dimensions = inputDimensions,
3837                                             .scale = 0.0f,
3838                                             .zeroPoint = 0};
3839 
3840     OperationTestBase test(ANEURALNETWORKS_POW, {inputType, inputType}, {inputType});
3841     test.testOpsValidations();
3842 }
3843 
TEST(OperationValidationTest,POW)3844 TEST(OperationValidationTest, POW) {
3845     powTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3846     powTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3847 }
3848 
boxWithNmsLimitOpTest(int32_t scoreOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)3849 void boxWithNmsLimitOpTest(int32_t scoreOperandCode, int32_t roiOperandCode,
3850                            int32_t scalarOperandCode) {
3851     uint32_t scoreDim[] = {19, 3}, roiDim[] = {19, 12}, splitDim[] = {2};
3852     uint32_t outScoreDim[] = {12}, outRoiDim[] = {12, 4}, outClassDim[] = {12}, outSplitDim[] = {2};
3853     OperationTestBase boxWithNmsLimitTest(
3854             ANEURALNETWORKS_BOX_WITH_NMS_LIMIT,
3855             {getOpType(scoreOperandCode, 2, scoreDim), getOpType(roiOperandCode, 2, roiDim),
3856              getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, splitDim), getOpType(scalarOperandCode),
3857              getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
3858              getOpType(scalarOperandCode), getOpType(scalarOperandCode),
3859              getOpType(scalarOperandCode)},
3860             {getOpType(scoreOperandCode, 1, outScoreDim), getOpType(roiOperandCode, 2, outRoiDim),
3861              getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outClassDim),
3862              getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outSplitDim)});
3863     boxWithNmsLimitTest.testOpsValidations();
3864 }
3865 
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_float16)3866 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_float16) {
3867     boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
3868                           ANEURALNETWORKS_FLOAT16);
3869 }
3870 
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_float32)3871 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_float32) {
3872     boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
3873                           ANEURALNETWORKS_FLOAT32);
3874 }
3875 
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_quant)3876 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_quant) {
3877     boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3878                           ANEURALNETWORKS_FLOAT32);
3879 }
3880 
TEST(OperationValidationTest,BOX_WITH_NMS_LIMIT_quant_signed)3881 TEST(OperationValidationTest, BOX_WITH_NMS_LIMIT_quant_signed) {
3882     boxWithNmsLimitOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3883                           ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
3884 }
3885 
castOpTest(int32_t inputOperandCode,int32_t outputOperandCode)3886 void castOpTest(int32_t inputOperandCode, int32_t outputOperandCode) {
3887     SCOPED_TRACE(testing::Message()
3888                  << "inputType: " << inputOperandCode << ", outputType: " << outputOperandCode);
3889     uint32_t inputDimensions[3] = {2, 2, 2};
3890     ANeuralNetworksOperandType input = getOpType(inputOperandCode, 3, inputDimensions);
3891     ANeuralNetworksOperandType output = getOpType(outputOperandCode, 3, inputDimensions);
3892     OperationTestBase test(ANEURALNETWORKS_CAST, {input}, {output});
3893     test.testOpsValidations();
3894 }
3895 
TEST(OperationValidationTest,CAST)3896 TEST(OperationValidationTest, CAST) {
3897     std::vector<int32_t> inputTypes = {ANEURALNETWORKS_TENSOR_FLOAT16,
3898                                        ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_INT32,
3899                                        ANEURALNETWORKS_TENSOR_QUANT8_ASYMM};
3900     std::vector<int32_t> outputTypes = inputTypes;
3901     for (auto inputType : inputTypes) {
3902         for (auto outputType : outputTypes) {
3903             castOpTest(inputType, outputType);
3904         }
3905     }
3906 }
3907 
TEST(OperationValidationTest,CAST_identity)3908 TEST(OperationValidationTest, CAST_identity) {
3909     std::vector<int32_t> inputTypes = {
3910             ANEURALNETWORKS_TENSOR_FLOAT32,
3911             ANEURALNETWORKS_TENSOR_INT32,
3912             ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
3913             ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
3914             ANEURALNETWORKS_TENSOR_FLOAT16,
3915             ANEURALNETWORKS_TENSOR_BOOL8,
3916             ANEURALNETWORKS_TENSOR_QUANT16_ASYMM,
3917             ANEURALNETWORKS_TENSOR_QUANT8_SYMM,
3918             ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
3919     };
3920     for (auto inputType : inputTypes) {
3921         castOpTest(inputType, inputType);
3922     }
3923 }
3924 
bidirectionlSequenceRNNTest(int32_t inputOperandCode)3925 void bidirectionlSequenceRNNTest(int32_t inputOperandCode) {
3926     const uint32_t batchSize = 2;
3927     const uint32_t maxTime = 3;
3928     const uint32_t inputSize = 4;
3929     const uint32_t numUnits = 5;
3930 
3931     uint32_t inputDims[3] = {maxTime, batchSize, inputSize};
3932     uint32_t weightsDims[2] = {inputSize, numUnits};
3933     uint32_t recurrentWeightsDims[2] = {numUnits, numUnits};
3934     uint32_t biasDims[1] = {numUnits};
3935     uint32_t hiddenStateDims[2] = {batchSize, numUnits};
3936     uint32_t outputDims[2] = {batchSize, numUnits};
3937 
3938     ANeuralNetworksOperandType input = {.type = inputOperandCode,
3939                                         .dimensionCount = 3,
3940                                         .dimensions = inputDims,
3941                                         .scale = 0.0f,
3942                                         .zeroPoint = 0};
3943     ANeuralNetworksOperandType fwWeights = {.type = inputOperandCode,
3944                                             .dimensionCount = 2,
3945                                             .dimensions = weightsDims,
3946                                             .scale = 0.0f,
3947                                             .zeroPoint = 0};
3948     ANeuralNetworksOperandType bwWeights = fwWeights;
3949     ANeuralNetworksOperandType fwRecurrentWeights = {.type = inputOperandCode,
3950                                                      .dimensionCount = 2,
3951                                                      .dimensions = recurrentWeightsDims,
3952                                                      .scale = 0.0f,
3953                                                      .zeroPoint = 0};
3954     ANeuralNetworksOperandType bwRecurrentWeights = fwRecurrentWeights;
3955     ANeuralNetworksOperandType fwBias = {.type = inputOperandCode,
3956                                          .dimensionCount = 1,
3957                                          .dimensions = biasDims,
3958                                          .scale = 0.0f,
3959                                          .zeroPoint = 0};
3960     ANeuralNetworksOperandType bwBias = fwBias;
3961     ANeuralNetworksOperandType fwHiddenState = {.type = inputOperandCode,
3962                                                 .dimensionCount = 2,
3963                                                 .dimensions = hiddenStateDims,
3964                                                 .scale = 0.0f,
3965                                                 .zeroPoint = 0};
3966     ANeuralNetworksOperandType bwHiddenState = fwHiddenState;
3967     ANeuralNetworksOperandType output = {.type = inputOperandCode,
3968                                          .dimensionCount = 2,
3969                                          .dimensions = outputDims,
3970                                          .scale = 0.0f,
3971                                          .zeroPoint = 0};
3972     ANeuralNetworksOperandType activation = {.type = ANEURALNETWORKS_INT32,
3973                                              .dimensionCount = 0,
3974                                              .dimensions = nullptr,
3975                                              .scale = 0.0f,
3976                                              .zeroPoint = 0};
3977     ANeuralNetworksOperandType boolScalar = {.type = ANEURALNETWORKS_BOOL,
3978                                              .dimensionCount = 0,
3979                                              .dimensions = nullptr,
3980                                              .scale = 0.0f,
3981                                              .zeroPoint = 0};
3982     ANeuralNetworksOperandType timeMajor = boolScalar;
3983     ANeuralNetworksOperandType mergeOutputs = boolScalar;
3984 
3985     OperationTestBase rnnTest(ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN,
3986                               {input, fwWeights, fwRecurrentWeights, fwBias, fwHiddenState,
3987                                bwWeights, bwRecurrentWeights, bwBias, bwHiddenState, input,
3988                                fwWeights, bwWeights, activation, timeMajor, mergeOutputs},
3989                               {output, output});
3990     rnnTest.testOpsValidations();
3991 }
3992 
TEST(OperationValidationTest,BIDIRECTIONAL_SEQUENCE_RNN_float32)3993 TEST(OperationValidationTest, BIDIRECTIONAL_SEQUENCE_RNN_float32) {
3994     bidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT32);
3995 }
3996 
TEST(OperationValidationTest,BIDIRECTIONAL_SEQUENCE_RNN_float16)3997 TEST(OperationValidationTest, BIDIRECTIONAL_SEQUENCE_RNN_float16) {
3998     bidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT16);
3999 }
4000 
unidirectionlSequenceRNNTest(int32_t inputOperandCode)4001 void unidirectionlSequenceRNNTest(int32_t inputOperandCode) {
4002     const uint32_t batchSize = 2;
4003     const uint32_t maxTime = 3;
4004     const uint32_t inputSize = 4;
4005     const uint32_t numUnits = 5;
4006 
4007     uint32_t inputDims[3] = {maxTime, batchSize, inputSize};
4008     uint32_t weightsDims[2] = {inputSize, numUnits};
4009     uint32_t recurrentWeightsDims[2] = {numUnits, numUnits};
4010     uint32_t biasDims[1] = {numUnits};
4011     uint32_t hiddenStateDims[2] = {batchSize, numUnits};
4012     uint32_t outputDims[2] = {batchSize, numUnits};
4013 
4014     ANeuralNetworksOperandType input = {.type = inputOperandCode,
4015                                         .dimensionCount = 3,
4016                                         .dimensions = inputDims,
4017                                         .scale = 0.0f,
4018                                         .zeroPoint = 0};
4019     ANeuralNetworksOperandType weights = {.type = inputOperandCode,
4020                                           .dimensionCount = 2,
4021                                           .dimensions = weightsDims,
4022                                           .scale = 0.0f,
4023                                           .zeroPoint = 0};
4024     ANeuralNetworksOperandType recurrentWeights = {.type = inputOperandCode,
4025                                                    .dimensionCount = 2,
4026                                                    .dimensions = recurrentWeightsDims,
4027                                                    .scale = 0.0f,
4028                                                    .zeroPoint = 0};
4029     ANeuralNetworksOperandType bias = {.type = inputOperandCode,
4030                                        .dimensionCount = 1,
4031                                        .dimensions = biasDims,
4032                                        .scale = 0.0f,
4033                                        .zeroPoint = 0};
4034     ANeuralNetworksOperandType hiddenState = {.type = inputOperandCode,
4035                                               .dimensionCount = 2,
4036                                               .dimensions = hiddenStateDims,
4037                                               .scale = 0.0f,
4038                                               .zeroPoint = 0};
4039     ANeuralNetworksOperandType output = {.type = inputOperandCode,
4040                                          .dimensionCount = 2,
4041                                          .dimensions = outputDims,
4042                                          .scale = 0.0f,
4043                                          .zeroPoint = 0};
4044     ANeuralNetworksOperandType intScalar = {.type = ANEURALNETWORKS_INT32,
4045                                             .dimensionCount = 0,
4046                                             .dimensions = nullptr,
4047                                             .scale = 0.0f,
4048                                             .zeroPoint = 0};
4049     ANeuralNetworksOperandType activation = intScalar;
4050     ANeuralNetworksOperandType timeMajor = intScalar;
4051 
4052     OperationTestBase rnnTest(
4053             ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN,
4054             {input, weights, recurrentWeights, bias, hiddenState, activation, timeMajor}, {output});
4055     rnnTest.testOpsValidations();
4056 }
4057 
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_RNN_float32)4058 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_RNN_float32) {
4059     unidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT32);
4060 }
4061 
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_RNN_float16)4062 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_RNN_float16) {
4063     unidirectionlSequenceRNNTest(ANEURALNETWORKS_TENSOR_FLOAT16);
4064 }
4065 
unidirectionalSequenceLSTMTest(int32_t inputOperandCode)4066 void unidirectionalSequenceLSTMTest(int32_t inputOperandCode) {
4067     const uint32_t maxTime = 2;
4068     const uint32_t batchSize = 3;
4069     const uint32_t numUnits = 4;
4070     const uint32_t inputSize = 5;
4071     const uint32_t outputSize = 6;
4072 
4073     uint32_t inputDims[3] = {maxTime, batchSize, inputSize};
4074     uint32_t inputWeightsDims[2] = {numUnits, inputSize};
4075     uint32_t recurrentWeightsDims[2] = {numUnits, outputSize};
4076     uint32_t diagonalDims[1] = {numUnits};
4077     uint32_t projectionDims[2] = {outputSize, numUnits};
4078     uint32_t projectionBiasDims[1] = {outputSize};
4079     uint32_t outputStateDims[2] = {batchSize, outputSize};
4080     uint32_t cellStateDims[2] = {batchSize, numUnits};
4081 
4082     uint32_t outputDims[3] = {maxTime, batchSize, outputSize};
4083 
4084     ANeuralNetworksOperandType input = {.type = inputOperandCode,
4085                                         .dimensionCount = 3,
4086                                         .dimensions = inputDims,
4087                                         .scale = 0.0f,
4088                                         .zeroPoint = 0};
4089     ANeuralNetworksOperandType inputToInputWeights = {.type = inputOperandCode,
4090                                                       .dimensionCount = 2,
4091                                                       .dimensions = inputWeightsDims,
4092                                                       .scale = 0.0f,
4093                                                       .zeroPoint = 0};
4094     ANeuralNetworksOperandType inputToForgetWeights = inputToInputWeights;
4095     ANeuralNetworksOperandType inputToCellWeights = inputToInputWeights;
4096     ANeuralNetworksOperandType inputToOutputWeights = inputToInputWeights;
4097     ANeuralNetworksOperandType recurrentToInputWeights = {.type = inputOperandCode,
4098                                                           .dimensionCount = 2,
4099                                                           .dimensions = recurrentWeightsDims,
4100                                                           .scale = 0.0f,
4101                                                           .zeroPoint = 0};
4102     ANeuralNetworksOperandType recurrentToForgetWeights = recurrentToInputWeights;
4103     ANeuralNetworksOperandType recurrentToCellWeights = recurrentToInputWeights;
4104     ANeuralNetworksOperandType recurrentToOutputWeights = recurrentToInputWeights;
4105     ANeuralNetworksOperandType cellToInputWeights = {.type = inputOperandCode,
4106                                                      .dimensionCount = 1,
4107                                                      .dimensions = diagonalDims,
4108                                                      .scale = 0.0f,
4109                                                      .zeroPoint = 0};
4110     ANeuralNetworksOperandType cellToForgetWeights = cellToInputWeights;
4111     ANeuralNetworksOperandType cellToOutputWeights = cellToInputWeights;
4112     ANeuralNetworksOperandType inputGateBias = {.type = inputOperandCode,
4113                                                 .dimensionCount = 1,
4114                                                 .dimensions = diagonalDims,
4115                                                 .scale = 0.0f,
4116                                                 .zeroPoint = 0};
4117     ANeuralNetworksOperandType forgetGateBias = inputGateBias;
4118     ANeuralNetworksOperandType cellGateBias = inputGateBias;
4119     ANeuralNetworksOperandType outputGateBias = inputGateBias;
4120     ANeuralNetworksOperandType projectionWeights = {.type = inputOperandCode,
4121                                                     .dimensionCount = 2,
4122                                                     .dimensions = projectionDims,
4123                                                     .scale = 0.0f,
4124                                                     .zeroPoint = 0};
4125     ANeuralNetworksOperandType projectionBias = {.type = inputOperandCode,
4126                                                  .dimensionCount = 1,
4127                                                  .dimensions = projectionBiasDims,
4128                                                  .scale = 0.0f,
4129                                                  .zeroPoint = 0};
4130     ANeuralNetworksOperandType outputStateIn = {.type = inputOperandCode,
4131                                                 .dimensionCount = 2,
4132                                                 .dimensions = outputStateDims,
4133                                                 .scale = 0.0f,
4134                                                 .zeroPoint = 0};
4135     ANeuralNetworksOperandType cellStateIn = {.type = inputOperandCode,
4136                                               .dimensionCount = 2,
4137                                               .dimensions = cellStateDims,
4138                                               .scale = 0.0f,
4139                                               .zeroPoint = 0};
4140     ANeuralNetworksOperandType intScalar = {
4141             .type = ANEURALNETWORKS_INT32,
4142             .dimensionCount = 0,
4143             .dimensions = nullptr,
4144             .scale = 0.0f,
4145             .zeroPoint = 0,
4146     };
4147     ANeuralNetworksOperandType activation = intScalar;
4148     ANeuralNetworksOperandType floatScalar = {
4149             .type = inputOperandCode == ANEURALNETWORKS_TENSOR_FLOAT32 ? ANEURALNETWORKS_FLOAT32
4150                                                                        : ANEURALNETWORKS_FLOAT16,
4151             .dimensionCount = 0,
4152             .dimensions = nullptr,
4153             .scale = 0.0f,
4154             .zeroPoint = 0,
4155     };
4156     ANeuralNetworksOperandType cellClip = floatScalar;
4157     ANeuralNetworksOperandType projClip = floatScalar;
4158     ANeuralNetworksOperandType boolScalar = {
4159             .type = ANEURALNETWORKS_BOOL,
4160             .dimensionCount = 0,
4161             .dimensions = nullptr,
4162             .scale = 0.0f,
4163             .zeroPoint = 0,
4164     };
4165     ANeuralNetworksOperandType timeMajor = boolScalar;
4166     ANeuralNetworksOperandType inputLayerNormWeights = {.type = inputOperandCode,
4167                                                         .dimensionCount = 1,
4168                                                         .dimensions = diagonalDims,
4169                                                         .scale = 0.0f,
4170                                                         .zeroPoint = 0};
4171     ANeuralNetworksOperandType forgetLayerNormWeights = inputLayerNormWeights;
4172     ANeuralNetworksOperandType cellLayerNormWeights = inputLayerNormWeights;
4173     ANeuralNetworksOperandType outputLayerNormWeights = inputLayerNormWeights;
4174 
4175     ANeuralNetworksOperandType output = {.type = inputOperandCode,
4176                                          .dimensionCount = 3,
4177                                          .dimensions = outputDims,
4178                                          .scale = 0.0f,
4179                                          .zeroPoint = 0};
4180 
4181     OperationTestBase ulstmTest(ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM,
4182                                 {input,
4183                                  inputToInputWeights,
4184                                  inputToForgetWeights,
4185                                  inputToCellWeights,
4186                                  inputToOutputWeights,
4187                                  recurrentToInputWeights,
4188                                  recurrentToForgetWeights,
4189                                  recurrentToCellWeights,
4190                                  recurrentToOutputWeights,
4191                                  cellToInputWeights,
4192                                  cellToForgetWeights,
4193                                  cellToOutputWeights,
4194                                  inputGateBias,
4195                                  forgetGateBias,
4196                                  cellGateBias,
4197                                  outputGateBias,
4198                                  projectionWeights,
4199                                  projectionBias,
4200                                  outputStateIn,
4201                                  cellStateIn,
4202                                  activation,
4203                                  cellClip,
4204                                  projClip,
4205                                  timeMajor,
4206                                  inputLayerNormWeights,
4207                                  forgetLayerNormWeights,
4208                                  cellLayerNormWeights,
4209                                  outputLayerNormWeights},
4210                                 {output});
4211     ulstmTest.testOpsValidations();
4212 }
4213 
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_LSTM_float32)4214 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_LSTM_float32) {
4215     unidirectionalSequenceLSTMTest(ANEURALNETWORKS_TENSOR_FLOAT32);
4216 }
4217 
TEST(OperationValidationTest,UNIDIRECTIONAL_SEQUENCE_LSTM_float16)4218 TEST(OperationValidationTest, UNIDIRECTIONAL_SEQUENCE_LSTM_float16) {
4219     unidirectionalSequenceLSTMTest(ANEURALNETWORKS_TENSOR_FLOAT16);
4220 }
4221 
generateProposalsOpTest(int32_t scoreOperandCode,int32_t deltaOperandCode,int32_t anchorOperandCode,int32_t roiOperandCode,int32_t scalarOperandCode)4222 void generateProposalsOpTest(int32_t scoreOperandCode, int32_t deltaOperandCode,
4223                              int32_t anchorOperandCode, int32_t roiOperandCode,
4224                              int32_t scalarOperandCode) {
4225     uint32_t scoreDim[] = {1, 2, 2, 2}, deltaDim[] = {1, 2, 2, 8}, anchorDim[] = {2, 4},
4226              imageInfoDim[] = {1, 2};
4227     uint32_t outScoreDim[] = {4}, outRoiDim[] = {4, 4}, outSplitDim[] = {1};
4228     OperationTestBase generateProposalsTest(
4229             ANEURALNETWORKS_GENERATE_PROPOSALS,
4230             {getOpType(scoreOperandCode, 4, scoreDim), getOpType(deltaOperandCode, 4, deltaDim),
4231              getOpType(anchorOperandCode, 2, anchorDim), getOpType(roiOperandCode, 2, imageInfoDim),
4232              getOpType(scalarOperandCode), getOpType(scalarOperandCode),
4233              getOpType(ANEURALNETWORKS_INT32), getOpType(ANEURALNETWORKS_INT32),
4234              getOpType(scalarOperandCode), getOpType(scalarOperandCode),
4235              getOpType(ANEURALNETWORKS_BOOL)},
4236             {getOpType(scoreOperandCode, 1, outScoreDim), getOpType(roiOperandCode, 2, outRoiDim),
4237              getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, outSplitDim)});
4238     generateProposalsTest.testOpsValidations();
4239 }
4240 
TEST(OperationValidationTest,GENERATE_PROPOSALS_float16)4241 TEST(OperationValidationTest, GENERATE_PROPOSALS_float16) {
4242     generateProposalsOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
4243                             ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16,
4244                             ANEURALNETWORKS_FLOAT16);
4245 }
4246 
TEST(OperationValidationTest,GENERATE_PROPOSALS_float32)4247 TEST(OperationValidationTest, GENERATE_PROPOSALS_float32) {
4248     generateProposalsOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
4249                             ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32,
4250                             ANEURALNETWORKS_FLOAT32);
4251 }
4252 
TEST(OperationValidationTest,GENERATE_PROPOSALS_quant)4253 TEST(OperationValidationTest, GENERATE_PROPOSALS_quant) {
4254     generateProposalsOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
4255                             ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
4256                             ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4257                             ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
4258 }
4259 
TEST(OperationValidationTest,GENERATE_PROPOSALS_quant_signed)4260 TEST(OperationValidationTest, GENERATE_PROPOSALS_quant_signed) {
4261     generateProposalsOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
4262                             ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
4263                             ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4264                             ANEURALNETWORKS_TENSOR_QUANT16_ASYMM, ANEURALNETWORKS_FLOAT32);
4265 }
4266 
resizeNearestNeighborTest(int32_t inputCode,int32_t scalarCode)4267 void resizeNearestNeighborTest(int32_t inputCode, int32_t scalarCode) {
4268     uint32_t inputDim[] = {1, 2, 2, 1}, outputDim[] = {1, 1, 1, 1};
4269     OperationTestBase resizeImageOpTest(ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR,
4270                                         {getOpType(inputCode, 4, inputDim), getOpType(scalarCode),
4271                                          getOpType(scalarCode), getOpType(ANEURALNETWORKS_BOOL)},
4272                                         {getOpType(inputCode, 4, outputDim)});
4273     resizeImageOpTest.testOpsValidations();
4274 }
4275 
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR)4276 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR) {
4277     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_INT32);
4278     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_FLOAT32);
4279 }
4280 
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR_float16)4281 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR_float16) {
4282     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_INT32);
4283     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_FLOAT16);
4284 }
4285 
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR_quant8)4286 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR_quant8) {
4287     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_INT32);
4288     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, ANEURALNETWORKS_FLOAT32);
4289 }
4290 
TEST(OperationValidationTest,RESIZE_NEAREST_NEIGHBOR_quant8_signed)4291 TEST(OperationValidationTest, RESIZE_NEAREST_NEIGHBOR_quant8_signed) {
4292     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_INT32);
4293     resizeNearestNeighborTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED, ANEURALNETWORKS_FLOAT32);
4294 }
4295 
TEST(OperationValidationTest,QUANTIZED_LSTM)4296 TEST(OperationValidationTest, QUANTIZED_LSTM) {
4297     uint32_t oneDimensional[1] = {5};
4298     uint32_t twoDimensional[2] = {5, 5};
4299 
4300     ANeuralNetworksOperandType quant8AsymSignedTensor2D = {
4301             .type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED,
4302             .dimensionCount = 2,
4303             .dimensions = twoDimensional,
4304             .scale = 0.0078125,
4305             .zeroPoint = 0,
4306     };
4307     ANeuralNetworksOperandType quant8SymTensor2D = {
4308             .type = ANEURALNETWORKS_TENSOR_QUANT8_SYMM,
4309             .dimensionCount = 2,
4310             .dimensions = twoDimensional,
4311             .scale = 0.0078125,
4312             .zeroPoint = 0,
4313     };
4314     ANeuralNetworksOperandType quant16SymTensor1D = {
4315             .type = ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4316             .dimensionCount = 1,
4317             .dimensions = oneDimensional,
4318             .scale = 1.0,
4319             .zeroPoint = 0,
4320     };
4321     ANeuralNetworksOperandType quant16SymTensor2D = {
4322             .type = ANEURALNETWORKS_TENSOR_QUANT16_SYMM,
4323             .dimensionCount = 2,
4324             .dimensions = twoDimensional,
4325             .scale = 1.0,
4326             .zeroPoint = 0,
4327     };
4328     ANeuralNetworksOperandType int32Tensor1D = {
4329             .type = ANEURALNETWORKS_TENSOR_INT32,
4330             .dimensionCount = 1,
4331             .dimensions = oneDimensional,
4332             .scale = 4.65661e-08,
4333             .zeroPoint = 0,
4334     };
4335     ANeuralNetworksOperandType int32Scalar = {
4336             .type = ANEURALNETWORKS_INT32,
4337     };
4338     ANeuralNetworksOperandType float32Scalar = {
4339             .type = ANEURALNETWORKS_FLOAT32,
4340     };
4341 
4342     ANeuralNetworksOperandType input = quant8AsymSignedTensor2D;
4343     ANeuralNetworksOperandType input_to_input_weights = quant8SymTensor2D;
4344     ANeuralNetworksOperandType input_to_forget_weights = quant8SymTensor2D;
4345     ANeuralNetworksOperandType input_to_cell_weights = quant8SymTensor2D;
4346     ANeuralNetworksOperandType input_to_output_weights = quant8SymTensor2D;
4347     ANeuralNetworksOperandType recurrent_to_input_weights = quant8SymTensor2D;
4348     ANeuralNetworksOperandType recurrent_to_forget_weights = quant8SymTensor2D;
4349     ANeuralNetworksOperandType recurrent_to_cell_weights = quant8SymTensor2D;
4350     ANeuralNetworksOperandType recurrent_to_output_weights = quant8SymTensor2D;
4351     ANeuralNetworksOperandType cell_to_input_weights = quant16SymTensor2D;
4352     ANeuralNetworksOperandType cell_to_forget_weights = quant16SymTensor2D;
4353     ANeuralNetworksOperandType cell_to_output_weights = quant16SymTensor2D;
4354     ANeuralNetworksOperandType input_gate_bias = int32Tensor1D;
4355     ANeuralNetworksOperandType forget_gate_bias = int32Tensor1D;
4356     ANeuralNetworksOperandType cell_gate_bias = int32Tensor1D;
4357     ANeuralNetworksOperandType output_gate_bias = int32Tensor1D;
4358     ANeuralNetworksOperandType projection_weights = quant8SymTensor2D;
4359     ANeuralNetworksOperandType projection_bias = int32Tensor1D;
4360     ANeuralNetworksOperandType output_state_in = quant8AsymSignedTensor2D;
4361     ANeuralNetworksOperandType cell_state_in = quant16SymTensor2D;
4362     ANeuralNetworksOperandType input_layer_norm_weights = quant16SymTensor1D;
4363     ANeuralNetworksOperandType forget_layer_norm_weights = quant16SymTensor1D;
4364     ANeuralNetworksOperandType cell_layer_norm_weights = quant16SymTensor1D;
4365     ANeuralNetworksOperandType output_layer_norm_weights = quant16SymTensor1D;
4366     ANeuralNetworksOperandType cell_clip = float32Scalar;
4367     ANeuralNetworksOperandType projection_clip = float32Scalar;
4368     ANeuralNetworksOperandType input_intermediate_scale = float32Scalar;
4369     ANeuralNetworksOperandType forget_intermediate_scale = float32Scalar;
4370     ANeuralNetworksOperandType cell_intermediate_scale = float32Scalar;
4371     ANeuralNetworksOperandType output_intermediate_scale = float32Scalar;
4372     ANeuralNetworksOperandType hidden_state_zero_point = int32Scalar;
4373     ANeuralNetworksOperandType hidden_state_scale = float32Scalar;
4374 
4375     ANeuralNetworksOperandType output_state_out = quant8AsymSignedTensor2D;
4376     ANeuralNetworksOperandType cell_state_out = quant16SymTensor2D;
4377     ANeuralNetworksOperandType output = quant8AsymSignedTensor2D;
4378 
4379     OperationTestBase test(ANEURALNETWORKS_QUANTIZED_LSTM,
4380                            {input,
4381                             input_to_input_weights,
4382                             input_to_forget_weights,
4383                             input_to_cell_weights,
4384                             input_to_output_weights,
4385                             recurrent_to_input_weights,
4386                             recurrent_to_forget_weights,
4387                             recurrent_to_cell_weights,
4388                             recurrent_to_output_weights,
4389                             cell_to_input_weights,
4390                             cell_to_forget_weights,
4391                             cell_to_output_weights,
4392                             input_gate_bias,
4393                             forget_gate_bias,
4394                             cell_gate_bias,
4395                             output_gate_bias,
4396                             projection_weights,
4397                             projection_bias,
4398                             output_state_in,
4399                             cell_state_in,
4400                             input_layer_norm_weights,
4401                             forget_layer_norm_weights,
4402                             cell_layer_norm_weights,
4403                             output_layer_norm_weights,
4404                             cell_clip,
4405                             projection_clip,
4406                             input_intermediate_scale,
4407                             forget_intermediate_scale,
4408                             cell_intermediate_scale,
4409                             output_intermediate_scale,
4410                             hidden_state_zero_point,
4411                             hidden_state_scale},
4412                            {output_state_out, cell_state_out, output});
4413     test.testOpsValidations();
4414 }
4415 
fillTest(int32_t valueOperandType,int32_t outputOperandType)4416 void fillTest(int32_t valueOperandType, int32_t outputOperandType) {
4417     uint32_t inputDimensions[1] = {3};
4418     ANeuralNetworksOperandType input0 = getOpType(ANEURALNETWORKS_TENSOR_INT32, 1, inputDimensions);
4419     ANeuralNetworksOperandType input1 = getOpType(valueOperandType);
4420     uint32_t outputDimensions[3] = {3, 4, 5};
4421     ANeuralNetworksOperandType output = getOpType(outputOperandType, 3, outputDimensions);
4422     OperationTestBase test(ANEURALNETWORKS_FILL, {input0, input1}, {output});
4423     test.testOpsValidations();
4424 }
4425 
TEST(OperationValidationTest,FILL_float16)4426 TEST(OperationValidationTest, FILL_float16) {
4427     fillTest(ANEURALNETWORKS_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
4428 }
4429 
TEST(OperationValidationTest,FILL_float32)4430 TEST(OperationValidationTest, FILL_float32) {
4431     fillTest(ANEURALNETWORKS_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
4432 }
4433 
TEST(OperationValidationTest,FILL_int32)4434 TEST(OperationValidationTest, FILL_int32) {
4435     fillTest(ANEURALNETWORKS_INT32, ANEURALNETWORKS_TENSOR_INT32);
4436 }
4437 
rankTest(int32_t inputOperandType)4438 void rankTest(int32_t inputOperandType) {
4439     uint32_t inputDimensions[3] = {3, 4, 5};
4440     ANeuralNetworksOperandType input = getOpType(inputOperandType, 3, inputDimensions);
4441     ANeuralNetworksOperandType output = getOpType(ANEURALNETWORKS_INT32);
4442     OperationTestBase test(ANEURALNETWORKS_RANK, {input}, {output});
4443     test.testOpsValidations();
4444 }
4445 
TEST(OperationValidationTest,RANK_float16)4446 TEST(OperationValidationTest, RANK_float16) {
4447     rankTest(ANEURALNETWORKS_TENSOR_FLOAT16);
4448 }
4449 
TEST(OperationValidationTest,RANK_float32)4450 TEST(OperationValidationTest, RANK_float32) {
4451     rankTest(ANEURALNETWORKS_TENSOR_FLOAT32);
4452 }
4453 
TEST(OperationValidationTest,RANK_int32)4454 TEST(OperationValidationTest, RANK_int32) {
4455     rankTest(ANEURALNETWORKS_TENSOR_INT32);
4456 }
4457 
TEST(OperationValidationTest,RANK_quant8)4458 TEST(OperationValidationTest, RANK_quant8) {
4459     rankTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM);
4460 }
4461 
TEST(OperationValidationTest,RANK_quant8_signed)4462 TEST(OperationValidationTest, RANK_quant8_signed) {
4463     rankTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED);
4464 }
4465 
makeIdentityModel(const ANeuralNetworksOperandType * type)4466 ANeuralNetworksModel* makeIdentityModel(const ANeuralNetworksOperandType* type) {
4467     ANeuralNetworksModel* model = nullptr;
4468     EXPECT_EQ(ANeuralNetworksModel_create(&model), ANEURALNETWORKS_NO_ERROR);
4469     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4470     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4471     uint32_t inputs[] = {0};
4472     uint32_t outputs[] = {1};
4473     EXPECT_EQ(ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_CAST, std::size(inputs),
4474                                                 inputs, std::size(outputs), outputs),
4475               ANEURALNETWORKS_NO_ERROR);
4476     EXPECT_EQ(ANeuralNetworksModel_identifyInputsAndOutputs(model, std::size(inputs), inputs,
4477                                                             std::size(outputs), outputs),
4478               ANEURALNETWORKS_NO_ERROR);
4479     EXPECT_EQ(ANeuralNetworksModel_finish(model), ANEURALNETWORKS_NO_ERROR);
4480     return model;
4481 }
4482 
testIf(const std::vector<uint32_t> & outerDims,const ANeuralNetworksModel * thenModel,const ANeuralNetworksModel * elseModel,bool testMutations)4483 void testIf(const std::vector<uint32_t>& outerDims, const ANeuralNetworksModel* thenModel,
4484             const ANeuralNetworksModel* elseModel, bool testMutations) {
4485     const uint32_t kThenOperand = 1;
4486     const uint32_t kElseOperand = 2;
4487     const uint32_t boolDims[] = {1};
4488     ANeuralNetworksOperandType boolType =
4489             getOpType(ANEURALNETWORKS_TENSOR_BOOL8, std::size(boolDims), boolDims);
4490     ANeuralNetworksOperandType dataType =
4491             getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, outerDims.size(), outerDims.data());
4492     ANeuralNetworksOperandType modelType = getOpType(ANEURALNETWORKS_MODEL);
4493     OperationTestBase test(ANEURALNETWORKS_IF, {boolType, modelType, modelType, dataType},
4494                            {dataType});
4495     test.setInputOperandValueFromModel(kThenOperand, thenModel);
4496     test.setInputOperandValueFromModel(kElseOperand, elseModel);
4497     if (testMutations) {
4498         test.testOpsValidations();
4499     } else {
4500         EXPECT_TRUE(test.testSuccess());
4501     }
4502 }
4503 
testIf(const std::vector<uint32_t> & outerDims,const std::vector<uint32_t> & thenDims,const std::vector<uint32_t> & elseDims,bool testMutations)4504 void testIf(const std::vector<uint32_t>& outerDims, const std::vector<uint32_t>& thenDims,
4505             const std::vector<uint32_t>& elseDims, bool testMutations) {
4506     ANeuralNetworksOperandType thenDataType =
4507             getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, thenDims.size(), thenDims.data());
4508     ANeuralNetworksOperandType elseDataType =
4509             getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, elseDims.size(), elseDims.data());
4510     ANeuralNetworksModel* thenModel = makeIdentityModel(&thenDataType);
4511     ANeuralNetworksModel* elseModel = makeIdentityModel(&elseDataType);
4512     testIf(outerDims, thenModel, elseModel, testMutations);
4513     ANeuralNetworksModel_free(thenModel);
4514     ANeuralNetworksModel_free(elseModel);
4515 }
4516 
TEST(OperationValidationTest,IF)4517 TEST(OperationValidationTest, IF) {
4518     const std::vector<std::pair<std::string, std::vector<uint32_t>>> configurations = {
4519             {"fully specified", {1, 2, 3}},
4520             {"unknown dimensions", {0, 2, 0}},
4521             {"unknown rank", {}},
4522     };
4523     // We skip mutation testing for all but the first configuration to avoid the
4524     // exponential runtime blowup. The value of additional operand code and
4525     // count mutations is negligible because whether the shapes are fully
4526     // specified should have nothing to do with the operand code or count.
4527     bool testMutations = true;
4528     for (const auto& [outerTrace, outerDims] : configurations) {
4529         SCOPED_TRACE(testing::Message() << "outerDims: " << outerTrace);
4530         for (const auto& [thenTrace, thenDims] : configurations) {
4531             SCOPED_TRACE(testing::Message() << "thenDims: " << thenTrace);
4532             for (const auto& [elseTrace, elseDims] : configurations) {
4533                 SCOPED_TRACE(testing::Message() << "elseDims: " << elseTrace);
4534                 testIf(outerDims, thenDims, elseDims, testMutations);
4535                 testMutations = false;
4536             }
4537         }
4538     }
4539 }
4540 
4541 // operand 0 --> +------+
4542 //               | LESS | --> operand 2
4543 // operand 1 --> +------+
4544 //
makeWhileCondModel(const ANeuralNetworksOperandType * dataType,const ANeuralNetworksOperandType * boolType)4545 ANeuralNetworksModel* makeWhileCondModel(const ANeuralNetworksOperandType* dataType,
4546                                          const ANeuralNetworksOperandType* boolType) {
4547     ANeuralNetworksModel* model = nullptr;
4548     EXPECT_EQ(ANeuralNetworksModel_create(&model), ANEURALNETWORKS_NO_ERROR);
4549     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, dataType), ANEURALNETWORKS_NO_ERROR);
4550     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, dataType), ANEURALNETWORKS_NO_ERROR);
4551     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, boolType), ANEURALNETWORKS_NO_ERROR);
4552     const uint32_t inputs[] = {0, 1};
4553     const uint32_t outputs[] = {2};
4554     EXPECT_EQ(ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_LESS, std::size(inputs),
4555                                                 inputs, std::size(outputs), outputs),
4556               ANEURALNETWORKS_NO_ERROR);
4557     EXPECT_EQ(ANeuralNetworksModel_identifyInputsAndOutputs(model, std::size(inputs), inputs,
4558                                                             std::size(outputs), outputs),
4559               ANEURALNETWORKS_NO_ERROR);
4560     EXPECT_EQ(ANeuralNetworksModel_finish(model), ANEURALNETWORKS_NO_ERROR);
4561     return model;
4562 }
4563 
4564 //               +------+
4565 // operand 0 --> | CAST | --> operand 2
4566 //               +------+
4567 //
4568 // operand 1 --> (unused)
4569 //
makeWhileBodyModel(const ANeuralNetworksOperandType * type)4570 ANeuralNetworksModel* makeWhileBodyModel(const ANeuralNetworksOperandType* type) {
4571     ANeuralNetworksModel* model = nullptr;
4572     EXPECT_EQ(ANeuralNetworksModel_create(&model), ANEURALNETWORKS_NO_ERROR);
4573     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4574     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4575     EXPECT_EQ(ANeuralNetworksModel_addOperand(model, type), ANEURALNETWORKS_NO_ERROR);
4576     const uint32_t castInputs[] = {0};
4577     const uint32_t castOutputs[] = {2};
4578     EXPECT_EQ(ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_CAST, std::size(castInputs),
4579                                                 castInputs, std::size(castOutputs), castOutputs),
4580               ANEURALNETWORKS_NO_ERROR);
4581     const uint32_t modelInputs[] = {0, 1};
4582     const uint32_t modelOutputs[] = {2};
4583     EXPECT_EQ(ANeuralNetworksModel_identifyInputsAndOutputs(model, std::size(modelInputs),
4584                                                             modelInputs, std::size(modelOutputs),
4585                                                             modelOutputs),
4586               ANEURALNETWORKS_NO_ERROR);
4587     EXPECT_EQ(ANeuralNetworksModel_finish(model), ANEURALNETWORKS_NO_ERROR);
4588     return model;
4589 }
4590 
testWhile(const std::vector<uint32_t> & outerDims,const ANeuralNetworksModel * condModel,const ANeuralNetworksModel * bodyModel,bool testMutations)4591 void testWhile(const std::vector<uint32_t>& outerDims, const ANeuralNetworksModel* condModel,
4592                const ANeuralNetworksModel* bodyModel, bool testMutations) {
4593     const uint32_t kCondOperand = 0;
4594     const uint32_t kBodyOperand = 1;
4595     ANeuralNetworksOperandType modelType = getOpType(ANEURALNETWORKS_MODEL);
4596     ANeuralNetworksOperandType dataType =
4597             getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, outerDims.size(), outerDims.data());
4598     OperationTestBase test(ANEURALNETWORKS_WHILE, {modelType, modelType, dataType, dataType},
4599                            {dataType});
4600     test.setInputOperandValueFromModel(kCondOperand, condModel);
4601     test.setInputOperandValueFromModel(kBodyOperand, bodyModel);
4602     if (testMutations) {
4603         test.testOpsValidations();
4604     } else {
4605         EXPECT_TRUE(test.testSuccess());
4606     }
4607 }
4608 
testWhile(const std::vector<uint32_t> & outerDims,const std::vector<uint32_t> & condDims,const std::vector<uint32_t> & bodyDims,bool testMutations)4609 void testWhile(const std::vector<uint32_t>& outerDims, const std::vector<uint32_t>& condDims,
4610                const std::vector<uint32_t>& bodyDims, bool testMutations) {
4611     const uint32_t boolDims[] = {1};
4612     ANeuralNetworksOperandType boolType =
4613             getOpType(ANEURALNETWORKS_TENSOR_BOOL8, std::size(boolDims), boolDims);
4614     ANeuralNetworksOperandType condDataType =
4615             getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, condDims.size(), condDims.data());
4616     ANeuralNetworksOperandType bodyDataType =
4617             getOpType(ANEURALNETWORKS_TENSOR_FLOAT32, bodyDims.size(), bodyDims.data());
4618     ANeuralNetworksModel* condModel = makeWhileCondModel(&condDataType, &boolType);
4619     ANeuralNetworksModel* bodyModel = makeWhileBodyModel(&bodyDataType);
4620     testWhile(outerDims, condModel, bodyModel, testMutations);
4621     ANeuralNetworksModel_free(condModel);
4622     ANeuralNetworksModel_free(bodyModel);
4623 }
4624 
TEST(OperationValidationTest,WHILE)4625 TEST(OperationValidationTest, WHILE) {
4626     const std::vector<std::pair<std::string, std::vector<uint32_t>>> configurations = {
4627             {"fully specified", {1, 2, 3}},
4628             {"unknown dimensions", {0, 2, 0}},
4629             {"unknown rank", {}},
4630     };
4631     // We skip mutation testing for all but the first configuration to avoid the
4632     // exponential runtime blowup. The value of additional operand code and
4633     // count mutations is negligible because whether the shapes are fully
4634     // specified should have nothing to do with the operand code or count.
4635     bool testMutations = true;
4636     for (const auto& [outerTrace, outerDims] : configurations) {
4637         SCOPED_TRACE(testing::Message() << "outerDims: " << outerTrace);
4638         for (const auto& [condTrace, condDims] : configurations) {
4639             SCOPED_TRACE(testing::Message() << "condDims: " << condTrace);
4640             for (const auto& [bodyTrace, bodyDims] : configurations) {
4641                 SCOPED_TRACE(testing::Message() << "bodyDims: " << bodyTrace);
4642                 testWhile(outerDims, condDims, bodyDims, testMutations);
4643                 testMutations = false;
4644             }
4645         }
4646     }
4647 }
4648 
4649 }  // end namespace
4650