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