1 /*
2  * Copyright (C) 2019 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 <errno.h>
18 
19 #include <algorithm>
20 #include <iostream>
21 #include <memory>
22 #include <string>
23 #include <type_traits>
24 #include <vector>
25 
26 #if defined(TRUSTY_USERSPACE)
27 #include <trusty_unittest.h>
28 #else
29 #include <lib/unittest/unittest.h>
30 #include <lk/trusty_unittest.h>
31 #endif
32 
33 int global_count;
34 
35 #define CHECK_ERRNO(e)       \
36     do {                     \
37         ASSERT_EQ(e, errno); \
38         errno = 0;           \
39     } while (0)
40 #define CLEAR_ERRNO() \
41     do {              \
42         errno = 0;    \
43     } while (0)
44 
45 typedef struct libcxx {
46 } libcxx_t;
47 
TEST_F_SETUP(libcxx)48 TEST_F_SETUP(libcxx) {
49     /* Isolate the tests. */
50     CLEAR_ERRNO();
51     global_count = 0;
52 }
53 
TEST_F_TEARDOWN(libcxx)54 TEST_F_TEARDOWN(libcxx) {
55     /* errno should have been checked and cleared if the test sets errno. */
56     CHECK_ERRNO(0);
57     ASSERT_EQ(0, global_count);
58 
59 test_abort:
60     global_count = 0;
61 }
62 
63 class Stub {};
64 
TEST_F(libcxx,new_and_delete)65 TEST_F(libcxx, new_and_delete) {
66     Stub* tmp = new Stub();
67     ASSERT_NE(nullptr, tmp);
68     delete tmp;
69 test_abort:;
70 }
71 
72 /*
73  * NOTE currently -fno-threadsafe-statics is suppressing threadsafe statics.
74  * When this is no longer the case, this test will link against __cxa_guard_*.
75  * This test is mainly checking that static initializers are executed only once
76  * and that all required ABI functions are provided. Thread safety is outside
77  * the scope of this test.
78  */
static_stub_getter()79 static Stub* static_stub_getter() {
80     static Stub* d = new Stub();
81     return d;
82 }
83 
TEST_F(libcxx,safe_static)84 TEST_F(libcxx, safe_static) {
85     ASSERT_NE(nullptr, static_stub_getter());
86     ASSERT_EQ(static_stub_getter(), static_stub_getter());
87 
88 test_abort:;
89 }
90 
91 /*
92  * Inspecting the generated code, it appears this variable can be optimized out
93  * if it is not declared volatile.
94  */
95 volatile bool did_init;
96 
97 class GlobalSetter {
98 public:
GlobalSetter()99     GlobalSetter() { did_init = true; }
100 };
101 
102 GlobalSetter setter;
103 
TEST_F(libcxx,global_constructor)104 TEST_F(libcxx, global_constructor) {
105     /* Did a global constructor run? */
106     ASSERT_EQ(true, did_init);
107 test_abort:;
108 }
109 
110 class Counter {
111 public:
Counter()112     Counter() { global_count++; }
113 
Counter(const Counter & other)114     Counter(const Counter& other) { global_count++; }
115 
~Counter()116     ~Counter() { global_count--; }
117 };
118 
TEST_F(libcxx,unique_ptr)119 TEST_F(libcxx, unique_ptr) {
120     ASSERT_EQ(0, global_count);
121     {
122         std::unique_ptr<Counter> u(new Counter());
123         ASSERT_EQ(1, global_count);
124     }
125     ASSERT_EQ(0, global_count);
126 test_abort:;
127 }
128 
TEST_F(libcxx,unique_ptr_move)129 TEST_F(libcxx, unique_ptr_move) {
130     Counter* p = new Counter();
131     std::unique_ptr<Counter> a(p);
132     std::unique_ptr<Counter> b;
133 
134     ASSERT_EQ(1, global_count);
135     ASSERT_EQ(p, a.get());
136     ASSERT_EQ(nullptr, b.get());
137 
138     b = std::move(a);
139 
140     ASSERT_EQ(1, global_count);
141     ASSERT_EQ(nullptr, a.get());
142     ASSERT_EQ(p, b.get());
143 
144     b.reset();
145     ASSERT_EQ(0, global_count);
146     ASSERT_EQ(nullptr, b.get());
147 
148 test_abort:;
149 }
150 
TEST_F(libcxx,shared_ptr)151 TEST_F(libcxx, shared_ptr) {
152     std::shared_ptr<Counter> a;
153     std::shared_ptr<Counter> b;
154     ASSERT_EQ(0, global_count);
155     a.reset(new Counter());
156     ASSERT_EQ(1, global_count);
157     b = a;
158     ASSERT_EQ(1, global_count);
159     ASSERT_NE(nullptr, a.get());
160     ASSERT_EQ(a.get(), b.get());
161     a.reset();
162     ASSERT_EQ(1, global_count);
163     b.reset();
164     ASSERT_EQ(0, global_count);
165 
166 test_abort:;
167 }
168 
TEST_F(libcxx,shared_ptr_move)169 TEST_F(libcxx, shared_ptr_move) {
170     Counter* p = new Counter();
171     std::shared_ptr<Counter> a(p);
172     std::shared_ptr<Counter> b;
173 
174     ASSERT_EQ(1, global_count);
175     ASSERT_EQ(p, a.get());
176     ASSERT_EQ(nullptr, b.get());
177 
178     b = std::move(a);
179 
180     ASSERT_EQ(1, global_count);
181     ASSERT_EQ(nullptr, a.get());
182     ASSERT_EQ(p, b.get());
183 
184     b.reset();
185     ASSERT_EQ(0, global_count);
186     ASSERT_EQ(nullptr, b.get());
187 
188 test_abort:;
189 }
190 
TEST_F(libcxx,weak_ptr)191 TEST_F(libcxx, weak_ptr) {
192     std::weak_ptr<Counter> w;
193     ASSERT_EQ(0, global_count);
194     {
195         std::shared_ptr<Counter> s(new Counter());
196         w = s;
197         ASSERT_EQ(1, global_count);
198         ASSERT_EQ(1, w.use_count());
199         {
200             auto t = w.lock();
201             ASSERT_EQ(1, global_count);
202             ASSERT_EQ(2, w.use_count());
203             ASSERT_EQ(s.get(), t.get());
204         }
205         ASSERT_EQ(1, global_count);
206         ASSERT_EQ(1, w.use_count());
207     }
208     ASSERT_EQ(0, global_count);
209     ASSERT_EQ(0, w.use_count());
210 
211 test_abort:;
212 }
213 
TEST_F(libcxx,weak_ptr_move)214 TEST_F(libcxx, weak_ptr_move) {
215     std::shared_ptr<Counter> s(new Counter());
216     std::weak_ptr<Counter> a(s);
217     std::weak_ptr<Counter> b;
218 
219     ASSERT_EQ(1, global_count);
220     ASSERT_EQ(1, a.use_count());
221     ASSERT_EQ(0, b.use_count());
222 
223     b = std::move(a);
224 
225     ASSERT_EQ(1, global_count);
226     ASSERT_EQ(0, a.use_count());
227     ASSERT_EQ(1, b.use_count());
228 
229     s.reset();
230 
231     ASSERT_EQ(0, global_count);
232     ASSERT_EQ(0, b.use_count());
233 
234 test_abort:;
235 }
236 
237 // TODO test framework does not compare anything that can't be cast to long.
TEST_F(libcxx,string_append)238 TEST_F(libcxx, string_append) {
239     std::string a("abcdefghijklmnopqrstuvwxyz!!!");
240     std::string b("abcdefghijklmnopqrstuvwxyz");
241     ASSERT_NE(0, strcmp(a.c_str(), b.c_str()));
242     b += "!!!";
243     ASSERT_EQ(0, strcmp(a.c_str(), b.c_str()));
244 
245 test_abort:;
246 }
247 
TEST_F(libcxx,string_move)248 TEST_F(libcxx, string_move) {
249     std::string a("foo");
250     std::string b;
251     ASSERT_EQ(0, strcmp(a.c_str(), "foo"));
252     ASSERT_NE(0, strcmp(b.c_str(), "foo"));
253 
254     b = std::move(a);
255 
256     ASSERT_NE(0, strcmp(a.c_str(), "foo"));
257     ASSERT_EQ(0, strcmp(b.c_str(), "foo"));
258 
259 test_abort:;
260 }
261 
TEST_F(libcxx,to_string)262 TEST_F(libcxx, to_string) {
263     ASSERT_EQ(0, strcmp(std::to_string(123).c_str(), "123"));
264 
265 test_abort:;
266 }
267 
TEST_F(libcxx,vector)268 TEST_F(libcxx, vector) {
269     const int limit = 20;
270     std::vector<int> v = {1, 2, 3, 4, 5, 6, 7};
271     for (int i = 8; i <= limit; ++i) {
272         v.push_back(i);
273     }
274     int sum = 0;
275     for (auto it = v.begin(); it != v.end(); ++it) {
276         sum += *it;
277     }
278     ASSERT_EQ(limit * (limit + 1) / 2, sum);
279 
280 test_abort:;
281 }
282 
TEST_F(libcxx,vector_move)283 TEST_F(libcxx, vector_move) {
284     std::vector<Counter> a(3);
285     std::vector<Counter> b;
286 
287     EXPECT_EQ(3, global_count);
288     EXPECT_EQ(3U, a.size());
289     EXPECT_EQ(0U, b.size());
290 
291     b = std::move(a);
292 
293     // Note: can't say much about the state of "a".
294     EXPECT_EQ(3U, b.size());
295 
296     a = {};
297     b = {};
298 
299     EXPECT_EQ(0, global_count);
300 
301 test_abort:;
302 }
303 
304 // libcxx's headers "extern template" common parameterizations of std::sort.
305 // These parameterizations must be explicitly instantiated inside libcxx or
306 // else there will be a link error.
TEST_F(libcxx,vector_sort)307 TEST_F(libcxx, vector_sort) {
308     std::vector<int> v = {2, 3, 1};
309     std::sort(v.begin(), v.end());
310 
311     EXPECT_EQ(1, v[0]);
312     EXPECT_EQ(2, v[1]);
313     EXPECT_EQ(3, v[2]);
314 
315 test_abort:;
316 }
317 
318 // Make sure a simple use of cout can compile and run.
TEST_F(libcxx,iostream_smoke_test)319 TEST_F(libcxx, iostream_smoke_test) {
320     std::cout << "Hello, world. " << 123 << "!" << std::endl;
321 }
322 
323 class Parent {};
324 
325 class Child : Parent {};
326 
327 class Stranger {};
328 
329 // Do we have full C++17 support?
TEST_F(libcxx,is_base_of_v)330 TEST_F(libcxx, is_base_of_v) {
331     // Extra parentheses needed because templates create lexical ambiguity for
332     // preprocessor.
333     EXPECT_EQ(true, (std::is_base_of_v<Parent, Parent>));
334     EXPECT_EQ(true, (std::is_base_of_v<Child, Child>));
335     EXPECT_EQ(true, (std::is_base_of_v<Stranger, Stranger>));
336     EXPECT_EQ(true, (std::is_base_of_v<Parent, Child>));
337     EXPECT_EQ(false, (std::is_base_of_v<Child, Parent>));
338     EXPECT_EQ(false, (std::is_base_of_v<Parent, Stranger>));
339     EXPECT_EQ(false, (std::is_base_of_v<Stranger, Parent>));
340     EXPECT_EQ(false, (std::is_base_of_v<Child, Stranger>));
341     EXPECT_EQ(false, (std::is_base_of_v<Stranger, Child>));
342 }
343 
344 #if defined(TRUSTY_USERSPACE)
345 PORT_TEST(libcxx, "com.android.libcxxtest");
346 #else
347 PORT_TEST(libcxx, "com.android.kernel.libcxxtest");
348 #endif
349