Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / profiler / stack_copier_signal_unittest.cc
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <string.h>
6 #include <algorithm>
7 #include <utility>
8
9 #include "base/debug/alias.h"
10 #include "base/profiler/sampling_profiler_thread_token.h"
11 #include "base/profiler/stack_buffer.h"
12 #include "base/profiler/stack_copier_signal.h"
13 #include "base/profiler/thread_delegate_posix.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/threading/platform_thread.h"
16 #include "base/threading/simple_thread.h"
17 #include "build/build_config.h"
18 #include "build/chromeos_buildflags.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace base {
22
23 namespace {
24
25 // Values to write to the stack and look for in the copy.
26 static const uint32_t kStackSentinels[] = {0xf312ecd9, 0x1fcd7f19, 0xe69e617d,
27                                            0x8245f94f};
28
29 class TargetThread : public SimpleThread {
30  public:
31   TargetThread()
32       : SimpleThread("target", Options()),
33         started_(WaitableEvent::ResetPolicy::MANUAL,
34                  WaitableEvent::InitialState::NOT_SIGNALED),
35         copy_finished_(WaitableEvent::ResetPolicy::MANUAL,
36                        WaitableEvent::InitialState::NOT_SIGNALED) {}
37
38   void Run() override {
39     thread_token_ = GetSamplingProfilerCurrentThreadToken();
40
41     // Copy the sentinel values onto the stack. Volatile to defeat compiler
42     // optimizations.
43     volatile uint32_t sentinels[std::size(kStackSentinels)];
44     for (size_t i = 0; i < std::size(kStackSentinels); ++i)
45       sentinels[i] = kStackSentinels[i];
46
47     started_.Signal();
48     copy_finished_.Wait();
49   }
50
51   SamplingProfilerThreadToken GetThreadToken() {
52     started_.Wait();
53     return thread_token_;
54   }
55
56   void NotifyCopyFinished() { copy_finished_.Signal(); }
57
58  private:
59   WaitableEvent started_;
60   WaitableEvent copy_finished_;
61   SamplingProfilerThreadToken thread_token_;
62 };
63
64 class TestStackCopierDelegate : public StackCopier::Delegate {
65  public:
66   void OnStackCopy() override {
67     on_stack_copy_was_invoked_ = true;
68   }
69
70   bool on_stack_copy_was_invoked() const { return on_stack_copy_was_invoked_; }
71
72  private:
73   bool on_stack_copy_was_invoked_ = false;
74 };
75
76 }  // namespace
77
78 // ASAN moves local variables outside of the stack extents, which breaks the
79 // sentinels.
80 // MSan complains that the memcmp() reads uninitialized memory.
81 // TSAN hangs on the AsyncSafeWaitableEvent FUTEX_WAIT call.
82 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
83     defined(THREAD_SANITIZER)
84 #define MAYBE_CopyStack DISABLED_CopyStack
85 #elif BUILDFLAG(IS_LINUX)
86 // We don't support getting the stack base address on Linux, and thus can't
87 // copy the stack. // https://crbug.com/1394278
88 #define MAYBE_CopyStack DISABLED_CopyStack
89 #else
90 #define MAYBE_CopyStack CopyStack
91 #endif
92 TEST(StackCopierSignalTest, MAYBE_CopyStack) {
93   StackBuffer stack_buffer(/* buffer_size = */ 1 << 20);
94   memset(stack_buffer.buffer(), 0, stack_buffer.size());
95   uintptr_t stack_top = 0;
96   TimeTicks timestamp;
97   RegisterContext context;
98   TestStackCopierDelegate stack_copier_delegate;
99
100   auto thread_delegate =
101       ThreadDelegatePosix::Create(GetSamplingProfilerCurrentThreadToken());
102   ASSERT_TRUE(thread_delegate);
103   StackCopierSignal copier(std::move(thread_delegate));
104
105   // Copy the sentinel values onto the stack.
106   uint32_t sentinels[std::size(kStackSentinels)];
107   for (size_t i = 0; i < std::size(kStackSentinels); ++i)
108     sentinels[i] = kStackSentinels[i];
109   base::debug::Alias((void*)sentinels);  // Defeat compiler optimizations.
110
111   bool result = copier.CopyStack(&stack_buffer, &stack_top, &timestamp,
112                                  &context, &stack_copier_delegate);
113   ASSERT_TRUE(result);
114
115   uint32_t* const end = reinterpret_cast<uint32_t*>(stack_top);
116   uint32_t* const sentinel_location = std::find_if(
117       reinterpret_cast<uint32_t*>(RegisterContextStackPointer(&context)), end,
118       [](const uint32_t& location) {
119         return memcmp(&location, &kStackSentinels[0],
120                       sizeof(kStackSentinels)) == 0;
121       });
122   EXPECT_NE(end, sentinel_location);
123 }
124
125 // TSAN hangs on the AsyncSafeWaitableEvent FUTEX_WAIT call.
126 #if defined(THREAD_SANITIZER)
127 #define MAYBE_CopyStackTimestamp DISABLED_CopyStackTimestamp
128 #elif BUILDFLAG(IS_LINUX)
129 // We don't support getting the stack base address on Linux, and thus can't
130 // copy the stack. // https://crbug.com/1394278
131 #define MAYBE_CopyStackTimestamp DISABLED_CopyStackTimestamp
132 #else
133 #define MAYBE_CopyStackTimestamp CopyStackTimestamp
134 #endif
135 TEST(StackCopierSignalTest, MAYBE_CopyStackTimestamp) {
136   StackBuffer stack_buffer(/* buffer_size = */ 1 << 20);
137   memset(stack_buffer.buffer(), 0, stack_buffer.size());
138   uintptr_t stack_top = 0;
139   TimeTicks timestamp;
140   RegisterContext context;
141   TestStackCopierDelegate stack_copier_delegate;
142
143   auto thread_delegate =
144       ThreadDelegatePosix::Create(GetSamplingProfilerCurrentThreadToken());
145   ASSERT_TRUE(thread_delegate);
146   StackCopierSignal copier(std::move(thread_delegate));
147
148   TimeTicks before = TimeTicks::Now();
149   bool result = copier.CopyStack(&stack_buffer, &stack_top, &timestamp,
150                                  &context, &stack_copier_delegate);
151   TimeTicks after = TimeTicks::Now();
152   ASSERT_TRUE(result);
153
154   EXPECT_GE(timestamp, before);
155   EXPECT_LE(timestamp, after);
156 }
157
158 // TSAN hangs on the AsyncSafeWaitableEvent FUTEX_WAIT call.
159 #if defined(THREAD_SANITIZER)
160 #define MAYBE_CopyStackDelegateInvoked DISABLED_CopyStackDelegateInvoked
161 #elif BUILDFLAG(IS_LINUX)
162 // We don't support getting the stack base address on Linux, and thus can't
163 // copy the stack. // https://crbug.com/1394278
164 #define MAYBE_CopyStackDelegateInvoked DISABLED_CopyStackDelegateInvoked
165 #else
166 #define MAYBE_CopyStackDelegateInvoked CopyStackDelegateInvoked
167 #endif
168 TEST(StackCopierSignalTest, MAYBE_CopyStackDelegateInvoked) {
169   StackBuffer stack_buffer(/* buffer_size = */ 1 << 20);
170   memset(stack_buffer.buffer(), 0, stack_buffer.size());
171   uintptr_t stack_top = 0;
172   TimeTicks timestamp;
173   RegisterContext context;
174   TestStackCopierDelegate stack_copier_delegate;
175
176   auto thread_delegate =
177       ThreadDelegatePosix::Create(GetSamplingProfilerCurrentThreadToken());
178   ASSERT_TRUE(thread_delegate);
179   StackCopierSignal copier(std::move(thread_delegate));
180
181   bool result = copier.CopyStack(&stack_buffer, &stack_top, &timestamp,
182                                  &context, &stack_copier_delegate);
183   ASSERT_TRUE(result);
184
185   EXPECT_TRUE(stack_copier_delegate.on_stack_copy_was_invoked());
186 }
187
188 // Limit to 32-bit Android, which is the platform we care about for this
189 // functionality. The test is broken on too many other varied platforms to try
190 // to selectively disable.
191 #if !(BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_32_BITS))
192 #define MAYBE_CopyStackFromOtherThread DISABLED_CopyStackFromOtherThread
193 #elif BUILDFLAG(IS_LINUX)
194 // We don't support getting the stack base address on Linux, and thus can't
195 // copy the stack. // https://crbug.com/1394278
196 #define MAYBE_CopyStackFromOtherThread DISABLED_CopyStackFromOtherThread
197 #else
198 #define MAYBE_CopyStackFromOtherThread CopyStackFromOtherThread
199 #endif
200 TEST(StackCopierSignalTest, MAYBE_CopyStackFromOtherThread) {
201   StackBuffer stack_buffer(/* buffer_size = */ 1 << 20);
202   memset(stack_buffer.buffer(), 0, stack_buffer.size());
203   uintptr_t stack_top = 0;
204   TimeTicks timestamp;
205   RegisterContext context{};
206   TestStackCopierDelegate stack_copier_delegate;
207
208   TargetThread target_thread;
209   target_thread.Start();
210   const SamplingProfilerThreadToken thread_token =
211       target_thread.GetThreadToken();
212
213   auto thread_delegate = ThreadDelegatePosix::Create(thread_token);
214   ASSERT_TRUE(thread_delegate);
215   StackCopierSignal copier(std::move(thread_delegate));
216
217   bool result = copier.CopyStack(&stack_buffer, &stack_top, &timestamp,
218                                  &context, &stack_copier_delegate);
219   ASSERT_TRUE(result);
220
221   target_thread.NotifyCopyFinished();
222   target_thread.Join();
223
224   uint32_t* const end = reinterpret_cast<uint32_t*>(stack_top);
225   uint32_t* const sentinel_location = std::find_if(
226       reinterpret_cast<uint32_t*>(RegisterContextStackPointer(&context)), end,
227       [](const uint32_t& location) {
228         return memcmp(&location, &kStackSentinels[0],
229                       sizeof(kStackSentinels)) == 0;
230       });
231   EXPECT_NE(end, sentinel_location);
232 }
233
234 }  // namespace base