xref: /aosp_15_r20/external/perfetto/src/tracing/test/api_test_support.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 "src/tracing/test/api_test_support.h"
18 
19 #include "perfetto/base/compiler.h"
20 #include "perfetto/base/proc_utils.h"
21 #include "perfetto/base/time.h"
22 #include "perfetto/ext/base/string_utils.h"
23 #include "perfetto/ext/base/temp_file.h"
24 #include "perfetto/tracing/internal/basic_types.h"
25 #include "src/tracing/internal/tracing_muxer_impl.h"
26 
27 #include <sstream>
28 
29 #if PERFETTO_BUILDFLAG(PERFETTO_IPC)
30 #include "test/test_helper.h"
31 #endif
32 
33 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
34 #include <Windows.h>
35 #endif
36 
37 namespace perfetto {
38 namespace test {
39 
40 using internal::TracingMuxerImpl;
41 
42 #if PERFETTO_BUILDFLAG(PERFETTO_IPC)
43 namespace {
44 
45 class InProcessSystemService {
46  public:
InProcessSystemService()47   InProcessSystemService()
48       : test_helper_(&task_runner_, TestHelper::Mode::kStartDaemons) {
49     // Will always start service because we explicitly set kStartDaemons.
50     test_helper_.StartServiceIfRequired();
51   }
52 
CleanEnv()53   void CleanEnv() { test_helper_.CleanEnv(); }
54 
Restart()55   void Restart() { test_helper_.RestartService(); }
56 
57  private:
58   perfetto::base::TestTaskRunner task_runner_;
59   perfetto::TestHelper test_helper_;
60 };
61 
62 InProcessSystemService* g_system_service = nullptr;
63 
64 }  // namespace
65 
66 // static
Start()67 SystemService SystemService::Start() {
68   // If there already was a system service running, make sure the new one is
69   // running before tearing down the old one. This avoids a 1 second
70   // reconnection delay between each test since the connection to the new
71   // service succeeds immediately.
72   std::unique_ptr<InProcessSystemService> old_service(g_system_service);
73   if (old_service) {
74     old_service->CleanEnv();
75   }
76   g_system_service = new InProcessSystemService();
77 
78   // Tear down the service at process exit to make sure temporary files get
79   // deleted.
80   static bool cleanup_registered;
81   if (!cleanup_registered) {
82     atexit([] { delete g_system_service; });
83     cleanup_registered = true;
84   }
85   SystemService ret;
86   ret.valid_ = true;
87   return ret;
88 }
89 
Clean()90 void SystemService::Clean() {
91   if (valid_) {
92     if (g_system_service) {
93       // Does not really stop. We want to reuse the service in future tests. It
94       // is important to clean the environment variables, though.
95       g_system_service->CleanEnv();
96     }
97   }
98   valid_ = false;
99 }
100 
Restart()101 void SystemService::Restart() {
102   PERFETTO_CHECK(valid_);
103   g_system_service->Restart();
104 }
105 #else   // !PERFETTO_BUILDFLAG(PERFETTO_IPC)
106 // static
Start()107 SystemService SystemService::Start() {
108   return SystemService();
109 }
Clean()110 void SystemService::Clean() {
111   valid_ = false;
112 }
Restart()113 void SystemService::Restart() {
114   valid_ = false;
115 }
116 #endif  // !PERFETTO_BUILDFLAG(PERFETTO_IPC)
117 
operator =(SystemService && other)118 SystemService& SystemService::operator=(SystemService&& other) noexcept {
119   PERFETTO_CHECK(!valid_ || !other.valid_);
120   Clean();
121   valid_ = other.valid_;
122   other.valid_ = false;
123   return *this;
124 }
125 
GetCurrentProcessId()126 int32_t GetCurrentProcessId() {
127   return static_cast<int32_t>(base::GetProcessId());
128 }
129 
SyncProducers()130 void SyncProducers() {
131   auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
132       perfetto::internal::TracingMuxer::Get());
133   muxer->SyncProducersForTesting();
134 }
135 
SetBatchCommitsDuration(uint32_t batch_commits_duration_ms,BackendType backend_type)136 void SetBatchCommitsDuration(uint32_t batch_commits_duration_ms,
137                              BackendType backend_type) {
138   auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
139       perfetto::internal::TracingMuxer::Get());
140   muxer->SetBatchCommitsDurationForTesting(batch_commits_duration_ms,
141                                            backend_type);
142 }
143 
DisableReconnectLimit()144 void DisableReconnectLimit() {
145   auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
146       perfetto::internal::TracingMuxer::Get());
147   muxer->SetMaxProducerReconnectionsForTesting(
148       std::numeric_limits<uint32_t>::max());
149 }
150 
EnableDirectSMBPatching(BackendType backend_type)151 bool EnableDirectSMBPatching(BackendType backend_type) {
152   auto* muxer = reinterpret_cast<perfetto::internal::TracingMuxerImpl*>(
153       perfetto::internal::TracingMuxer::Get());
154   return muxer->EnableDirectSMBPatchingForTesting(backend_type);
155 }
156 
CreateTempFile()157 TestTempFile CreateTempFile() {
158   TestTempFile res{};
159 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
160   base::StackString<255> temp_file("%s\\perfetto-XXXXXX", getenv("TMP"));
161   PERFETTO_CHECK(_mktemp_s(temp_file.mutable_data(), temp_file.len() + 1) == 0);
162   HANDLE handle =
163       ::CreateFileA(temp_file.c_str(), GENERIC_READ | GENERIC_WRITE,
164                     FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, CREATE_ALWAYS,
165                     FILE_ATTRIBUTE_TEMPORARY, nullptr);
166   PERFETTO_CHECK(handle && handle != INVALID_HANDLE_VALUE);
167   res.fd = _open_osfhandle(reinterpret_cast<intptr_t>(handle), 0);
168   res.path = temp_file.ToStdString();
169 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
170   char temp_file[] = "/data/local/tmp/perfetto-XXXXXXXX";
171   res.fd = mkstemp(temp_file);
172   res.path = temp_file;
173 #else
174   char temp_file[] = "/tmp/perfetto-XXXXXXXX";
175   res.fd = mkstemp(temp_file);
176   res.path = temp_file;
177 #endif
178   PERFETTO_CHECK(res.fd > 0);
179   return res;
180 }
181 
182 // static
DoesSystemBackendHaveSMB()183 bool TracingMuxerImplInternalsForTest::DoesSystemBackendHaveSMB() {
184   using RegisteredProducerBackend = TracingMuxerImpl::RegisteredProducerBackend;
185   // Ideally we should be doing dynamic_cast and a DCHECK(muxer != nullptr);
186   auto* muxer =
187       reinterpret_cast<TracingMuxerImpl*>(TracingMuxerImpl::instance_);
188   const auto& backends = muxer->producer_backends_;
189   const auto& backend =
190       std::find_if(backends.begin(), backends.end(),
191                    [](const RegisteredProducerBackend& r_backend) {
192                      return r_backend.type == kSystemBackend;
193                    });
194   if (backend == backends.end())
195     return false;
196   const auto& service = backend->producer->service_;
197   return service && service->shared_memory();
198 }
199 
200 // static
ClearIncrementalState()201 void TracingMuxerImplInternalsForTest::ClearIncrementalState() {
202   auto* muxer =
203       reinterpret_cast<TracingMuxerImpl*>(TracingMuxerImpl::instance_);
204   for (const auto& data_source : muxer->data_sources_) {
205     for (uint32_t inst_idx = 0; inst_idx < internal::kMaxDataSourceInstances;
206          inst_idx++) {
207       internal::DataSourceState* ds_static_state =
208           data_source.static_state->TryGet(inst_idx);
209       if (ds_static_state) {
210         ds_static_state->incremental_state_generation.fetch_add(
211             1, std::memory_order_relaxed);
212       }
213     }
214   }
215 }
216 
217 // static
AppendResetForTestingCallback(std::function<void ()> f)218 void TracingMuxerImplInternalsForTest::AppendResetForTestingCallback(
219     std::function<void()> f) {
220   auto* muxer =
221       reinterpret_cast<TracingMuxerImpl*>(TracingMuxerImpl::instance_);
222   muxer->AppendResetForTestingCallback(f);
223 }
224 
225 }  // namespace test
226 }  // namespace perfetto
227