• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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