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