deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / cctest.h
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 "src/v8.h"
32
33 #include "src/isolate-inl.h"
34
35 #ifndef TEST
36 #define TEST(Name)                                                             \
37   static void Test##Name();                                                    \
38   CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true, true);  \
39   static void Test##Name()
40 #endif
41
42 #ifndef UNINITIALIZED_TEST
43 #define UNINITIALIZED_TEST(Name)                                               \
44   static void Test##Name();                                                    \
45   CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true, false); \
46   static void Test##Name()
47 #endif
48
49 #ifndef DEPENDENT_TEST
50 #define DEPENDENT_TEST(Name, Dep)                                              \
51   static void Test##Name();                                                    \
52   CcTest register_test_##Name(Test##Name, __FILE__, #Name, #Dep, true, true);  \
53   static void Test##Name()
54 #endif
55
56 #ifndef UNINITIALIZED_DEPENDENT_TEST
57 #define UNINITIALIZED_DEPENDENT_TEST(Name, Dep)                                \
58   static void Test##Name();                                                    \
59   CcTest register_test_##Name(Test##Name, __FILE__, #Name, #Dep, true, false); \
60   static void Test##Name()
61 #endif
62
63 #ifndef DISABLED_TEST
64 #define DISABLED_TEST(Name)                                                    \
65   static void Test##Name();                                                    \
66   CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, false, true); \
67   static void Test##Name()
68 #endif
69
70 #define EXTENSION_LIST(V)                                                      \
71   V(GC_EXTENSION,       "v8/gc")                                               \
72   V(PRINT_EXTENSION,    "v8/print")                                            \
73   V(PROFILER_EXTENSION, "v8/profiler")                                         \
74   V(TRACE_EXTENSION,    "v8/trace")
75
76 #define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
77 enum CcTestExtensionIds {
78   EXTENSION_LIST(DEFINE_EXTENSION_ID)
79   kMaxExtensions
80 };
81 #undef DEFINE_EXTENSION_ID
82
83 typedef v8::internal::EnumSet<CcTestExtensionIds> CcTestExtensionFlags;
84 #define DEFINE_EXTENSION_FLAG(Name, Ident)                               \
85   static const CcTestExtensionFlags Name(1 << Name##_ID);
86   static const CcTestExtensionFlags NO_EXTENSIONS(0);
87   static const CcTestExtensionFlags ALL_EXTENSIONS((1 << kMaxExtensions) - 1);
88   EXTENSION_LIST(DEFINE_EXTENSION_FLAG)
89 #undef DEFINE_EXTENSION_FLAG
90
91
92 // Use this to expose protected methods in i::Heap.
93 class TestHeap : public i::Heap {
94  public:
95   using i::Heap::AllocateByteArray;
96   using i::Heap::AllocateFixedArray;
97   using i::Heap::AllocateHeapNumber;
98   using i::Heap::AllocateJSObject;
99   using i::Heap::AllocateJSObjectFromMap;
100   using i::Heap::AllocateMap;
101   using i::Heap::CopyCode;
102   using i::Heap::kInitialNumberStringCacheSize;
103 };
104
105
106 class CcTest {
107  public:
108   typedef void (TestFunction)();
109   CcTest(TestFunction* callback, const char* file, const char* name,
110          const char* dependency, bool enabled, bool initialize);
111   void Run();
112   static CcTest* last() { return last_; }
113   CcTest* prev() { return prev_; }
114   const char* file() { return file_; }
115   const char* name() { return name_; }
116   const char* dependency() { return dependency_; }
117   bool enabled() { return enabled_; }
118
119   static v8::Isolate* isolate() {
120     CHECK(isolate_ != NULL);
121     v8::base::NoBarrier_Store(&isolate_used_, 1);
122     return isolate_;
123   }
124
125   static i::Isolate* InitIsolateOnce() {
126     if (!initialize_called_) InitializeVM();
127     return i_isolate();
128   }
129
130   static i::Isolate* i_isolate() {
131     return reinterpret_cast<i::Isolate*>(isolate());
132   }
133
134   static i::Heap* heap() {
135     return i_isolate()->heap();
136   }
137
138   static TestHeap* test_heap() {
139     return reinterpret_cast<TestHeap*>(i_isolate()->heap());
140   }
141
142   static v8::base::RandomNumberGenerator* random_number_generator() {
143     return InitIsolateOnce()->random_number_generator();
144   }
145
146   static v8::Local<v8::Object> global() {
147     return isolate()->GetCurrentContext()->Global();
148   }
149
150   // TODO(dcarney): Remove.
151   // This must be called first in a test.
152   static void InitializeVM() {
153     CHECK(!v8::base::NoBarrier_Load(&isolate_used_));
154     CHECK(!initialize_called_);
155     initialize_called_ = true;
156     v8::HandleScope handle_scope(CcTest::isolate());
157     v8::Context::New(CcTest::isolate())->Enter();
158   }
159
160   // Only for UNINITIALIZED_TESTs
161   static void DisableAutomaticDispose();
162
163   // Helper function to configure a context.
164   // Must be in a HandleScope.
165   static v8::Local<v8::Context> NewContext(
166       CcTestExtensionFlags extensions,
167       v8::Isolate* isolate = CcTest::isolate());
168
169   static void TearDown() {
170     if (isolate_ != NULL) isolate_->Dispose();
171   }
172
173  private:
174   friend int main(int argc, char** argv);
175   TestFunction* callback_;
176   const char* file_;
177   const char* name_;
178   const char* dependency_;
179   bool enabled_;
180   bool initialize_;
181   CcTest* prev_;
182   static CcTest* last_;
183   static v8::Isolate* isolate_;
184   static bool initialize_called_;
185   static v8::base::Atomic32 isolate_used_;
186 };
187
188 // Switches between all the Api tests using the threading support.
189 // In order to get a surprising but repeatable pattern of thread
190 // switching it has extra semaphores to control the order in which
191 // the tests alternate, not relying solely on the big V8 lock.
192 //
193 // A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
194 // callbacks.  This will have no effect when we are not running the
195 // thread fuzzing test.  In the thread fuzzing test it will
196 // pseudorandomly select a successor thread and switch execution
197 // to that thread, suspending the current test.
198 class ApiTestFuzzer: public v8::base::Thread {
199  public:
200   void CallTest();
201
202   // The ApiTestFuzzer is also a Thread, so it has a Run method.
203   virtual void Run();
204
205   enum PartOfTest { FIRST_PART,
206                     SECOND_PART,
207                     THIRD_PART,
208                     FOURTH_PART,
209                     LAST_PART = FOURTH_PART };
210
211   static void SetUp(PartOfTest part);
212   static void RunAllTests();
213   static void TearDown();
214   // This method switches threads if we are running the Threading test.
215   // Otherwise it does nothing.
216   static void Fuzz();
217
218  private:
219   explicit ApiTestFuzzer(int num)
220       : Thread(Options("ApiTestFuzzer")),
221         test_number_(num),
222         gate_(0),
223         active_(true) {}
224   ~ApiTestFuzzer() {}
225
226   static bool fuzzing_;
227   static int tests_being_run_;
228   static int current_;
229   static int active_tests_;
230   static bool NextThread();
231   int test_number_;
232   v8::base::Semaphore gate_;
233   bool active_;
234   void ContextSwitch();
235   static int GetNextTestNumber();
236   static v8::base::Semaphore all_tests_done_;
237 };
238
239
240 #define THREADED_TEST(Name)                                          \
241   static void Test##Name();                                          \
242   RegisterThreadedTest register_##Name(Test##Name, #Name);           \
243   /* */ TEST(Name)
244
245
246 class RegisterThreadedTest {
247  public:
248   explicit RegisterThreadedTest(CcTest::TestFunction* callback,
249                                 const char* name)
250       : fuzzer_(NULL), callback_(callback), name_(name) {
251     prev_ = first_;
252     first_ = this;
253     count_++;
254   }
255   static int count() { return count_; }
256   static RegisterThreadedTest* nth(int i) {
257     CHECK(i < count());
258     RegisterThreadedTest* current = first_;
259     while (i > 0) {
260       i--;
261       current = current->prev_;
262     }
263     return current;
264   }
265   CcTest::TestFunction* callback() { return callback_; }
266   ApiTestFuzzer* fuzzer_;
267   const char* name() { return name_; }
268
269  private:
270   static RegisterThreadedTest* first_;
271   static int count_;
272   CcTest::TestFunction* callback_;
273   RegisterThreadedTest* prev_;
274   const char* name_;
275 };
276
277 // A LocalContext holds a reference to a v8::Context.
278 class LocalContext {
279  public:
280   LocalContext(v8::Isolate* isolate,
281                v8::ExtensionConfiguration* extensions = 0,
282                v8::Handle<v8::ObjectTemplate> global_template =
283                    v8::Handle<v8::ObjectTemplate>(),
284                v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) {
285     Initialize(isolate, extensions, global_template, global_object);
286   }
287
288   LocalContext(v8::ExtensionConfiguration* extensions = 0,
289                v8::Handle<v8::ObjectTemplate> global_template =
290                    v8::Handle<v8::ObjectTemplate>(),
291                v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) {
292     Initialize(CcTest::isolate(), extensions, global_template, global_object);
293   }
294
295   virtual ~LocalContext() {
296     v8::HandleScope scope(isolate_);
297     v8::Local<v8::Context>::New(isolate_, context_)->Exit();
298     context_.Reset();
299   }
300
301   v8::Context* operator->() {
302     return *reinterpret_cast<v8::Context**>(&context_);
303   }
304   v8::Context* operator*() { return operator->(); }
305   bool IsReady() { return !context_.IsEmpty(); }
306
307   v8::Local<v8::Context> local() {
308     return v8::Local<v8::Context>::New(isolate_, context_);
309   }
310
311  private:
312   void Initialize(v8::Isolate* isolate,
313                   v8::ExtensionConfiguration* extensions,
314                   v8::Handle<v8::ObjectTemplate> global_template,
315                   v8::Handle<v8::Value> global_object) {
316      v8::HandleScope scope(isolate);
317      v8::Local<v8::Context> context = v8::Context::New(isolate,
318                                                        extensions,
319                                                        global_template,
320                                                        global_object);
321      context_.Reset(isolate, context);
322      context->Enter();
323      // We can't do this later perhaps because of a fatal error.
324      isolate_ = isolate;
325   }
326
327   v8::Persistent<v8::Context> context_;
328   v8::Isolate* isolate_;
329 };
330
331
332 static inline uint16_t* AsciiToTwoByteString(const char* source) {
333   int array_length = i::StrLength(source) + 1;
334   uint16_t* converted = i::NewArray<uint16_t>(array_length);
335   for (int i = 0; i < array_length; i++) converted[i] = source[i];
336   return converted;
337 }
338
339
340 static inline v8::Local<v8::Value> v8_num(double x) {
341   return v8::Number::New(v8::Isolate::GetCurrent(), x);
342 }
343
344
345 static inline v8::Local<v8::String> v8_str(const char* x) {
346   return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x);
347 }
348
349
350 static inline v8::Local<v8::Symbol> v8_symbol(const char* name) {
351   return v8::Symbol::New(v8::Isolate::GetCurrent(), v8_str(name));
352 }
353
354
355 static inline v8::Local<v8::Script> v8_compile(const char* x) {
356   return v8::Script::Compile(v8_str(x));
357 }
358
359
360 static inline v8::Local<v8::Script> v8_compile(v8::Local<v8::String> x) {
361   return v8::Script::Compile(x);
362 }
363
364
365 static inline v8::Local<v8::Script> CompileWithOrigin(
366     v8::Local<v8::String> source, v8::Local<v8::String> origin_url) {
367   v8::ScriptOrigin origin(origin_url);
368   v8::ScriptCompiler::Source script_source(source, origin);
369   return v8::ScriptCompiler::Compile(
370       v8::Isolate::GetCurrent(), &script_source);
371 }
372
373
374 static inline v8::Local<v8::Script> CompileWithOrigin(
375     v8::Local<v8::String> source, const char* origin_url) {
376   return CompileWithOrigin(source, v8_str(origin_url));
377 }
378
379
380 static inline v8::Local<v8::Script> CompileWithOrigin(const char* source,
381                                                       const char* origin_url) {
382   return CompileWithOrigin(v8_str(source), v8_str(origin_url));
383 }
384
385
386 // Helper functions that compile and run the source.
387 static inline v8::Local<v8::Value> CompileRun(const char* source) {
388   return v8::Script::Compile(v8_str(source))->Run();
389 }
390
391
392 // Compiles source as an ES6 module.
393 static inline v8::Local<v8::Value> CompileRunModule(const char* source) {
394   v8::ScriptCompiler::Source script_source(v8_str(source));
395   return v8::ScriptCompiler::CompileModule(v8::Isolate::GetCurrent(),
396                                            &script_source)->Run();
397 }
398
399
400 static inline v8::Local<v8::Value> CompileRun(v8::Local<v8::String> source) {
401   return v8::Script::Compile(source)->Run();
402 }
403
404
405 static inline v8::Local<v8::Value> ParserCacheCompileRun(const char* source) {
406   // Compile once just to get the preparse data, then compile the second time
407   // using the data.
408   v8::Isolate* isolate = v8::Isolate::GetCurrent();
409   v8::ScriptCompiler::Source script_source(v8_str(source));
410   v8::ScriptCompiler::Compile(isolate, &script_source,
411                               v8::ScriptCompiler::kProduceParserCache);
412
413   // Check whether we received cached data, and if so use it.
414   v8::ScriptCompiler::CompileOptions options =
415       script_source.GetCachedData() ? v8::ScriptCompiler::kConsumeParserCache
416                                     : v8::ScriptCompiler::kNoCompileOptions;
417
418   return v8::ScriptCompiler::Compile(isolate, &script_source, options)->Run();
419 }
420
421
422 // Helper functions that compile and run the source with given origin.
423 static inline v8::Local<v8::Value> CompileRunWithOrigin(const char* source,
424                                                         const char* origin_url,
425                                                         int line_number,
426                                                         int column_number) {
427   v8::Isolate* isolate = v8::Isolate::GetCurrent();
428   v8::ScriptOrigin origin(v8_str(origin_url),
429                           v8::Integer::New(isolate, line_number),
430                           v8::Integer::New(isolate, column_number));
431   v8::ScriptCompiler::Source script_source(v8_str(source), origin);
432   return v8::ScriptCompiler::Compile(isolate, &script_source)->Run();
433 }
434
435
436 static inline v8::Local<v8::Value> CompileRunWithOrigin(
437     v8::Local<v8::String> source, const char* origin_url) {
438   v8::ScriptCompiler::Source script_source(
439       source, v8::ScriptOrigin(v8_str(origin_url)));
440   return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &script_source)
441       ->Run();
442 }
443
444
445 static inline v8::Local<v8::Value> CompileRunWithOrigin(
446     const char* source, const char* origin_url) {
447   return CompileRunWithOrigin(v8_str(source), origin_url);
448 }
449
450
451
452 static inline void ExpectString(const char* code, const char* expected) {
453   v8::Local<v8::Value> result = CompileRun(code);
454   CHECK(result->IsString());
455   v8::String::Utf8Value utf8(result);
456   CHECK_EQ(0, strcmp(expected, *utf8));
457 }
458
459
460 static inline void ExpectInt32(const char* code, int expected) {
461   v8::Local<v8::Value> result = CompileRun(code);
462   CHECK(result->IsInt32());
463   CHECK_EQ(expected, result->Int32Value());
464 }
465
466
467 static inline void ExpectBoolean(const char* code, bool expected) {
468   v8::Local<v8::Value> result = CompileRun(code);
469   CHECK(result->IsBoolean());
470   CHECK_EQ(expected, result->BooleanValue());
471 }
472
473
474 static inline void ExpectTrue(const char* code) {
475   ExpectBoolean(code, true);
476 }
477
478
479 static inline void ExpectFalse(const char* code) {
480   ExpectBoolean(code, false);
481 }
482
483
484 static inline void ExpectObject(const char* code,
485                                 v8::Local<v8::Value> expected) {
486   v8::Local<v8::Value> result = CompileRun(code);
487   CHECK(result->SameValue(expected));
488 }
489
490
491 static inline void ExpectUndefined(const char* code) {
492   v8::Local<v8::Value> result = CompileRun(code);
493   CHECK(result->IsUndefined());
494 }
495
496
497 // Helper function that simulates a full new-space in the heap.
498 static inline bool FillUpOnePage(v8::internal::NewSpace* space) {
499   v8::internal::AllocationResult allocation =
500       space->AllocateRaw(v8::internal::Page::kMaxRegularHeapObjectSize);
501   if (allocation.IsRetry()) return false;
502   v8::internal::HeapObject* free_space = NULL;
503   CHECK(allocation.To(&free_space));
504   space->heap()->CreateFillerObjectAt(
505       free_space->address(), v8::internal::Page::kMaxRegularHeapObjectSize);
506   return true;
507 }
508
509
510 // Helper function that simulates a fill new-space in the heap.
511 static inline void AllocateAllButNBytes(v8::internal::NewSpace* space,
512                                         int extra_bytes) {
513   int space_remaining = static_cast<int>(*space->allocation_limit_address() -
514                                          *space->allocation_top_address());
515   CHECK(space_remaining >= extra_bytes);
516   int new_linear_size = space_remaining - extra_bytes;
517   if (new_linear_size == 0) return;
518   v8::internal::AllocationResult allocation =
519       space->AllocateRaw(new_linear_size);
520   v8::internal::HeapObject* free_space = NULL;
521   CHECK(allocation.To(&free_space));
522   space->heap()->CreateFillerObjectAt(free_space->address(), new_linear_size);
523 }
524
525
526 static inline void FillCurrentPage(v8::internal::NewSpace* space) {
527   AllocateAllButNBytes(space, 0);
528 }
529
530
531 static inline void SimulateFullSpace(v8::internal::NewSpace* space) {
532   FillCurrentPage(space);
533   while (FillUpOnePage(space)) {
534   }
535 }
536
537
538 // Helper function that simulates a full old-space in the heap.
539 static inline void SimulateFullSpace(v8::internal::PagedSpace* space) {
540   space->EmptyAllocationInfo();
541   space->ResetFreeList();
542   space->ClearStats();
543 }
544
545
546 // Helper function that simulates many incremental marking steps until
547 // marking is completed.
548 static inline void SimulateIncrementalMarking(i::Heap* heap) {
549   i::MarkCompactCollector* collector = heap->mark_compact_collector();
550   i::IncrementalMarking* marking = heap->incremental_marking();
551   if (collector->sweeping_in_progress()) {
552     collector->EnsureSweepingCompleted();
553   }
554   CHECK(marking->IsMarking() || marking->IsStopped());
555   if (marking->IsStopped()) {
556     marking->Start();
557   }
558   CHECK(marking->IsMarking());
559   while (!marking->IsComplete()) {
560     marking->Step(i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
561     if (marking->IsReadyToOverApproximateWeakClosure()) {
562       marking->MarkObjectGroups();
563     }
564   }
565   CHECK(marking->IsComplete());
566 }
567
568
569 // Helper class for new allocations tracking and checking.
570 // To use checking of JS allocations tracking in a test,
571 // just create an instance of this class.
572 class HeapObjectsTracker {
573  public:
574   HeapObjectsTracker() {
575     heap_profiler_ = i::Isolate::Current()->heap_profiler();
576     CHECK_NOT_NULL(heap_profiler_);
577     heap_profiler_->StartHeapObjectsTracking(true);
578   }
579
580   ~HeapObjectsTracker() {
581     i::Isolate::Current()->heap()->CollectAllAvailableGarbage();
582     CHECK_EQ(0, heap_profiler_->heap_object_map()->FindUntrackedObjects());
583     heap_profiler_->StopHeapObjectsTracking();
584   }
585
586  private:
587   i::HeapProfiler* heap_profiler_;
588 };
589
590
591 class InitializedHandleScope {
592  public:
593   InitializedHandleScope()
594       : main_isolate_(CcTest::InitIsolateOnce()),
595         handle_scope_(main_isolate_) {}
596
597   // Prefixing the below with main_ reduces a lot of naming clashes.
598   i::Isolate* main_isolate() { return main_isolate_; }
599
600  private:
601   i::Isolate* main_isolate_;
602   i::HandleScope handle_scope_;
603 };
604
605
606 class HandleAndZoneScope : public InitializedHandleScope {
607  public:
608   HandleAndZoneScope() {}
609
610   // Prefixing the below with main_ reduces a lot of naming clashes.
611   i::Zone* main_zone() { return &main_zone_; }
612
613  private:
614   i::Zone main_zone_;
615 };
616
617 #endif  // ifndef CCTEST_H_