1 /*
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 #include <android/binder_auto_utils.h>
18 #include <android/binder_manager.h>
19 #include <binder/ProcessState.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include <aidl/android/aidl/tests/ITestService.h>
24 
25 using aidl::android::aidl::tests::BackendType;
26 using aidl::android::aidl::tests::ITestService;
27 using testing::Eq;
28 
29 struct AidlTest : testing::Test {
30   template <typename T>
getServiceAidlTest31   std::shared_ptr<T> getService() {
32     android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
33     android::ProcessState::self()->startThreadPool();
34     ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_waitForService(T::descriptor));
35     return T::fromBinder(binder);
36   }
SetUpAidlTest37   void SetUp() override {
38     service = getService<ITestService>();
39     auto status = service->getBackendType(&backend);
40     ASSERT_TRUE(status.isOk()) << status.getDescription();
41   }
42   std::shared_ptr<ITestService> service;
43   BackendType backend;
44 };
45 
TEST_F(AidlTest,repeatUtf8String)46 TEST_F(AidlTest, repeatUtf8String) {
47   const std::vector<std::string> utf8_inputs = {
48       std::string("Deliver us from evil."),
49       std::string(),
50       std::string("\0\0", 2),
51       // Similarly, the utf8 encodings of the small letter yee and euro sign.
52       std::string("\xF0\x90\x90\xB7\xE2\x82\xAC"),
53       ITestService::STRING_CONSTANT_UTF8,
54   };
55 
56   for (const auto& input : utf8_inputs) {
57     std::string reply;
58     auto status = service->RepeatUtf8CppString(input, &reply);
59     ASSERT_TRUE(status.isOk());
60     ASSERT_THAT(reply, Eq(input));
61   }
62 
63   std::optional<std::string> reply;
64   auto status = service->RepeatNullableUtf8CppString(std::nullopt, &reply);
65   ASSERT_TRUE(status.isOk());
66   ASSERT_FALSE(reply.has_value());
67 
68   for (const auto& input : utf8_inputs) {
69     std::optional<std::string> reply;
70     auto status = service->RepeatNullableUtf8CppString(input, &reply);
71     ASSERT_TRUE(status.isOk());
72     ASSERT_TRUE(reply.has_value());
73     ASSERT_THAT(*reply, Eq(input));
74   }
75 }
76 
TEST_F(AidlTest,reverseUtf8StringArray)77 TEST_F(AidlTest, reverseUtf8StringArray) {
78   std::vector<std::string> input = {"a", "", "\xc3\xb8"};
79   decltype(input) repeated;
80   if (backend == BackendType::JAVA) {
81     repeated = decltype(input)(input.size());
82   }
83   decltype(input) reversed;
84 
85   auto status = service->ReverseUtf8CppString(input, &repeated, &reversed);
86   ASSERT_TRUE(status.isOk()) << status.getDescription();
87   ASSERT_THAT(repeated, Eq(input));
88 
89   decltype(input) reversed_input(input);
90   std::reverse(reversed_input.begin(), reversed_input.end());
91   ASSERT_THAT(reversed, Eq(reversed_input));
92 }
93 
94 struct AidlStringArrayTest : public AidlTest {
DoTestAidlStringArrayTest95   void DoTest(::ndk::ScopedAStatus (ITestService::*func)(
96       const std::optional<std::vector<std::optional<std::string>>>&,
97       std::optional<std::vector<std::optional<std::string>>>*,
98       std::optional<std::vector<std::optional<std::string>>>*)) {
99     std::optional<std::vector<std::optional<std::string>>> input;
100     decltype(input) repeated;
101     decltype(input) reversed;
102 
103     auto status = (*service.*func)(input, &repeated, &reversed);
104     ASSERT_TRUE(status.isOk()) << status.getDescription();
105 
106     if (func == &ITestService::ReverseUtf8CppStringList && backend == BackendType::JAVA) {
107       // Java cannot clear the input variable to return a null value. It can
108       // only ever fill out a list.
109       ASSERT_TRUE(repeated.has_value());
110     } else {
111       ASSERT_FALSE(repeated.has_value());
112     }
113 
114     ASSERT_FALSE(reversed.has_value());
115 
116     input = std::vector<std::optional<std::string>>();
117     input->push_back("Deliver us from evil.");
118     input->push_back(std::nullopt);
119     input->push_back("\xF0\x90\x90\xB7\xE2\x82\xAC");
120 
121     // usable size needs to be initialized for Java
122     repeated = std::vector<std::optional<std::string>>(input->size());
123 
124     status = (*service.*func)(input, &repeated, &reversed);
125     ASSERT_TRUE(status.isOk()) << status.getDescription();
126     ASSERT_TRUE(reversed.has_value());
127     ASSERT_TRUE(repeated.has_value());
128     ASSERT_THAT(reversed->size(), Eq(input->size()));
129     ASSERT_THAT(repeated->size(), Eq(input->size()));
130 
131     for (size_t i = 0; i < input->size(); i++) {
132       auto input_str = (*input)[i];
133       auto repeated_str = (*repeated)[i];
134       auto reversed_str = (*reversed)[(reversed->size() - 1) - i];
135       if (!input_str) {
136         ASSERT_FALSE(repeated_str.has_value());
137         ASSERT_FALSE(reversed_str.has_value());
138         // 3 nullptrs to strings.  No need to compare values.
139         continue;
140       }
141       ASSERT_TRUE(repeated_str.has_value());
142       ASSERT_TRUE(reversed_str.has_value());
143 
144       ASSERT_THAT(*repeated_str, Eq(*input_str));
145       ASSERT_THAT(*reversed_str, Eq(*input_str));
146     }
147   }
148 };
149 
TEST_F(AidlStringArrayTest,nullableList)150 TEST_F(AidlStringArrayTest, nullableList) {
151   DoTest(&ITestService::ReverseUtf8CppStringList);
152 }
153 
TEST_F(AidlStringArrayTest,nullableArray)154 TEST_F(AidlStringArrayTest, nullableArray) {
155   DoTest(&ITestService::ReverseNullableUtf8CppString);
156 }
157