1 /*
2  * Copyright 2020 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 #include <string>
17 
18 #include "ClientConfig.pb.h"
19 #include "LocalPrebuiltGraph.h"
20 #include "PrebuiltEngineInterface.h"
21 #include "PrebuiltEngineInterfaceImpl.h"
22 #include "ProfilingType.pb.h"
23 #include "RunnerComponent.h"
24 #include "gmock/gmock-matchers.h"
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "types/Status.h"
28 
29 using ::android::automotive::computepipe::runner::ClientConfig;
30 using ::android::automotive::computepipe::runner::RunnerComponentInterface;
31 using ::android::automotive::computepipe::runner::RunnerEvent;
32 using ::testing::HasSubstr;
33 
34 namespace android {
35 namespace automotive {
36 namespace computepipe {
37 namespace graph {
38 namespace {
39 
40 // The stub graph implementation is a passthrough implementation that does not run
41 // any graph and returns success for all implementations. The only useful things that
42 // it does for the tests are
43 //
44 //    1. Stores the name of the function last visited and returns that with GetErrorMessage call
45 //    2. When an input stream is set, it immediately returns an output callback with the same input
46 //       data and timestamp. Similar callback is issued for when input stream pixel data is set too
47 //
48 // The above two properties are used to test that the prebuilt graph wrapper calls the correct
49 // functions and callbacks are issued as expected. These tests do not test the internals of the
50 // graph themselves and such tests must be written along with the graph implementation.
TEST(LocalPrebuiltGraphTest,FunctionMappingFromLibraryIsSuccessful)51 TEST(LocalPrebuiltGraphTest, FunctionMappingFromLibraryIsSuccessful) {
52     PrebuiltEngineInterfaceImpl callback;
53     std::shared_ptr<PrebuiltEngineInterface> engineInterface =
54             std::static_pointer_cast<PrebuiltEngineInterface, PrebuiltEngineInterfaceImpl>(
55                     std::make_shared<PrebuiltEngineInterfaceImpl>(callback));
56     PrebuiltGraph* graph = GetLocalGraphFromLibrary("libstubgraphimpl.so", engineInterface);
57     ASSERT_TRUE(graph);
58     EXPECT_EQ(graph->GetGraphType(), PrebuiltGraphType::LOCAL);
59     EXPECT_NE(graph->GetGraphState(), PrebuiltGraphState::UNINITIALIZED);
60     EXPECT_EQ(graph->GetSupportedGraphConfigs().graph_name(), "stub_graph");
61 }
62 
TEST(LocalPrebuiltGraphTest,GraphConfigurationIssuesCorrectFunctionCalls)63 TEST(LocalPrebuiltGraphTest, GraphConfigurationIssuesCorrectFunctionCalls) {
64     PrebuiltEngineInterfaceImpl callback;
65     std::shared_ptr<PrebuiltEngineInterface> engineInterface =
66             std::static_pointer_cast<PrebuiltEngineInterface, PrebuiltEngineInterfaceImpl>(
67                     std::make_shared<PrebuiltEngineInterfaceImpl>(callback));
68     PrebuiltGraph* graph = GetLocalGraphFromLibrary("libstubgraphimpl.so", engineInterface);
69     ASSERT_TRUE(graph);
70     EXPECT_EQ(graph->GetGraphType(), PrebuiltGraphType::LOCAL);
71     ASSERT_NE(graph->GetGraphState(), PrebuiltGraphState::UNINITIALIZED);
72 
73     graph->GetSupportedGraphConfigs();
74     std::string functionVisited = graph->GetErrorMessage();
75     EXPECT_THAT(functionVisited, HasSubstr("GetSupportedGraphConfigs"));
76 
77     std::map<int, int> maxOutputPacketsPerStream;
78     ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
79     e.setPhaseState(runner::PhaseState::ENTRY);
80     EXPECT_EQ(graph->handleConfigPhase(e), Status::SUCCESS);
81     functionVisited = graph->GetErrorMessage();
82 
83     EXPECT_EQ(graph->GetStatus(), Status::SUCCESS);
84     functionVisited = graph->GetErrorMessage();
85     EXPECT_THAT(functionVisited, HasSubstr("GetErrorCode"));
86 }
87 
TEST(LocalPrebuiltGraphTest,GraphOperationEndToEndIsSuccessful)88 TEST(LocalPrebuiltGraphTest, GraphOperationEndToEndIsSuccessful) {
89     bool graphHasTerminated = false;
90     int numOutputStreamCallbacksReceived[4] = {0, 0, 0, 0};
91 
92     PrebuiltEngineInterfaceImpl callback;
93     callback.SetGraphTerminationCallback(
94             [&graphHasTerminated](Status, std::string) { graphHasTerminated = true; });
95 
96     // Add multiple pixel stream callback functions to see if all of them register.
97     callback.SetPixelCallback([&numOutputStreamCallbacksReceived](int streamIndex, int64_t,
98                                                                   const runner::InputFrame&) {
99         ASSERT_TRUE(streamIndex == 0 || streamIndex == 1);
100         numOutputStreamCallbacksReceived[streamIndex]++;
101     });
102 
103     // Add multiple stream callback functions to see if all of them register.
104     callback.SetSerializedStreamCallback(
105             [&numOutputStreamCallbacksReceived](int streamIndex, int64_t, std::string&&) {
106                 ASSERT_TRUE(streamIndex == 2 || streamIndex == 3);
107                 numOutputStreamCallbacksReceived[streamIndex]++;
108             });
109 
110     std::shared_ptr<PrebuiltEngineInterface> engineInterface =
111             std::static_pointer_cast<PrebuiltEngineInterface, PrebuiltEngineInterfaceImpl>(
112                     std::make_shared<PrebuiltEngineInterfaceImpl>(callback));
113 
114     PrebuiltGraph* graph = GetLocalGraphFromLibrary("libstubgraphimpl.so", engineInterface);
115 
116     EXPECT_EQ(graph->GetGraphType(), PrebuiltGraphType::LOCAL);
117     ASSERT_NE(graph->GetGraphState(), PrebuiltGraphState::UNINITIALIZED);
118 
119     graph->GetSupportedGraphConfigs();
120     std::string functionVisited = graph->GetErrorMessage();
121     EXPECT_THAT(functionVisited, HasSubstr("GetSupportedGraphConfigs"));
122 
123     std::map<int, int> maxOutputPacketsPerStream;
124     ClientConfig e(0, 0, 0, maxOutputPacketsPerStream, proto::ProfilingType::DISABLED);
125     e.setPhaseState(runner::PhaseState::ENTRY);
126     EXPECT_EQ(graph->handleConfigPhase(e), Status::SUCCESS);
127     functionVisited = graph->GetErrorMessage();
128 
129     EXPECT_EQ(graph->handleExecutionPhase(e), Status::SUCCESS);
130     functionVisited = graph->GetErrorMessage();
131     EXPECT_THAT(functionVisited, HasSubstr("StartGraphExecution"));
132 
133     runner::InputFrame inputFrame(0, 0, PixelFormat::RGB, 0, nullptr);
134     EXPECT_EQ(graph->SetInputStreamPixelData(
135                       /*streamIndex =*/0, /*timestamp =*/0, /*inputFrame =*/inputFrame),
136               Status::SUCCESS);
137     EXPECT_EQ(graph->SetInputStreamPixelData(
138                       /*streamIndex =*/0, /*timestamp =*/0, /*inputFrame =*/inputFrame),
139               Status::SUCCESS);
140     EXPECT_EQ(graph->SetInputStreamPixelData(
141                       /*streamIndex =*/0, /*timestamp =*/0, /*inputFrame =*/inputFrame),
142               Status::SUCCESS);
143     EXPECT_EQ(graph->SetInputStreamPixelData(
144                       /*streamIndex =*/1, /*timestamp =*/0, /*inputFrame =*/inputFrame),
145               Status::SUCCESS);
146     EXPECT_EQ(graph->SetInputStreamPixelData(
147                       /*streamIndex =*/1, /*timestamp =*/0, /*inputFrame =*/inputFrame),
148               Status::SUCCESS);
149     functionVisited = graph->GetErrorMessage();
150     EXPECT_THAT(functionVisited, HasSubstr("SetInputStreamPixelData"));
151 
152     EXPECT_EQ(graph->SetInputStreamData(/*streamIndex =*/2, /* timestamp =*/0, /* data =*/""),
153               Status::SUCCESS);
154     EXPECT_EQ(graph->SetInputStreamData(/*streamIndex =*/2, /* timestamp =*/0, /* data =*/""),
155               Status::SUCCESS);
156     EXPECT_EQ(graph->SetInputStreamData(/*streamIndex =*/2, /* timestamp =*/0, /* data =*/""),
157               Status::SUCCESS);
158     EXPECT_EQ(graph->SetInputStreamData(/*streamIndex =*/3, /* timestamp =*/0, /* data =*/""),
159               Status::SUCCESS);
160     EXPECT_EQ(graph->SetInputStreamData(/*streamIndex =*/3, /* timestamp =*/0, /* data =*/""),
161               Status::SUCCESS);
162     functionVisited = graph->GetErrorMessage();
163     EXPECT_THAT(functionVisited, HasSubstr("SetInputStreamData"));
164 
165     EXPECT_EQ(numOutputStreamCallbacksReceived[0], 3);
166     EXPECT_EQ(numOutputStreamCallbacksReceived[1], 2);
167     EXPECT_EQ(numOutputStreamCallbacksReceived[2], 3);
168     EXPECT_EQ(numOutputStreamCallbacksReceived[3], 2);
169 
170     EXPECT_FALSE(graphHasTerminated);
171     EXPECT_EQ(graph->handleStopImmediatePhase(e), Status::SUCCESS);
172 
173     EXPECT_EQ(graph->handleResetPhase(e), Status::SUCCESS);
174     functionVisited = graph->GetErrorMessage();
175     EXPECT_THAT(functionVisited, HasSubstr("ResetGraph"));
176 
177     EXPECT_TRUE(graphHasTerminated);
178 }
179 
180 }  // namespace
181 }  // namespace graph
182 }  // namespace computepipe
183 }  // namespace automotive
184 }  // namespace android
185