1 // Copyright 2017 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.
5 #include "gin/public/v8_platform.h"
9 #include "base/barrier_closure.h"
10 #include "base/check_op.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/test/task_environment.h"
13 #include "base/test/test_waitable_event.h"
14 #include "base/trace_event/trace_event.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
18 class TestTraceStateObserver
19 : public v8::TracingController::TraceStateObserver {
21 void OnTraceEnabled() final { ++enabled_; }
22 void OnTraceDisabled() final { ++disabled_; }
23 int Enabled() { return enabled_; }
24 int Disabled() { return disabled_; }
30 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
34 // No TraceStateObservers in Perfetto build.
35 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
36 TEST(V8PlatformTest, TraceStateObserverAPI) {
37 TestTraceStateObserver test_observer;
38 ASSERT_EQ(0, test_observer.Enabled());
39 ASSERT_EQ(0, test_observer.Disabled());
41 V8Platform::Get()->GetTracingController()->AddTraceStateObserver(
43 base::trace_event::TraceLog::GetInstance()->SetEnabled(
44 base::trace_event::TraceConfig("*", ""),
45 base::trace_event::TraceLog::RECORDING_MODE);
46 ASSERT_EQ(1, test_observer.Enabled());
47 ASSERT_EQ(0, test_observer.Disabled());
48 base::trace_event::TraceLog::GetInstance()->SetDisabled();
49 ASSERT_EQ(1, test_observer.Enabled());
50 ASSERT_EQ(1, test_observer.Disabled());
52 V8Platform::Get()->GetTracingController()->RemoveTraceStateObserver(
54 base::trace_event::TraceLog::GetInstance()->SetEnabled(
55 base::trace_event::TraceConfig("*", ""),
56 base::trace_event::TraceLog::RECORDING_MODE);
57 base::trace_event::TraceLog::GetInstance()->SetDisabled();
58 ASSERT_EQ(1, test_observer.Enabled());
59 ASSERT_EQ(1, test_observer.Disabled());
62 TEST(V8PlatformTest, TraceStateObserverFired) {
63 TestTraceStateObserver test_observer;
64 ASSERT_EQ(0, test_observer.Enabled());
65 ASSERT_EQ(0, test_observer.Disabled());
67 base::trace_event::TraceLog::GetInstance()->SetEnabled(
68 base::trace_event::TraceConfig("*", ""),
69 base::trace_event::TraceLog::RECORDING_MODE);
70 V8Platform::Get()->GetTracingController()->AddTraceStateObserver(
72 ASSERT_EQ(1, test_observer.Enabled());
73 ASSERT_EQ(0, test_observer.Disabled());
74 V8Platform::Get()->GetTracingController()->RemoveTraceStateObserver(
77 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
79 // Tests that PostJob runs a task and is done after Join.
80 TEST(V8PlatformTest, PostJobSimple) {
81 base::test::TaskEnvironment task_environment;
82 std::atomic_size_t num_tasks_to_run(4);
83 class Task : public v8::JobTask {
85 explicit Task(std::atomic_size_t* num_tasks_to_run)
86 : num_tasks_to_run(num_tasks_to_run) {}
87 void Run(v8::JobDelegate* delegate) override { --(*num_tasks_to_run); }
89 size_t GetMaxConcurrency(size_t /* worker_count*/) const override {
90 return *num_tasks_to_run;
93 raw_ptr<std::atomic_size_t> num_tasks_to_run;
96 V8Platform::Get()->PostJob(v8::TaskPriority::kUserVisible,
97 std::make_unique<Task>(&num_tasks_to_run));
98 EXPECT_TRUE(handle->IsValid());
100 EXPECT_FALSE(handle->IsValid());
101 DCHECK_EQ(num_tasks_to_run, 0U);
104 // Tests that JobTask's lifetime is extended beyond job handle, until no
105 // references are left; and is gracefully destroyed.
106 TEST(V8PlatformTest, PostJobLifetime) {
107 std::atomic_size_t num_tasks_to_run(4);
109 base::TestWaitableEvent threads_running;
110 base::TestWaitableEvent threads_continue;
111 base::RepeatingClosure threads_running_barrier = base::BarrierClosure(
113 BindOnce(&base::TestWaitableEvent::Signal, Unretained(&threads_running)));
115 class Task : public v8::JobTask {
117 explicit Task(std::atomic_size_t* num_tasks_to_run,
118 base::RepeatingClosure threads_running_barrier,
119 base::TestWaitableEvent* threads_continue)
120 : num_tasks_to_run_(num_tasks_to_run),
121 threads_running_barrier_(std::move(threads_running_barrier)),
122 threads_continue_(threads_continue) {}
124 // This should only be destroyed once all workers returned.
125 EXPECT_EQ(*num_tasks_to_run_, 0U);
128 void Run(v8::JobDelegate* delegate) override {
129 threads_running_barrier_.Run();
130 threads_continue_->Wait();
131 --(*num_tasks_to_run_);
134 size_t GetMaxConcurrency(size_t /* worker_count*/) const override {
135 return *num_tasks_to_run_;
138 raw_ptr<std::atomic_size_t> num_tasks_to_run_;
139 base::RepeatingClosure threads_running_barrier_;
140 raw_ptr<base::TestWaitableEvent> threads_continue_;
143 base::test::TaskEnvironment task_environment;
145 auto handle = V8Platform::Get()->PostJob(
146 v8::TaskPriority::kUserVisible,
147 std::make_unique<Task>(&num_tasks_to_run,
148 std::move(threads_running_barrier),
150 EXPECT_TRUE(handle->IsValid());
151 threads_running.Wait();
152 handle->CancelAndDetach();
155 // Release workers and let the job get destroyed.
156 threads_continue.Signal();