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