Line data Source code
1 : // Copyright 2008 the V8 project authors. All rights reserved.
2 : // Redistribution and use in source and binary forms, with or without
3 : // modification, are permitted provided that the following conditions are
4 : // met:
5 : //
6 : // * Redistributions of source code must retain the above copyright
7 : // notice, this list of conditions and the following disclaimer.
8 : // * Redistributions in binary form must reproduce the above
9 : // copyright notice, this list of conditions and the following
10 : // disclaimer in the documentation and/or other materials provided
11 : // with the distribution.
12 : // * Neither the name of Google Inc. nor the names of its
13 : // contributors may be used to endorse or promote products derived
14 : // from this software without specific prior written permission.
15 : //
16 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 :
28 : #ifndef CCTEST_H_
29 : #define CCTEST_H_
30 :
31 : #include <memory>
32 :
33 : #include "include/libplatform/libplatform.h"
34 : #include "include/v8-platform.h"
35 : #include "src/debug/debug-interface.h"
36 : #include "src/factory.h"
37 : #include "src/flags.h"
38 : #include "src/isolate.h"
39 : #include "src/objects.h"
40 : #include "src/utils.h"
41 : #include "src/v8.h"
42 : #include "src/zone/accounting-allocator.h"
43 :
44 : namespace v8 {
45 : namespace base {
46 :
47 : class RandomNumberGenerator;
48 :
49 : } // namespace base
50 :
51 : namespace internal {
52 :
53 : class HandleScope;
54 : class Zone;
55 :
56 : } // namespace internal
57 :
58 : } // namespace v8
59 :
60 : #ifndef TEST
61 : #define TEST(Name) \
62 : static void Test##Name(); \
63 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, true); \
64 : static void Test##Name()
65 : #endif
66 :
67 : #ifndef UNINITIALIZED_TEST
68 : #define UNINITIALIZED_TEST(Name) \
69 : static void Test##Name(); \
70 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, false); \
71 : static void Test##Name()
72 : #endif
73 :
74 : #ifndef DISABLED_TEST
75 : #define DISABLED_TEST(Name) \
76 : static void Test##Name(); \
77 : CcTest register_test_##Name(Test##Name, __FILE__, #Name, false, true); \
78 : static void Test##Name()
79 : #endif
80 :
81 : #define EXTENSION_LIST(V) \
82 : V(GC_EXTENSION, "v8/gc") \
83 : V(PRINT_EXTENSION, "v8/print") \
84 : V(PROFILER_EXTENSION, "v8/profiler") \
85 : V(TRACE_EXTENSION, "v8/trace")
86 :
87 : #define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
88 : enum CcTestExtensionIds {
89 : EXTENSION_LIST(DEFINE_EXTENSION_ID)
90 : kMaxExtensions
91 : };
92 : #undef DEFINE_EXTENSION_ID
93 :
94 : typedef v8::internal::EnumSet<CcTestExtensionIds> CcTestExtensionFlags;
95 : #define DEFINE_EXTENSION_FLAG(Name, Ident) \
96 : static const CcTestExtensionFlags Name(1 << Name##_ID);
97 : static const CcTestExtensionFlags NO_EXTENSIONS(0);
98 : static const CcTestExtensionFlags ALL_EXTENSIONS((1 << kMaxExtensions) - 1);
99 : EXTENSION_LIST(DEFINE_EXTENSION_FLAG)
100 : #undef DEFINE_EXTENSION_FLAG
101 :
102 :
103 : class CcTest {
104 : public:
105 : typedef void (TestFunction)();
106 : CcTest(TestFunction* callback, const char* file, const char* name,
107 : bool enabled, bool initialize);
108 203737620 : ~CcTest() { i::DeleteArray(file_); }
109 : void Run();
110 30437 : static CcTest* last() { return last_; }
111 : CcTest* prev() { return prev_; }
112 : const char* file() { return file_; }
113 : const char* name() { return name_; }
114 : bool enabled() { return enabled_; }
115 :
116 8664469 : static v8::Isolate* isolate() {
117 8664469 : CHECK_NOT_NULL(isolate_);
118 : v8::base::Relaxed_Store(&isolate_used_, 1);
119 8664469 : return isolate_;
120 : }
121 :
122 4075587 : static i::Isolate* InitIsolateOnce() {
123 4075587 : if (!initialize_called_) InitializeVM();
124 4075587 : return i_isolate();
125 : }
126 :
127 : static i::Isolate* i_isolate() {
128 8496396 : return reinterpret_cast<i::Isolate*>(isolate());
129 : }
130 :
131 : static i::Heap* heap();
132 :
133 : static void CollectGarbage(i::AllocationSpace space);
134 : static void CollectAllGarbage();
135 : static void CollectAllGarbage(int flags);
136 : static void CollectAllAvailableGarbage();
137 :
138 : static v8::base::RandomNumberGenerator* random_number_generator();
139 :
140 : static v8::Local<v8::Object> global();
141 :
142 : static v8::ArrayBuffer::Allocator* array_buffer_allocator() {
143 1181 : return allocator_;
144 : }
145 :
146 : static void set_array_buffer_allocator(
147 : v8::ArrayBuffer::Allocator* allocator) {
148 23718 : allocator_ = allocator;
149 : }
150 :
151 : // TODO(dcarney): Remove.
152 : // This must be called first in a test.
153 : static void InitializeVM();
154 :
155 : // Only for UNINITIALIZED_TESTs
156 : static void DisableAutomaticDispose();
157 :
158 : // Helper function to configure a context.
159 : // Must be in a HandleScope.
160 : static v8::Local<v8::Context> NewContext(
161 : CcTestExtensionFlags extensions,
162 : v8::Isolate* isolate = CcTest::isolate());
163 :
164 : static void TearDown();
165 :
166 : private:
167 : friend int main(int argc, char** argv);
168 : TestFunction* callback_;
169 : const char* file_;
170 : const char* name_;
171 : bool enabled_;
172 : bool initialize_;
173 : CcTest* prev_;
174 : static CcTest* last_;
175 : static v8::ArrayBuffer::Allocator* allocator_;
176 : static v8::Isolate* isolate_;
177 : static bool initialize_called_;
178 : static v8::base::Atomic32 isolate_used_;
179 : };
180 :
181 : // Switches between all the Api tests using the threading support.
182 : // In order to get a surprising but repeatable pattern of thread
183 : // switching it has extra semaphores to control the order in which
184 : // the tests alternate, not relying solely on the big V8 lock.
185 : //
186 : // A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
187 : // callbacks. This will have no effect when we are not running the
188 : // thread fuzzing test. In the thread fuzzing test it will
189 : // pseudorandomly select a successor thread and switch execution
190 : // to that thread, suspending the current test.
191 : class ApiTestFuzzer: public v8::base::Thread {
192 : public:
193 : void CallTest();
194 :
195 : // The ApiTestFuzzer is also a Thread, so it has a Run method.
196 : virtual void Run();
197 :
198 : enum PartOfTest {
199 : FIRST_PART,
200 : SECOND_PART,
201 : THIRD_PART,
202 : FOURTH_PART,
203 : FIFTH_PART,
204 : SIXTH_PART,
205 : SEVENTH_PART,
206 : EIGHTH_PART,
207 : LAST_PART = EIGHTH_PART
208 : };
209 :
210 : static void SetUp(PartOfTest part);
211 : static void RunAllTests();
212 : static void TearDown();
213 : // This method switches threads if we are running the Threading test.
214 : // Otherwise it does nothing.
215 : static void Fuzz();
216 :
217 : private:
218 471 : explicit ApiTestFuzzer(int num)
219 : : Thread(Options("ApiTestFuzzer")),
220 : test_number_(num),
221 : gate_(0),
222 471 : active_(true) {}
223 0 : ~ApiTestFuzzer() {}
224 :
225 : static bool fuzzing_;
226 : static int tests_being_run_;
227 : static int current_;
228 : static int active_tests_;
229 : static bool NextThread();
230 : int test_number_;
231 : v8::base::Semaphore gate_;
232 : bool active_;
233 : void ContextSwitch();
234 : static int GetNextTestNumber();
235 : static v8::base::Semaphore all_tests_done_;
236 : };
237 :
238 :
239 : #define THREADED_TEST(Name) \
240 : static void Test##Name(); \
241 : RegisterThreadedTest register_##Name(Test##Name, #Name); \
242 : /* */ TEST(Name)
243 :
244 :
245 : class RegisterThreadedTest {
246 : public:
247 : explicit RegisterThreadedTest(CcTest::TestFunction* callback,
248 : const char* name)
249 11171178 : : fuzzer_(nullptr), callback_(callback), name_(name) {
250 11171178 : prev_ = first_;
251 11171178 : first_ = this;
252 11171178 : count_++;
253 : }
254 3376241 : static int count() { return count_; }
255 3372457 : static RegisterThreadedTest* nth(int i) {
256 3372457 : CHECK(i < count());
257 3372457 : RegisterThreadedTest* current = first_;
258 106143653 : while (i > 0) {
259 99398739 : i--;
260 99398739 : current = current->prev_;
261 : }
262 3372457 : return current;
263 : }
264 : CcTest::TestFunction* callback() { return callback_; }
265 : ApiTestFuzzer* fuzzer_;
266 : const char* name() { return name_; }
267 :
268 : private:
269 : static RegisterThreadedTest* first_;
270 : static int count_;
271 : CcTest::TestFunction* callback_;
272 : RegisterThreadedTest* prev_;
273 : const char* name_;
274 : };
275 :
276 : // A LocalContext holds a reference to a v8::Context.
277 : class LocalContext {
278 : public:
279 : LocalContext(v8::Isolate* isolate, v8::ExtensionConfiguration* extensions = 0,
280 : v8::Local<v8::ObjectTemplate> global_template =
281 : v8::Local<v8::ObjectTemplate>(),
282 2167 : v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
283 2167 : Initialize(isolate, extensions, global_template, global_object);
284 : }
285 :
286 7566 : LocalContext(v8::ExtensionConfiguration* extensions = 0,
287 : v8::Local<v8::ObjectTemplate> global_template =
288 : v8::Local<v8::ObjectTemplate>(),
289 7566 : v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
290 7566 : Initialize(CcTest::isolate(), extensions, global_template, global_object);
291 7566 : }
292 :
293 : virtual ~LocalContext();
294 :
295 : v8::Context* operator->() {
296 67602 : return *reinterpret_cast<v8::Context**>(&context_);
297 : }
298 : v8::Context* operator*() { return operator->(); }
299 : bool IsReady() { return !context_.IsEmpty(); }
300 :
301 68261 : v8::Local<v8::Context> local() {
302 136522 : return v8::Local<v8::Context>::New(isolate_, context_);
303 : }
304 :
305 : private:
306 : void Initialize(v8::Isolate* isolate, v8::ExtensionConfiguration* extensions,
307 : v8::Local<v8::ObjectTemplate> global_template,
308 : v8::Local<v8::Value> global_object);
309 :
310 : v8::Persistent<v8::Context> context_;
311 : v8::Isolate* isolate_;
312 : };
313 :
314 :
315 119 : static inline uint16_t* AsciiToTwoByteString(const char* source) {
316 119 : int array_length = i::StrLength(source) + 1;
317 119 : uint16_t* converted = i::NewArray<uint16_t>(array_length);
318 119 : for (int i = 0; i < array_length; i++) converted[i] = source[i];
319 119 : return converted;
320 : }
321 :
322 : template <typename T>
323 72 : static inline i::Handle<T> GetGlobal(const char* name) {
324 : i::Isolate* isolate = CcTest::i_isolate();
325 : i::Handle<i::String> str_name =
326 72 : isolate->factory()->InternalizeUtf8String(name);
327 :
328 : i::Handle<i::Object> value =
329 144 : i::Object::GetProperty(isolate->global_object(), str_name)
330 144 : .ToHandleChecked();
331 72 : return i::Handle<T>::cast(value);
332 : }
333 :
334 15067 : static inline v8::Local<v8::Value> v8_num(double x) {
335 15067 : return v8::Number::New(v8::Isolate::GetCurrent(), x);
336 : }
337 :
338 : static inline v8::Local<v8::Integer> v8_int(int32_t x) {
339 17 : return v8::Integer::New(v8::Isolate::GetCurrent(), x);
340 : }
341 :
342 418630 : static inline v8::Local<v8::String> v8_str(const char* x) {
343 : return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x,
344 418630 : v8::NewStringType::kNormal)
345 837260 : .ToLocalChecked();
346 : }
347 :
348 :
349 1803 : static inline v8::Local<v8::String> v8_str(v8::Isolate* isolate,
350 : const char* x) {
351 : return v8::String::NewFromUtf8(isolate, x, v8::NewStringType::kNormal)
352 3606 : .ToLocalChecked();
353 : }
354 :
355 :
356 5 : static inline v8::Local<v8::Symbol> v8_symbol(const char* name) {
357 5 : return v8::Symbol::New(v8::Isolate::GetCurrent(), v8_str(name));
358 : }
359 :
360 :
361 79016 : static inline v8::Local<v8::Script> v8_compile(v8::Local<v8::String> x) {
362 : v8::Local<v8::Script> result;
363 158032 : if (v8::Script::Compile(v8::Isolate::GetCurrent()->GetCurrentContext(), x)
364 79016 : .ToLocal(&result)) {
365 79006 : return result;
366 : }
367 10 : return v8::Local<v8::Script>();
368 : }
369 :
370 :
371 : static inline v8::Local<v8::Script> v8_compile(const char* x) {
372 2178 : return v8_compile(v8_str(x));
373 : }
374 :
375 :
376 2054 : static inline int32_t v8_run_int32value(v8::Local<v8::Script> script) {
377 2054 : v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
378 6162 : return script->Run(context).ToLocalChecked()->Int32Value(context).FromJust();
379 : }
380 :
381 :
382 50 : static inline v8::Local<v8::Script> CompileWithOrigin(
383 : v8::Local<v8::String> source, v8::Local<v8::String> origin_url) {
384 : v8::ScriptOrigin origin(origin_url);
385 : v8::ScriptCompiler::Source script_source(source, origin);
386 : return v8::ScriptCompiler::Compile(
387 50 : v8::Isolate::GetCurrent()->GetCurrentContext(), &script_source)
388 100 : .ToLocalChecked();
389 : }
390 :
391 :
392 : static inline v8::Local<v8::Script> CompileWithOrigin(
393 : v8::Local<v8::String> source, const char* origin_url) {
394 18 : return CompileWithOrigin(source, v8_str(origin_url));
395 : }
396 :
397 :
398 21 : static inline v8::Local<v8::Script> CompileWithOrigin(const char* source,
399 : const char* origin_url) {
400 21 : return CompileWithOrigin(v8_str(source), v8_str(origin_url));
401 : }
402 :
403 :
404 : // Helper functions that compile and run the source.
405 271 : static inline v8::MaybeLocal<v8::Value> CompileRun(
406 : v8::Local<v8::Context> context, const char* source) {
407 271 : return v8::Script::Compile(context, v8_str(source))
408 271 : .ToLocalChecked()
409 271 : ->Run(context);
410 : }
411 :
412 :
413 972 : static inline v8::Local<v8::Value> CompileRunChecked(v8::Isolate* isolate,
414 : const char* source) {
415 : v8::Local<v8::String> source_string =
416 : v8::String::NewFromUtf8(isolate, source, v8::NewStringType::kNormal)
417 1944 : .ToLocalChecked();
418 972 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
419 : v8::Local<v8::Script> script =
420 972 : v8::Script::Compile(context, source_string).ToLocalChecked();
421 1944 : return script->Run(context).ToLocalChecked();
422 : }
423 :
424 :
425 76700 : static inline v8::Local<v8::Value> CompileRun(v8::Local<v8::String> source) {
426 : v8::Local<v8::Value> result;
427 76700 : if (v8_compile(source)
428 153400 : ->Run(v8::Isolate::GetCurrent()->GetCurrentContext())
429 76700 : .ToLocal(&result)) {
430 74050 : return result;
431 : }
432 2650 : return v8::Local<v8::Value>();
433 : }
434 :
435 :
436 : // Helper functions that compile and run the source.
437 : static inline v8::Local<v8::Value> CompileRun(const char* source) {
438 75431 : return CompileRun(v8_str(source));
439 : }
440 :
441 :
442 165 : static inline v8::Local<v8::Value> CompileRun(
443 : v8::Local<v8::Context> context, v8::ScriptCompiler::Source* script_source,
444 : v8::ScriptCompiler::CompileOptions options) {
445 : v8::Local<v8::Value> result;
446 165 : if (v8::ScriptCompiler::Compile(context, script_source, options)
447 165 : .ToLocalChecked()
448 : ->Run(context)
449 165 : .ToLocal(&result)) {
450 145 : return result;
451 : }
452 20 : return v8::Local<v8::Value>();
453 : }
454 :
455 :
456 20 : static inline v8::Local<v8::Value> ParserCacheCompileRun(const char* source) {
457 : // Compile once just to get the preparse data, then compile the second time
458 : // using the data.
459 20 : v8::Isolate* isolate = v8::Isolate::GetCurrent();
460 20 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
461 20 : v8::ScriptCompiler::Source script_source(v8_str(source));
462 : v8::ScriptCompiler::Compile(context, &script_source,
463 : v8::ScriptCompiler::kProduceParserCache)
464 20 : .ToLocalChecked();
465 :
466 : // Check whether we received cached data, and if so use it.
467 : v8::ScriptCompiler::CompileOptions options =
468 20 : script_source.GetCachedData() ? v8::ScriptCompiler::kConsumeParserCache
469 20 : : v8::ScriptCompiler::kNoCompileOptions;
470 :
471 40 : return CompileRun(context, &script_source, options);
472 : }
473 :
474 :
475 : // Helper functions that compile and run the source with given origin.
476 60 : static inline v8::Local<v8::Value> CompileRunWithOrigin(const char* source,
477 : const char* origin_url,
478 : int line_number,
479 : int column_number) {
480 60 : v8::Isolate* isolate = v8::Isolate::GetCurrent();
481 60 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
482 : v8::ScriptOrigin origin(v8_str(origin_url),
483 : v8::Integer::New(isolate, line_number),
484 60 : v8::Integer::New(isolate, column_number));
485 60 : v8::ScriptCompiler::Source script_source(v8_str(source), origin);
486 : return CompileRun(context, &script_source,
487 120 : v8::ScriptCompiler::CompileOptions());
488 : }
489 :
490 :
491 35 : static inline v8::Local<v8::Value> CompileRunWithOrigin(
492 : v8::Local<v8::String> source, const char* origin_url) {
493 35 : v8::Isolate* isolate = v8::Isolate::GetCurrent();
494 35 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
495 : v8::ScriptCompiler::Source script_source(
496 35 : source, v8::ScriptOrigin(v8_str(origin_url)));
497 : return CompileRun(context, &script_source,
498 70 : v8::ScriptCompiler::CompileOptions());
499 : }
500 :
501 :
502 : static inline v8::Local<v8::Value> CompileRunWithOrigin(
503 : const char* source, const char* origin_url) {
504 25 : return CompileRunWithOrigin(v8_str(source), origin_url);
505 : }
506 :
507 :
508 :
509 759 : static inline void ExpectString(const char* code, const char* expected) {
510 : v8::Local<v8::Value> result = CompileRun(code);
511 759 : CHECK(result->IsString());
512 759 : v8::String::Utf8Value utf8(v8::Isolate::GetCurrent(), result);
513 759 : CHECK_EQ(0, strcmp(expected, *utf8));
514 759 : }
515 :
516 :
517 1250 : static inline void ExpectInt32(const char* code, int expected) {
518 : v8::Local<v8::Value> result = CompileRun(code);
519 1250 : CHECK(result->IsInt32());
520 2500 : CHECK_EQ(expected,
521 : result->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext())
522 : .FromJust());
523 1250 : }
524 :
525 :
526 932 : static inline void ExpectBoolean(const char* code, bool expected) {
527 : v8::Local<v8::Value> result = CompileRun(code);
528 932 : CHECK(result->IsBoolean());
529 1864 : CHECK_EQ(expected,
530 : result->BooleanValue(v8::Isolate::GetCurrent()->GetCurrentContext())
531 : .FromJust());
532 932 : }
533 :
534 :
535 : static inline void ExpectTrue(const char* code) {
536 256 : ExpectBoolean(code, true);
537 : }
538 :
539 :
540 : static inline void ExpectFalse(const char* code) {
541 89 : ExpectBoolean(code, false);
542 : }
543 :
544 :
545 92 : static inline void ExpectObject(const char* code,
546 : v8::Local<v8::Value> expected) {
547 : v8::Local<v8::Value> result = CompileRun(code);
548 92 : CHECK(result->SameValue(expected));
549 92 : }
550 :
551 :
552 45 : static inline void ExpectUndefined(const char* code) {
553 : v8::Local<v8::Value> result = CompileRun(code);
554 45 : CHECK(result->IsUndefined());
555 45 : }
556 :
557 :
558 : static inline void ExpectNull(const char* code) {
559 : v8::Local<v8::Value> result = CompileRun(code);
560 : CHECK(result->IsNull());
561 : }
562 :
563 :
564 5 : static inline void CheckDoubleEquals(double expected, double actual) {
565 : const double kEpsilon = 1e-10;
566 10 : CHECK_LE(expected, actual + kEpsilon);
567 10 : CHECK_GE(expected, actual - kEpsilon);
568 5 : }
569 :
570 3866034 : static v8::debug::DebugDelegate dummy_delegate;
571 :
572 : static inline void EnableDebugger(v8::Isolate* isolate) {
573 20 : v8::debug::SetDebugDelegate(isolate, &dummy_delegate);
574 : }
575 :
576 :
577 : static inline void DisableDebugger(v8::Isolate* isolate) {
578 15 : v8::debug::SetDebugDelegate(isolate, nullptr);
579 : }
580 :
581 :
582 23552 : static inline void EmptyMessageQueues(v8::Isolate* isolate) {
583 62059 : while (v8::platform::PumpMessageLoop(v8::internal::V8::GetCurrentPlatform(),
584 38507 : isolate)) {
585 : }
586 23552 : }
587 :
588 : class InitializedHandleScopeImpl;
589 :
590 : class InitializedHandleScope {
591 : public:
592 : InitializedHandleScope();
593 : ~InitializedHandleScope();
594 :
595 : // Prefixing the below with main_ reduces a lot of naming clashes.
596 : i::Isolate* main_isolate() { return main_isolate_; }
597 :
598 : private:
599 : i::Isolate* main_isolate_;
600 : std::unique_ptr<InitializedHandleScopeImpl> initialized_handle_scope_impl_;
601 : };
602 :
603 : class HandleAndZoneScope : public InitializedHandleScope {
604 : public:
605 : HandleAndZoneScope();
606 : ~HandleAndZoneScope();
607 :
608 : // Prefixing the below with main_ reduces a lot of naming clashes.
609 : i::Zone* main_zone() { return main_zone_.get(); }
610 :
611 : private:
612 : v8::internal::AccountingAllocator allocator_;
613 : std::unique_ptr<i::Zone> main_zone_;
614 : };
615 :
616 : class StaticOneByteResource : public v8::String::ExternalOneByteStringResource {
617 : public:
618 5 : explicit StaticOneByteResource(const char* data) : data_(data) {}
619 :
620 10 : ~StaticOneByteResource() {}
621 :
622 10 : const char* data() const { return data_; }
623 :
624 15 : size_t length() const { return strlen(data_); }
625 :
626 : private:
627 : const char* data_;
628 : };
629 :
630 : class ManualGCScope {
631 : public:
632 : ManualGCScope()
633 : : flag_concurrent_marking_(i::FLAG_concurrent_marking),
634 : flag_concurrent_sweeping_(i::FLAG_concurrent_sweeping),
635 265 : flag_stress_incremental_marking_(i::FLAG_stress_incremental_marking) {
636 265 : i::FLAG_concurrent_marking = false;
637 265 : i::FLAG_concurrent_sweeping = false;
638 265 : i::FLAG_stress_incremental_marking = false;
639 : }
640 : ~ManualGCScope() {
641 265 : i::FLAG_concurrent_marking = flag_concurrent_marking_;
642 265 : i::FLAG_concurrent_sweeping = flag_concurrent_sweeping_;
643 265 : i::FLAG_stress_incremental_marking = flag_stress_incremental_marking_;
644 : }
645 :
646 : private:
647 : bool flag_concurrent_marking_;
648 : bool flag_concurrent_sweeping_;
649 : bool flag_stress_incremental_marking_;
650 : };
651 :
652 : // This is an abstract base class that can be overridden to implement a test
653 : // platform. It delegates all operations to a given platform at the time
654 : // of construction.
655 : class TestPlatform : public v8::Platform {
656 : public:
657 : // v8::Platform implementation.
658 0 : void OnCriticalMemoryPressure() override {
659 0 : old_platform_->OnCriticalMemoryPressure();
660 0 : }
661 :
662 43 : void CallOnBackgroundThread(v8::Task* task,
663 : ExpectedRuntime expected_runtime) override {
664 43 : old_platform_->CallOnBackgroundThread(task, expected_runtime);
665 43 : }
666 :
667 0 : void CallOnForegroundThread(v8::Isolate* isolate, v8::Task* task) override {
668 0 : old_platform_->CallOnForegroundThread(isolate, task);
669 0 : }
670 :
671 0 : void CallDelayedOnForegroundThread(v8::Isolate* isolate, v8::Task* task,
672 : double delay_in_seconds) override {
673 : old_platform_->CallDelayedOnForegroundThread(isolate, task,
674 0 : delay_in_seconds);
675 0 : }
676 :
677 5292 : double MonotonicallyIncreasingTime() override {
678 5292 : return old_platform_->MonotonicallyIncreasingTime();
679 : }
680 :
681 0 : double CurrentClockTimeMillis() override {
682 0 : return old_platform_->CurrentClockTimeMillis();
683 : }
684 :
685 0 : void CallIdleOnForegroundThread(v8::Isolate* isolate,
686 : v8::IdleTask* task) override {
687 0 : old_platform_->CallIdleOnForegroundThread(isolate, task);
688 0 : }
689 :
690 0 : bool IdleTasksEnabled(v8::Isolate* isolate) override {
691 0 : return old_platform_->IdleTasksEnabled(isolate);
692 : }
693 :
694 1706 : v8::TracingController* GetTracingController() override {
695 1706 : return old_platform_->GetTracingController();
696 : }
697 :
698 : protected:
699 240 : TestPlatform() : old_platform_(i::V8::GetCurrentPlatform()) {}
700 222 : ~TestPlatform() { i::V8::SetPlatformForTesting(old_platform_); }
701 :
702 : v8::Platform* old_platform() const { return old_platform_; }
703 :
704 : private:
705 : v8::Platform* old_platform_;
706 :
707 : DISALLOW_COPY_AND_ASSIGN(TestPlatform);
708 : };
709 :
710 : #endif // ifndef CCTEST_H_
|