blob: 3be4c1b97dbbee06223f57bc12ff140c83deac28 [file] [log] [blame]
Lev Proleevc185e882020-12-15 19:25:32 +00001/*
2 * Copyright (C) 2021 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#define LOG_TAG "neuralnetworks_aidl_hal_test"
18
19#include <android/binder_auto_utils.h>
20
21#include <chrono>
22
23#include <TestHarness.h>
24#include <nnapi/hal/aidl/Utils.h>
25
26#include "Callbacks.h"
27#include "GeneratedTestHarness.h"
28#include "Utils.h"
29#include "VtsHalNeuralnetworks.h"
30
31namespace aidl::android::hardware::neuralnetworks::vts::functional {
32
33using ExecutionMutation = std::function<void(Request*)>;
34
35///////////////////////// UTILITY FUNCTIONS /////////////////////////
36
37// Primary validation function. This function will take a valid request, apply a
38// mutation to it to invalidate the request, then pass it to interface calls
39// that use the request.
40static void validate(const std::shared_ptr<IPreparedModel>& preparedModel,
41 const std::string& message, const Request& originalRequest,
42 const ExecutionMutation& mutate) {
43 Request request = utils::clone(originalRequest).value();
44 mutate(&request);
45
46 // We'd like to test both with timing requested and without timing
47 // requested. Rather than running each test both ways, we'll decide whether
48 // to request timing by hashing the message. We do not use std::hash because
49 // it is not guaranteed stable across executions.
50 char hash = 0;
51 for (auto c : message) {
52 hash ^= c;
53 };
54 bool measure = (hash & 1);
55
56 // synchronous
57 {
58 SCOPED_TRACE(message + " [executeSynchronously]");
59 ExecutionResult executionResult;
60 const auto executeStatus = preparedModel->executeSynchronously(
61 request, measure, kNoDeadline, kOmittedTimeoutDuration, &executionResult);
62 ASSERT_FALSE(executeStatus.isOk());
63 ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
64 ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
65 ErrorStatus::INVALID_ARGUMENT);
66 }
67
68 // fenced
69 {
70 SCOPED_TRACE(message + " [executeFenced]");
Jooyung Hand33893f2021-02-26 17:09:23 +090071 FencedExecutionResult executionResult;
Lev Proleevc185e882020-12-15 19:25:32 +000072 const auto executeStatus = preparedModel->executeFenced(request, {}, false, kNoDeadline,
73 kOmittedTimeoutDuration,
Jooyung Hand33893f2021-02-26 17:09:23 +090074 kNoDuration, &executionResult);
Lev Proleevc185e882020-12-15 19:25:32 +000075 ASSERT_FALSE(executeStatus.isOk());
76 ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
77 ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
78 ErrorStatus::INVALID_ARGUMENT);
79 }
80}
81
82///////////////////////// REMOVE INPUT ////////////////////////////////////
83
84static void removeInputTest(const std::shared_ptr<IPreparedModel>& preparedModel,
85 const Request& request) {
86 for (size_t input = 0; input < request.inputs.size(); ++input) {
87 const std::string message = "removeInput: removed input " + std::to_string(input);
88 validate(preparedModel, message, request, [input](Request* request) {
89 request->inputs.erase(request->inputs.begin() + input);
90 });
91 }
92}
93
94///////////////////////// REMOVE OUTPUT ////////////////////////////////////
95
96static void removeOutputTest(const std::shared_ptr<IPreparedModel>& preparedModel,
97 const Request& request) {
98 for (size_t output = 0; output < request.outputs.size(); ++output) {
99 const std::string message = "removeOutput: removed Output " + std::to_string(output);
100 validate(preparedModel, message, request, [output](Request* request) {
101 request->outputs.erase(request->outputs.begin() + output);
102 });
103 }
104}
105
106///////////////////////////// ENTRY POINT //////////////////////////////////
107
108void validateRequest(const std::shared_ptr<IPreparedModel>& preparedModel, const Request& request) {
109 removeInputTest(preparedModel, request);
110 removeOutputTest(preparedModel, request);
111}
112
113void validateRequestFailure(const std::shared_ptr<IPreparedModel>& preparedModel,
114 const Request& request) {
115 SCOPED_TRACE("Expecting request to fail [executeSynchronously]");
116 ExecutionResult executionResult;
117 const auto executeStatus = preparedModel->executeSynchronously(
118 request, false, kNoDeadline, kOmittedTimeoutDuration, &executionResult);
119
120 ASSERT_FALSE(executeStatus.isOk());
121 ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
122 ASSERT_NE(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()), ErrorStatus::NONE);
123}
124
125} // namespace aidl::android::hardware::neuralnetworks::vts::functional