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