v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cctest.h
Go to the documentation of this file.
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 "v8.h"
32 
33 #ifndef TEST
34 #define TEST(Name) \
35  static void Test##Name(); \
36  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true, true); \
37  static void Test##Name()
38 #endif
39 
40 #ifndef UNINITIALIZED_TEST
41 #define UNINITIALIZED_TEST(Name) \
42  static void Test##Name(); \
43  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true, false); \
44  static void Test##Name()
45 #endif
46 
47 #ifndef DEPENDENT_TEST
48 #define DEPENDENT_TEST(Name, Dep) \
49  static void Test##Name(); \
50  CcTest register_test_##Name(Test##Name, __FILE__, #Name, #Dep, true, true); \
51  static void Test##Name()
52 #endif
53 
54 #ifndef DISABLED_TEST
55 #define DISABLED_TEST(Name) \
56  static void Test##Name(); \
57  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, false, true); \
58  static void Test##Name()
59 #endif
60 
61 #define EXTENSION_LIST(V) \
62  V(GC_EXTENSION, "v8/gc") \
63  V(PRINT_EXTENSION, "v8/print") \
64  V(PROFILER_EXTENSION, "v8/profiler") \
65  V(TRACE_EXTENSION, "v8/trace")
66 
67 #define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
71 };
72 #undef DEFINE_EXTENSION_ID
73 
75 #define DEFINE_EXTENSION_FLAG(Name, Ident) \
76  static const CcTestExtensionFlags Name(1 << Name##_ID);
77  static const CcTestExtensionFlags NO_EXTENSIONS(0);
78  static const CcTestExtensionFlags ALL_EXTENSIONS((1 << kMaxExtensions) - 1);
80 #undef DEFINE_EXTENSION_FLAG
81 
82 
83 class CcTest {
84  public:
85  typedef void (TestFunction)();
86  CcTest(TestFunction* callback, const char* file, const char* name,
87  const char* dependency, bool enabled, bool initialize);
88  void Run();
89  static CcTest* last() { return last_; }
90  CcTest* prev() { return prev_; }
91  const char* file() { return file_; }
92  const char* name() { return name_; }
93  const char* dependency() { return dependency_; }
94  bool enabled() { return enabled_; }
95 
96  static v8::Isolate* isolate() {
97  CHECK(isolate_ != NULL);
98  isolate_used_ = true;
99  return isolate_;
100  }
101 
102  static i::Isolate* i_isolate() {
103  return reinterpret_cast<i::Isolate*>(isolate());
104  }
105 
106  static i::Heap* heap() {
107  return i_isolate()->heap();
108  }
109 
111  return isolate()->GetCurrentContext()->Global();
112  }
113 
114  // TODO(dcarney): Remove.
115  // This must be called first in a test.
116  static void InitializeVM() {
117  CHECK(!isolate_used_);
118  CHECK(!initialize_called_);
119  initialize_called_ = true;
120  v8::HandleScope handle_scope(CcTest::isolate());
121  v8::Context::New(CcTest::isolate())->Enter();
122  }
123 
124  // Only for UNINITIALIZED_TESTs
125  static void DisableAutomaticDispose();
126 
127  // Helper function to configure a context.
128  // Must be in a HandleScope.
130  CcTestExtensionFlags extensions,
132 
133  static void TearDown() {
134  if (isolate_ != NULL) isolate_->Dispose();
135  }
136 
137  private:
138  friend int main(int argc, char** argv);
139  TestFunction* callback_;
140  const char* file_;
141  const char* name_;
142  const char* dependency_;
143  bool enabled_;
144  bool initialize_;
145  CcTest* prev_;
146  static CcTest* last_;
147  static v8::Isolate* isolate_;
148  static bool initialize_called_;
149  static bool isolate_used_;
150 };
151 
152 // Switches between all the Api tests using the threading support.
153 // In order to get a surprising but repeatable pattern of thread
154 // switching it has extra semaphores to control the order in which
155 // the tests alternate, not relying solely on the big V8 lock.
156 //
157 // A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
158 // callbacks. This will have no effect when we are not running the
159 // thread fuzzing test. In the thread fuzzing test it will
160 // pseudorandomly select a successor thread and switch execution
161 // to that thread, suspending the current test.
163  public:
164  void CallTest();
165 
166  // The ApiTestFuzzer is also a Thread, so it has a Run method.
167  virtual void Run();
168 
174 
175  static void SetUp(PartOfTest part);
176  static void RunAllTests();
177  static void TearDown();
178  // This method switches threads if we are running the Threading test.
179  // Otherwise it does nothing.
180  static void Fuzz();
181 
182  private:
183  explicit ApiTestFuzzer(int num)
184  : Thread("ApiTestFuzzer"),
185  test_number_(num),
186  gate_(0),
187  active_(true) {
188  }
189  ~ApiTestFuzzer() {}
190 
191  static bool fuzzing_;
192  static int tests_being_run_;
193  static int current_;
194  static int active_tests_;
195  static bool NextThread();
196  int test_number_;
197  v8::internal::Semaphore gate_;
198  bool active_;
199  void ContextSwitch();
200  static int GetNextTestNumber();
201  static v8::internal::Semaphore all_tests_done_;
202 };
203 
204 
205 #define THREADED_TEST(Name) \
206  static void Test##Name(); \
207  RegisterThreadedTest register_##Name(Test##Name, #Name); \
208  /* */ TEST(Name)
209 
210 
212  public:
214  const char* name)
215  : fuzzer_(NULL), callback_(callback), name_(name) {
216  prev_ = first_;
217  first_ = this;
218  count_++;
219  }
220  static int count() { return count_; }
221  static RegisterThreadedTest* nth(int i) {
222  CHECK(i < count());
223  RegisterThreadedTest* current = first_;
224  while (i > 0) {
225  i--;
226  current = current->prev_;
227  }
228  return current;
229  }
230  CcTest::TestFunction* callback() { return callback_; }
232  const char* name() { return name_; }
233 
234  private:
235  static RegisterThreadedTest* first_;
236  static int count_;
237  CcTest::TestFunction* callback_;
238  RegisterThreadedTest* prev_;
239  const char* name_;
240 };
241 
242 // A LocalContext holds a reference to a v8::Context.
244  public:
246  v8::ExtensionConfiguration* extensions = 0,
247  v8::Handle<v8::ObjectTemplate> global_template =
249  v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) {
250  Initialize(isolate, extensions, global_template, global_object);
251  }
252 
254  v8::Handle<v8::ObjectTemplate> global_template =
256  v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) {
257  Initialize(CcTest::isolate(), extensions, global_template, global_object);
258  }
259 
260  virtual ~LocalContext() {
261  v8::HandleScope scope(isolate_);
262  v8::Local<v8::Context>::New(isolate_, context_)->Exit();
263  context_.Reset();
264  }
265 
267  return *reinterpret_cast<v8::Context**>(&context_);
268  }
270  bool IsReady() { return !context_.IsEmpty(); }
271 
273  return v8::Local<v8::Context>::New(isolate_, context_);
274  }
275 
276  private:
277  void Initialize(v8::Isolate* isolate,
278  v8::ExtensionConfiguration* extensions,
279  v8::Handle<v8::ObjectTemplate> global_template,
280  v8::Handle<v8::Value> global_object) {
281  v8::HandleScope scope(isolate);
282  v8::Local<v8::Context> context = v8::Context::New(isolate,
283  extensions,
284  global_template,
285  global_object);
286  context_.Reset(isolate, context);
287  context->Enter();
288  // We can't do this later perhaps because of a fatal error.
289  isolate_ = isolate;
290  }
291 
293  v8::Isolate* isolate_;
294 };
295 
296 static inline v8::Local<v8::Value> v8_num(double x) {
298 }
299 
300 
301 static inline v8::Local<v8::String> v8_str(const char* x) {
303 }
304 
305 
306 static inline v8::Local<v8::Script> v8_compile(const char* x) {
307  return v8::Script::Compile(v8_str(x));
308 }
309 
310 
311 static inline v8::Local<v8::Script> v8_compile(v8::Local<v8::String> x) {
312  return v8::Script::Compile(x);
313 }
314 
315 
316 static inline v8::Local<v8::Script> CompileWithOrigin(
317  v8::Local<v8::String> source, v8::Local<v8::String> origin_url) {
318  v8::ScriptOrigin origin(origin_url);
319  v8::ScriptCompiler::Source script_source(source, origin);
321  v8::Isolate::GetCurrent(), &script_source);
322 }
323 
324 
325 static inline v8::Local<v8::Script> CompileWithOrigin(
326  v8::Local<v8::String> source, const char* origin_url) {
327  return CompileWithOrigin(source, v8_str(origin_url));
328 }
329 
330 
331 static inline v8::Local<v8::Script> CompileWithOrigin(const char* source,
332  const char* origin_url) {
333  return CompileWithOrigin(v8_str(source), v8_str(origin_url));
334 }
335 
336 
337 // Helper functions that compile and run the source.
338 static inline v8::Local<v8::Value> CompileRun(const char* source) {
339  return v8::Script::Compile(v8_str(source))->Run();
340 }
341 
342 
343 static inline v8::Local<v8::Value> CompileRun(v8::Local<v8::String> source) {
344  return v8::Script::Compile(source)->Run();
345 }
346 
347 
348 static inline v8::Local<v8::Value> PreCompileCompileRun(const char* source) {
350  v8::Local<v8::String> source_string =
351  v8::String::NewFromUtf8(isolate, source);
352  v8::ScriptData* preparse = v8::ScriptData::PreCompile(source_string);
353  v8::ScriptCompiler::Source script_source(
354  source_string, new v8::ScriptCompiler::CachedData(
355  reinterpret_cast<const uint8_t*>(preparse->Data()),
356  preparse->Length()));
357  v8::Local<v8::Script> script =
358  v8::ScriptCompiler::Compile(isolate, &script_source);
359  v8::Local<v8::Value> result = script->Run();
360  delete preparse;
361  return result;
362 }
363 
364 
365 // Helper functions that compile and run the source with given origin.
366 static inline v8::Local<v8::Value> CompileRunWithOrigin(const char* source,
367  const char* origin_url,
368  int line_number,
369  int column_number) {
371  v8::ScriptOrigin origin(v8_str(origin_url),
372  v8::Integer::New(isolate, line_number),
373  v8::Integer::New(isolate, column_number));
374  v8::ScriptCompiler::Source script_source(v8_str(source), origin);
375  return v8::ScriptCompiler::Compile(isolate, &script_source)->Run();
376 }
377 
378 
379 static inline v8::Local<v8::Value> CompileRunWithOrigin(
380  v8::Local<v8::String> source, const char* origin_url) {
381  v8::ScriptCompiler::Source script_source(
382  source, v8::ScriptOrigin(v8_str(origin_url)));
383  return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &script_source)
384  ->Run();
385 }
386 
387 
388 static inline v8::Local<v8::Value> CompileRunWithOrigin(
389  const char* source, const char* origin_url) {
390  return CompileRunWithOrigin(v8_str(source), origin_url);
391 }
392 
393 
394 // Pick a slightly different port to allow tests to be run in parallel.
395 static inline int FlagDependentPortOffset() {
396  return ::v8::internal::FLAG_crankshaft == false ? 100 :
397  ::v8::internal::FLAG_always_opt ? 200 : 0;
398 }
399 
400 
401 // Helper function that simulates a full new-space in the heap.
402 static inline void SimulateFullSpace(v8::internal::NewSpace* space) {
403  int new_linear_size = static_cast<int>(
404  *space->allocation_limit_address() - *space->allocation_top_address());
405  if (new_linear_size == 0) return;
406  v8::internal::MaybeObject* maybe = space->AllocateRaw(new_linear_size);
408  node->set_size(space->heap(), new_linear_size);
409 }
410 
411 
412 // Helper function that simulates a full old-space in the heap.
413 static inline void SimulateFullSpace(v8::internal::PagedSpace* space) {
414  space->EmptyAllocationInfo();
415  space->ResetFreeList();
416  space->ClearStats();
417 }
418 
419 
420 // Helper class for new allocations tracking and checking.
421 // To use checking of JS allocations tracking in a test,
422 // just create an instance of this class.
424  public:
426  heap_profiler_ = i::Isolate::Current()->heap_profiler();
427  CHECK_NE(NULL, heap_profiler_);
428  heap_profiler_->StartHeapObjectsTracking(true);
429  }
430 
432  i::Isolate::Current()->heap()->CollectAllAvailableGarbage();
433  CHECK_EQ(0, heap_profiler_->heap_object_map()->FindUntrackedObjects());
434  heap_profiler_->StopHeapObjectsTracking();
435  }
436 
437  private:
438  i::HeapProfiler* heap_profiler_;
439 };
440 
441 
442 #endif // ifndef CCTEST_H_
void Enter()
Definition: api.cc:650
static void RunAllTests()
Definition: test-api.cc:13173
virtual ~LocalContext()
Definition: cctest.h:260
static Isolate * GetCurrent()
Definition: api.cc:6580
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static V8_INLINE Local< T > New(Isolate *isolate, Handle< T > that)
Definition: v8.h:5713
#define CHECK_EQ(expected, value)
Definition: checks.h:252
HeapObjectsMap * heap_object_map() const
Definition: heap-profiler.h:61
void Dispose()
Definition: api.cc:6592
static void TearDown()
Definition: test-api.cc:13205
void set_size(Heap *heap, int size_in_bytes)
Definition: spaces.cc:2008
static FreeListNode * cast(MaybeObject *maybe)
Definition: spaces.h:1523
Thread(const Options &options)
CcTest(TestFunction *callback, const char *file, const char *name, const char *dependency, bool enabled, bool initialize)
Definition: cctest.cc:46
LocalContext(v8::ExtensionConfiguration *extensions=0, v8::Handle< v8::ObjectTemplate > global_template=v8::Handle< v8::ObjectTemplate >(), v8::Handle< v8::Value > global_object=v8::Handle< v8::Value >())
Definition: cctest.h:253
const char * file()
Definition: cctest.h:91
v8::Context * operator*()
Definition: cctest.h:269
Address * allocation_top_address()
Definition: spaces.h:2534
static void DisableAutomaticDispose()
Definition: cctest.cc:105
static v8::Local< v8::Object > global()
Definition: cctest.h:110
#define DEFINE_EXTENSION_FLAG(Name, Ident)
Definition: cctest.h:75
Local< Context > GetCurrentContext()
Definition: api.cc:6359
static i::Heap * heap()
Definition: cctest.h:106
ApiTestFuzzer * fuzzer_
Definition: cctest.h:231
void( TestFunction)()
Definition: cctest.h:85
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6233
const char * dependency()
Definition: cctest.h:93
#define CHECK(condition)
Definition: checks.h:75
bool IsReady()
Definition: cctest.h:270
LocalContext(v8::Isolate *isolate, v8::ExtensionConfiguration *extensions=0, v8::Handle< v8::ObjectTemplate > global_template=v8::Handle< v8::ObjectTemplate >(), v8::Handle< v8::Value > global_object=v8::Handle< v8::Value >())
Definition: cctest.h:245
static v8::Local< v8::Context > NewContext(CcTestExtensionFlags extensions, v8::Isolate *isolate=CcTest::isolate())
Definition: cctest.cc:90
void StartHeapObjectsTracking(bool track_allocations)
const char * name()
Definition: cctest.h:232
virtual const char * Data()=0
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
#define DEFINE_EXTENSION_ID(Name, Ident)
Definition: cctest.h:67
static void Fuzz()
Definition: test-api.cc:13100
void Run()
Definition: cctest.cc:70
friend int main(int argc, char **argv)
Definition: mksnapshot.cc:268
RegisterThreadedTest(CcTest::TestFunction *callback, const char *name)
Definition: cctest.h:213
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *script_data=NULL)
Definition: api.cc:1832
static i::Isolate * i_isolate()
Definition: cctest.h:102
#define EXTENSION_LIST(V)
Definition: cctest.h:61
virtual void Run()
Definition: test-api.cc:13128
Definition: v8.h:123
static Local< Number > New(Isolate *isolate, double value)
Definition: api.cc:6220
bool enabled()
Definition: cctest.h:94
#define CHECK_NE(unexpected, value)
Definition: checks.h:256
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:5188
static void TearDown()
Definition: cctest.h:133
static void InitializeVM()
Definition: cctest.h:116
v8::internal::EnumSet< CcTestExtensionIds > CcTestExtensionFlags
Definition: cctest.h:74
const char * name()
Definition: cctest.h:92
static CcTest * last()
Definition: cctest.h:89
Heap * heap() const
Definition: spaces.h:900
static RegisterThreadedTest * nth(int i)
Definition: cctest.h:221
V8_INLINE bool IsEmpty() const
Definition: v8.h:497
CcTest * prev()
Definition: cctest.h:90
virtual int Length()=0
V8_INLINE void Reset()
Definition: v8.h:5808
Local< Value > Run()
Definition: api.cc:1686
static Local< Script > Compile(Isolate *isolate, Source *source, CompileOptions options=kNoCompileOptions)
Definition: api.cc:1816
CcTest::TestFunction * callback()
Definition: cctest.h:230
void CallTest()
Definition: test-api.cc:13243
CcTestExtensionIds
Definition: cctest.h:68
Address * allocation_limit_address()
Definition: spaces.h:2539
v8::Local< v8::Context > local()
Definition: cctest.h:272
static ScriptData * PreCompile(Handle< String > source)
Definition: api.cc:1573
static void SetUp(PartOfTest part)
Definition: test-api.cc:13152
v8::Context * operator->()
Definition: cctest.h:266
Definition: v8.h:124
Definition: cctest.h:83
static int count()
Definition: cctest.h:220
static v8::Isolate * isolate()
Definition: cctest.h:96
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417