| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "TestControlFlow" |
| |
| #include <ControlFlow.h> |
| #include <android-base/logging.h> |
| #include <gtest/gtest.h> |
| |
| #include "TestNeuralNetworksWrapper.h" |
| |
| namespace android::nn { |
| namespace { |
| |
| using test_wrapper::Compilation; |
| using test_wrapper::Execution; |
| using test_wrapper::Model; |
| using test_wrapper::OperandType; |
| using test_wrapper::Result; |
| using test_wrapper::Type; |
| |
| constexpr uint64_t kMillisecondsInNanosecond = 1'000'000; |
| constexpr int32_t kNoActivation = ANEURALNETWORKS_FUSED_NONE; |
| |
| class ControlFlowTest : public ::testing::Test {}; |
| |
| TEST_F(ControlFlowTest, InfiniteLoop) { |
| // Expected result: execution aborted after the specified timeout. |
| // Model: given n <= 1.0, never returns. |
| // |
| // i = 1.0 |
| // while i >= n: |
| // i = i + 1.0 |
| |
| OperandType boolType(Type::TENSOR_BOOL8, {1}); |
| OperandType activationType(Type::INT32, {}); |
| OperandType counterType(Type::TENSOR_FLOAT32, {1}); |
| |
| Model conditionModel; |
| { |
| uint32_t i = conditionModel.addOperand(&counterType); |
| uint32_t n = conditionModel.addOperand(&counterType); |
| uint32_t out = conditionModel.addOperand(&boolType); |
| conditionModel.addOperation(ANEURALNETWORKS_GREATER_EQUAL, {i, n}, {out}); |
| conditionModel.identifyInputsAndOutputs({i, n}, {out}); |
| ASSERT_EQ(conditionModel.finish(), Result::NO_ERROR); |
| ASSERT_TRUE(conditionModel.isValid()); |
| } |
| |
| Model bodyModel; |
| { |
| uint32_t i = bodyModel.addOperand(&counterType); |
| uint32_t n = bodyModel.addOperand(&counterType); |
| uint32_t one = bodyModel.addConstantOperand(&counterType, 1.0f); |
| uint32_t noActivation = bodyModel.addConstantOperand(&activationType, kNoActivation); |
| uint32_t iOut = bodyModel.addOperand(&counterType); |
| bodyModel.addOperation(ANEURALNETWORKS_ADD, {i, one, noActivation}, {iOut}); |
| bodyModel.identifyInputsAndOutputs({i, n}, {iOut}); |
| ASSERT_EQ(bodyModel.finish(), Result::NO_ERROR); |
| ASSERT_TRUE(bodyModel.isValid()); |
| } |
| |
| Model model; |
| { |
| uint32_t iInit = model.addConstantOperand(&counterType, 1.0f); |
| uint32_t n = model.addOperand(&counterType); |
| uint32_t conditionOperand = model.addModelOperand(&conditionModel); |
| uint32_t bodyOperand = model.addModelOperand(&bodyModel); |
| uint32_t iOut = model.addOperand(&counterType); |
| model.addOperation(ANEURALNETWORKS_WHILE, {conditionOperand, bodyOperand, iInit, n}, |
| {iOut}); |
| model.identifyInputsAndOutputs({n}, {iOut}); |
| ASSERT_EQ(model.finish(), Result::NO_ERROR); |
| ASSERT_TRUE(model.isValid()); |
| } |
| |
| Compilation compilation(&model); |
| ASSERT_EQ(compilation.finish(), Result::NO_ERROR); |
| |
| float input = 0; |
| float output; |
| Execution execution(&compilation); |
| ASSERT_EQ(execution.setInput(0, &input), Result::NO_ERROR); |
| ASSERT_EQ(execution.setOutput(0, &output), Result::NO_ERROR); |
| ASSERT_EQ(execution.setLoopTimeout(1 * kMillisecondsInNanosecond), Result::NO_ERROR); |
| Result result = execution.compute(); |
| ASSERT_TRUE(result == Result::MISSED_DEADLINE_TRANSIENT || |
| result == Result::MISSED_DEADLINE_PERSISTENT) |
| << "result = " << static_cast<int>(result); |
| } |
| |
| TEST_F(ControlFlowTest, GetLoopTimeouts) { |
| uint64_t defaultTimeout = ANeuralNetworks_getDefaultLoopTimeout(); |
| uint64_t maximumTimeout = ANeuralNetworks_getMaximumLoopTimeout(); |
| ASSERT_EQ(defaultTimeout, operation_while::kTimeoutNsDefault); |
| ASSERT_EQ(maximumTimeout, operation_while::kTimeoutNsMaximum); |
| } |
| |
| } // end namespace |
| } // namespace android::nn |