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