1 /*
2 * Copyright (C) 2017 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 "NeuralNetworksTest"
18
19 #include <android-base/logging.h>
20 #include <gtest/gtest.h>
21
22 #include <cctype>
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26
27 #include "LogTestCaseToLogcat.h"
28 #include "TestNeuralNetworksWrapper.h"
29
30 #ifndef NNTEST_ONLY_PUBLIC_API
31 #include <Utils.h>
32
33 #include "Manager.h"
34 #endif
35
36 namespace {
37
38 using namespace android::nn::test_wrapper;
39
40 // We run through the test suite several times, by invoking test() several
41 // times. Each run is a "pass".
42
43 // Bitmask of passes we're allowed to run.
44 static uint64_t allowedPasses = ~uint64_t(0);
45
46 // DeviceManager::setUseCpuOnly() and Execution::setComputeUsesSynchronousAPI()
47 // according to arguments, and return RUN_ALL_TESTS(). It is unspecified what
48 // values those settings have when this function returns.
49 //
50 // EXCEPTION: If NNTEST_ONLY_PUBLIC_API is defined, then we cannot call
51 // non-public DeviceManager::setUseCpuOnly(); we assume the setting is always
52 // false, and if we are asked to set it to true, we return 0 ("success") without
53 // running tests.
test(bool useCpuOnly,Execution::ComputeMode computeMode)54 static int test(bool useCpuOnly, Execution::ComputeMode computeMode) {
55 // NOTE: The test mapping configuration (packages/modules/NeuralNetworks/TEST_MAPPING) uses
56 // the value of 4 to only run pass 2 of the test, corresponding to
57 // "useCpuOnly = 0, computeMode = ComputeMode::ASYNC".
58 // If you change the bit representation here, also make the corresponding
59 // change to the TEST_MAPPING file to run the equivalent pass of the test.
60 uint32_t passIndex = (useCpuOnly << 0) + (static_cast<uint32_t>(computeMode) << 1);
61
62 #ifdef NNTEST_ONLY_PUBLIC_API
63 if (useCpuOnly) {
64 return 0;
65 }
66 #else
67 android::nn::DeviceManager::get()->setUseCpuOnly(useCpuOnly);
68 #endif
69
70 Execution::setComputeMode(computeMode);
71
72 auto computeModeText = [computeMode] {
73 switch (computeMode) {
74 case Execution::ComputeMode::SYNC:
75 return "ComputeMode::SYNC";
76 case Execution::ComputeMode::ASYNC:
77 return "ComputeMode::ASYNC";
78 case Execution::ComputeMode::BURST:
79 return "ComputeMode::BURST";
80 case Execution::ComputeMode::FENCED:
81 return "ComputeMode::FENCED";
82 }
83 return "<unknown ComputeMode>";
84 };
85
86 std::stringstream stream;
87 stream << "useCpuOnly = " << useCpuOnly << ", computeMode = " << computeModeText()
88 << " // pass " << passIndex;
89 const std::string message = stream.str();
90 LOG(INFO) << message;
91 std::cout << "[**********] " << message << std::endl;
92 SCOPED_TRACE(message);
93
94 if (!((uint64_t(1) << passIndex) & allowedPasses)) {
95 LOG(INFO) << "SKIPPED PASS";
96 std::cout << "SKIPPED PASS" << std::endl;
97 return 0;
98 }
99
100 return RUN_ALL_TESTS();
101 }
102
checkArgs(int argc,char ** argv,int nextArg)103 void checkArgs(int argc, char** argv, int nextArg) {
104 if (nextArg != argc) {
105 std::cerr << "Unexpected argument: " << argv[nextArg] << std::endl;
106 exit(1);
107 }
108 }
109
110 } // namespace
111
main(int argc,char ** argv)112 int main(int argc, char** argv) {
113 testing::InitGoogleTest(&argc, argv);
114 testing::UnitTest::GetInstance()->listeners().Append(new android::nn::LogTestCaseToLogcat());
115
116 if ((argc > 1) && std::isdigit(argv[1][0])) {
117 allowedPasses = std::stoull(argv[1]);
118 checkArgs(argc, argv, 2);
119 } else {
120 checkArgs(argc, argv, 1);
121 }
122
123 #ifndef NNTEST_ONLY_PUBLIC_API
124 android::nn::initVLogMask();
125 #endif
126
127 int n = test(/*useCpuOnly=*/false, Execution::ComputeMode::ASYNC) |
128 test(/*useCpuOnly=*/false, Execution::ComputeMode::SYNC) |
129 test(/*useCpuOnly=*/true, Execution::ComputeMode::ASYNC) |
130 test(/*useCpuOnly=*/true, Execution::ComputeMode::SYNC);
131
132 // Now try execution using a burst.
133 //
134 // The burst path is off by default in these tests. This is the first case
135 // where it is turned on. "useCpuOnly" is irrelevant here because the burst
136 // path is separate.
137 n |= test(/*useCpuOnly=*/false, Execution::ComputeMode::BURST);
138
139 return n;
140 }
141