xref: /aosp_15_r20/external/perfetto/src/base/utils_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
20*6dbdd20aSAndroid Build Coastguard Worker 
21*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
22*6dbdd20aSAndroid Build Coastguard Worker #include <Windows.h>
23*6dbdd20aSAndroid Build Coastguard Worker #else
24*6dbdd20aSAndroid Build Coastguard Worker #include <fcntl.h>
25*6dbdd20aSAndroid Build Coastguard Worker #include <signal.h>
26*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
27*6dbdd20aSAndroid Build Coastguard Worker #endif
28*6dbdd20aSAndroid Build Coastguard Worker 
29*6dbdd20aSAndroid Build Coastguard Worker #include <stdint.h>
30*6dbdd20aSAndroid Build Coastguard Worker 
31*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
32*6dbdd20aSAndroid Build Coastguard Worker #include <random>
33*6dbdd20aSAndroid Build Coastguard Worker #include <thread>
34*6dbdd20aSAndroid Build Coastguard Worker 
35*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
36*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/pipe.h"
37*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/temp_file.h"
38*6dbdd20aSAndroid Build Coastguard Worker #include "test/gtest_and_gmock.h"
39*6dbdd20aSAndroid Build Coastguard Worker 
40*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
41*6dbdd20aSAndroid Build Coastguard Worker namespace base {
42*6dbdd20aSAndroid Build Coastguard Worker namespace {
43*6dbdd20aSAndroid Build Coastguard Worker 
TEST(UtilsTest,ArraySize)44*6dbdd20aSAndroid Build Coastguard Worker TEST(UtilsTest, ArraySize) {
45*6dbdd20aSAndroid Build Coastguard Worker   char char_arr_1[1];
46*6dbdd20aSAndroid Build Coastguard Worker   char char_arr_4[4];
47*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, ArraySize(char_arr_1));
48*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, ArraySize(char_arr_4));
49*6dbdd20aSAndroid Build Coastguard Worker 
50*6dbdd20aSAndroid Build Coastguard Worker   int32_t int32_arr_1[1];
51*6dbdd20aSAndroid Build Coastguard Worker   int32_t int32_arr_4[4];
52*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, ArraySize(int32_arr_1));
53*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, ArraySize(int32_arr_4));
54*6dbdd20aSAndroid Build Coastguard Worker 
55*6dbdd20aSAndroid Build Coastguard Worker   uint64_t int64_arr_1[1];
56*6dbdd20aSAndroid Build Coastguard Worker   uint64_t int64_arr_4[4];
57*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, ArraySize(int64_arr_1));
58*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, ArraySize(int64_arr_4));
59*6dbdd20aSAndroid Build Coastguard Worker 
60*6dbdd20aSAndroid Build Coastguard Worker   char kString[] = "foo";
61*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, ArraySize(kString));
62*6dbdd20aSAndroid Build Coastguard Worker 
63*6dbdd20aSAndroid Build Coastguard Worker   struct Bar {
64*6dbdd20aSAndroid Build Coastguard Worker     int32_t a;
65*6dbdd20aSAndroid Build Coastguard Worker     int32_t b;
66*6dbdd20aSAndroid Build Coastguard Worker   };
67*6dbdd20aSAndroid Build Coastguard Worker   Bar bar_1[1];
68*6dbdd20aSAndroid Build Coastguard Worker   Bar bar_4[4];
69*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(1u, ArraySize(bar_1));
70*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, ArraySize(bar_4));
71*6dbdd20aSAndroid Build Coastguard Worker }
72*6dbdd20aSAndroid Build Coastguard Worker 
TEST(UtilsTest,PipeBlockingRW)73*6dbdd20aSAndroid Build Coastguard Worker TEST(UtilsTest, PipeBlockingRW) {
74*6dbdd20aSAndroid Build Coastguard Worker   Pipe pipe = Pipe::Create();
75*6dbdd20aSAndroid Build Coastguard Worker   std::string expected;
76*6dbdd20aSAndroid Build Coastguard Worker   expected.resize(1024 * 512u);
77*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < expected.size(); i++)
78*6dbdd20aSAndroid Build Coastguard Worker     expected[i] = '!' + static_cast<char>(i % 64);
79*6dbdd20aSAndroid Build Coastguard Worker 
80*6dbdd20aSAndroid Build Coastguard Worker   std::thread writer([&] {
81*6dbdd20aSAndroid Build Coastguard Worker     std::string tx = expected;
82*6dbdd20aSAndroid Build Coastguard Worker     std::minstd_rand0 rnd_engine(0);
83*6dbdd20aSAndroid Build Coastguard Worker 
84*6dbdd20aSAndroid Build Coastguard Worker     while (!tx.empty()) {
85*6dbdd20aSAndroid Build Coastguard Worker       size_t wsize = static_cast<size_t>(rnd_engine() % 4096) + 1;
86*6dbdd20aSAndroid Build Coastguard Worker       wsize = std::min(wsize, tx.size());
87*6dbdd20aSAndroid Build Coastguard Worker       WriteAllHandle(*pipe.wr, &tx[0], wsize);
88*6dbdd20aSAndroid Build Coastguard Worker       tx.erase(0, wsize);
89*6dbdd20aSAndroid Build Coastguard Worker     }
90*6dbdd20aSAndroid Build Coastguard Worker     pipe.wr.reset();
91*6dbdd20aSAndroid Build Coastguard Worker   });
92*6dbdd20aSAndroid Build Coastguard Worker 
93*6dbdd20aSAndroid Build Coastguard Worker   std::string actual;
94*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_TRUE(ReadPlatformHandle(*pipe.rd, &actual));
95*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(actual, expected);
96*6dbdd20aSAndroid Build Coastguard Worker   writer.join();
97*6dbdd20aSAndroid Build Coastguard Worker }
98*6dbdd20aSAndroid Build Coastguard Worker 
99*6dbdd20aSAndroid Build Coastguard Worker // Tests that WriteAllHandle and ReadPlatformHandle work as advertised.
100*6dbdd20aSAndroid Build Coastguard Worker // TODO(primiano): normalize File handling on Windows. Right now some places
101*6dbdd20aSAndroid Build Coastguard Worker // use POSIX-compat APIs that use "int" file descriptors (_open, _read, _write),
102*6dbdd20aSAndroid Build Coastguard Worker // some other places use WINAPI files (CreateFile(), ReadFile()), where the file
103*6dbdd20aSAndroid Build Coastguard Worker // is a HANDLE.
TEST(UtilsTest,ReadWritePlatformHandle)104*6dbdd20aSAndroid Build Coastguard Worker TEST(UtilsTest, ReadWritePlatformHandle) {
105*6dbdd20aSAndroid Build Coastguard Worker   auto tmp = TempDir::Create();
106*6dbdd20aSAndroid Build Coastguard Worker   std::string payload = "foo\nbar\0baz\r\nqux";
107*6dbdd20aSAndroid Build Coastguard Worker   std::string tmp_path = tmp.path() + "/temp.txt";
108*6dbdd20aSAndroid Build Coastguard Worker 
109*6dbdd20aSAndroid Build Coastguard Worker   // Write a file using PlatformHandle. Note: the {} blocks are to make sure
110*6dbdd20aSAndroid Build Coastguard Worker   // that the file is automatically closed via RAII before being reopened.
111*6dbdd20aSAndroid Build Coastguard Worker   {
112*6dbdd20aSAndroid Build Coastguard Worker     ScopedPlatformHandle handle {
113*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
114*6dbdd20aSAndroid Build Coastguard Worker       ::CreateFileA(tmp_path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
115*6dbdd20aSAndroid Build Coastguard Worker                     FILE_ATTRIBUTE_NORMAL, nullptr)
116*6dbdd20aSAndroid Build Coastguard Worker #else
117*6dbdd20aSAndroid Build Coastguard Worker       OpenFile(tmp_path, O_WRONLY | O_CREAT | O_TRUNC, 0644)
118*6dbdd20aSAndroid Build Coastguard Worker #endif
119*6dbdd20aSAndroid Build Coastguard Worker     };
120*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(handle);
121*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(WriteAllHandle(*handle, payload.data(), payload.size()),
122*6dbdd20aSAndroid Build Coastguard Worker               static_cast<ssize_t>(payload.size()));
123*6dbdd20aSAndroid Build Coastguard Worker   }
124*6dbdd20aSAndroid Build Coastguard Worker 
125*6dbdd20aSAndroid Build Coastguard Worker   // Read it back.
126*6dbdd20aSAndroid Build Coastguard Worker   {
127*6dbdd20aSAndroid Build Coastguard Worker     ScopedPlatformHandle handle {
128*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
129*6dbdd20aSAndroid Build Coastguard Worker       ::CreateFileA(tmp_path.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING,
130*6dbdd20aSAndroid Build Coastguard Worker                     FILE_ATTRIBUTE_NORMAL, nullptr)
131*6dbdd20aSAndroid Build Coastguard Worker #else
132*6dbdd20aSAndroid Build Coastguard Worker       OpenFile(tmp_path, O_RDONLY)
133*6dbdd20aSAndroid Build Coastguard Worker #endif
134*6dbdd20aSAndroid Build Coastguard Worker     };
135*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(handle);
136*6dbdd20aSAndroid Build Coastguard Worker     std::string actual = "preserve_existing:";
137*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_TRUE(ReadPlatformHandle(*handle, &actual));
138*6dbdd20aSAndroid Build Coastguard Worker     ASSERT_EQ(actual, "preserve_existing:" + payload);
139*6dbdd20aSAndroid Build Coastguard Worker   }
140*6dbdd20aSAndroid Build Coastguard Worker 
141*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(remove(tmp_path.c_str()), 0);
142*6dbdd20aSAndroid Build Coastguard Worker }
143*6dbdd20aSAndroid Build Coastguard Worker 
144*6dbdd20aSAndroid Build Coastguard Worker // Fuchsia doesn't currently support sigaction(), see
145*6dbdd20aSAndroid Build Coastguard Worker // https://fxbug.dev/42105390 .
146*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
147*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
148*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
TEST(UtilsTest,EintrWrapper)149*6dbdd20aSAndroid Build Coastguard Worker TEST(UtilsTest, EintrWrapper) {
150*6dbdd20aSAndroid Build Coastguard Worker   Pipe pipe = Pipe::Create();
151*6dbdd20aSAndroid Build Coastguard Worker 
152*6dbdd20aSAndroid Build Coastguard Worker   struct sigaction sa = {};
153*6dbdd20aSAndroid Build Coastguard Worker   struct sigaction old_sa = {};
154*6dbdd20aSAndroid Build Coastguard Worker 
155*6dbdd20aSAndroid Build Coastguard Worker // Glibc headers for sa_sigaction trigger this.
156*6dbdd20aSAndroid Build Coastguard Worker #pragma GCC diagnostic push
157*6dbdd20aSAndroid Build Coastguard Worker #if defined(__clang__)
158*6dbdd20aSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
159*6dbdd20aSAndroid Build Coastguard Worker #endif
160*6dbdd20aSAndroid Build Coastguard Worker   sa.sa_sigaction = [](int, siginfo_t*, void*) {};
161*6dbdd20aSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
162*6dbdd20aSAndroid Build Coastguard Worker 
163*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_EQ(0, sigaction(SIGUSR2, &sa, &old_sa));
164*6dbdd20aSAndroid Build Coastguard Worker   int parent_pid = getpid();
165*6dbdd20aSAndroid Build Coastguard Worker   pid_t pid = fork();
166*6dbdd20aSAndroid Build Coastguard Worker   ASSERT_NE(-1, pid);
167*6dbdd20aSAndroid Build Coastguard Worker   if (pid == 0 /* child */) {
168*6dbdd20aSAndroid Build Coastguard Worker     usleep(5000);
169*6dbdd20aSAndroid Build Coastguard Worker     kill(parent_pid, SIGUSR2);
170*6dbdd20aSAndroid Build Coastguard Worker     ignore_result(WriteAll(*pipe.wr, "foo\0", 4));
171*6dbdd20aSAndroid Build Coastguard Worker     _exit(0);
172*6dbdd20aSAndroid Build Coastguard Worker   }
173*6dbdd20aSAndroid Build Coastguard Worker 
174*6dbdd20aSAndroid Build Coastguard Worker   char buf[6] = {};
175*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4, PERFETTO_EINTR(read(*pipe.rd, buf, sizeof(buf))));
176*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_TRUE(close(*pipe.rd) == 0 || errno == EINTR);
177*6dbdd20aSAndroid Build Coastguard Worker   pipe.wr.reset();
178*6dbdd20aSAndroid Build Coastguard Worker 
179*6dbdd20aSAndroid Build Coastguard Worker   // A 2nd close should fail with the proper errno.
180*6dbdd20aSAndroid Build Coastguard Worker   int res = close(*pipe.rd);
181*6dbdd20aSAndroid Build Coastguard Worker   auto err = errno;
182*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(-1, res);
183*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(EBADF, err);
184*6dbdd20aSAndroid Build Coastguard Worker   pipe.rd.release();
185*6dbdd20aSAndroid Build Coastguard Worker 
186*6dbdd20aSAndroid Build Coastguard Worker   // Restore the old handler.
187*6dbdd20aSAndroid Build Coastguard Worker   sigaction(SIGUSR2, &old_sa, nullptr);
188*6dbdd20aSAndroid Build Coastguard Worker }
189*6dbdd20aSAndroid Build Coastguard Worker #endif  // LINUX | ANDROID | APPLE
190*6dbdd20aSAndroid Build Coastguard Worker 
TEST(UtilsTest,Align)191*6dbdd20aSAndroid Build Coastguard Worker TEST(UtilsTest, Align) {
192*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, AlignUp<4>(0));
193*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, AlignUp<4>(1));
194*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, AlignUp<4>(3));
195*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(4u, AlignUp<4>(4));
196*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(8u, AlignUp<4>(5));
197*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(0u, AlignUp<16>(0));
198*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(16u, AlignUp<16>(1));
199*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(16u, AlignUp<16>(15));
200*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(16u, AlignUp<16>(16));
201*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(32u, AlignUp<16>(17));
202*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(0xffffff00u, AlignUp<16>(0xffffff00 - 1));
203*6dbdd20aSAndroid Build Coastguard Worker }
204*6dbdd20aSAndroid Build Coastguard Worker 
TEST(UtilsTest,HexDump)205*6dbdd20aSAndroid Build Coastguard Worker TEST(UtilsTest, HexDump) {
206*6dbdd20aSAndroid Build Coastguard Worker   char input[] = {0x00, 0x00, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
207*6dbdd20aSAndroid Build Coastguard Worker                   'h',  'i',  'j', 'k', 'l', 'm', 'n', 'o', 'p'};
208*6dbdd20aSAndroid Build Coastguard Worker 
209*6dbdd20aSAndroid Build Coastguard Worker   std::string output = HexDump(input, sizeof(input));
210*6dbdd20aSAndroid Build Coastguard Worker 
211*6dbdd20aSAndroid Build Coastguard Worker   EXPECT_EQ(
212*6dbdd20aSAndroid Build Coastguard Worker       output,
213*6dbdd20aSAndroid Build Coastguard Worker       R"(00000000: 00 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E   ..abcdefghijklmn
214*6dbdd20aSAndroid Build Coastguard Worker 00000010: 6F 70                                             op
215*6dbdd20aSAndroid Build Coastguard Worker )");
216*6dbdd20aSAndroid Build Coastguard Worker }
217*6dbdd20aSAndroid Build Coastguard Worker 
218*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
219*6dbdd20aSAndroid Build Coastguard Worker }  // namespace base
220*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
221