The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / cctest.h @ f230a1cf

History | View | Annotate | Download (12.6 KB)

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(TRACE_EXTENSION, "v8/trace")
65

    
66
#define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
67
enum CcTestExtensionIds {
68
  EXTENSION_LIST(DEFINE_EXTENSION_ID)
69
  kMaxExtensions
70
};
71
#undef DEFINE_EXTENSION_ID
72

    
73
typedef v8::internal::EnumSet<CcTestExtensionIds> CcTestExtensionFlags;
74
#define DEFINE_EXTENSION_FLAG(Name, Ident)                               \
75
  static const CcTestExtensionFlags Name(1 << Name##_ID);
76
  static const CcTestExtensionFlags NO_EXTENSIONS(0);
77
  static const CcTestExtensionFlags ALL_EXTENSIONS((1 << kMaxExtensions) - 1);
78
  EXTENSION_LIST(DEFINE_EXTENSION_FLAG)
79
#undef DEFINE_EXTENSION_FLAG
80

    
81

    
82
class CcTest {
83
 public:
84
  typedef void (TestFunction)();
85
  CcTest(TestFunction* callback, const char* file, const char* name,
86
         const char* dependency, bool enabled, bool initialize);
87
  void Run();
88
  static CcTest* last() { return last_; }
89
  CcTest* prev() { return prev_; }
90
  const char* file() { return file_; }
91
  const char* name() { return name_; }
92
  const char* dependency() { return dependency_; }
93
  bool enabled() { return enabled_; }
94

    
95
  static v8::Isolate* isolate() {
96
    CHECK(isolate_ != NULL);
97
    isolate_used_ = true;
98
    return isolate_;
99
  }
100

    
101
  static i::Isolate* i_isolate() {
102
    return reinterpret_cast<i::Isolate*>(isolate());
103
  }
104

    
105
  static i::Heap* heap() {
106
    return i_isolate()->heap();
107
  }
108

    
109
  static v8::Local<v8::Object> global() {
110
    return isolate()->GetCurrentContext()->Global();
111
  }
112

    
113
  // TODO(dcarney): Remove.
114
  // This must be called first in a test.
115
  static void InitializeVM() {
116
    CHECK(!isolate_used_);
117
    CHECK(!initialize_called_);
118
    initialize_called_ = true;
119
    v8::HandleScope handle_scope(CcTest::isolate());
120
    v8::Context::New(CcTest::isolate())->Enter();
121
  }
122

    
123
  // Only for UNINITIALIZED_TESTs
124
  static void DisableAutomaticDispose();
125

    
126
  // Helper function to configure a context.
127
  // Must be in a HandleScope.
128
  static v8::Local<v8::Context> NewContext(
129
      CcTestExtensionFlags extensions,
130
      v8::Isolate* isolate = CcTest::isolate());
131

    
132
 private:
133
  friend int main(int argc, char** argv);
134
  TestFunction* callback_;
135
  const char* file_;
136
  const char* name_;
137
  const char* dependency_;
138
  bool enabled_;
139
  bool initialize_;
140
  CcTest* prev_;
141
  static CcTest* last_;
142
  static v8::Isolate* isolate_;
143
  static bool initialize_called_;
144
  static bool isolate_used_;
145
};
146

    
147
// Switches between all the Api tests using the threading support.
148
// In order to get a surprising but repeatable pattern of thread
149
// switching it has extra semaphores to control the order in which
150
// the tests alternate, not relying solely on the big V8 lock.
151
//
152
// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
153
// callbacks.  This will have no effect when we are not running the
154
// thread fuzzing test.  In the thread fuzzing test it will
155
// pseudorandomly select a successor thread and switch execution
156
// to that thread, suspending the current test.
157
class ApiTestFuzzer: public v8::internal::Thread {
158
 public:
159
  void CallTest();
160

    
161
  // The ApiTestFuzzer is also a Thread, so it has a Run method.
162
  virtual void Run();
163

    
164
  enum PartOfTest { FIRST_PART,
165
                    SECOND_PART,
166
                    THIRD_PART,
167
                    FOURTH_PART,
168
                    LAST_PART = FOURTH_PART };
169

    
170
  static void SetUp(PartOfTest part);
171
  static void RunAllTests();
172
  static void TearDown();
173
  // This method switches threads if we are running the Threading test.
174
  // Otherwise it does nothing.
175
  static void Fuzz();
176

    
177
 private:
178
  explicit ApiTestFuzzer(int num)
179
      : Thread("ApiTestFuzzer"),
180
        test_number_(num),
181
        gate_(0),
182
        active_(true) {
183
  }
184
  ~ApiTestFuzzer() {}
185

    
186
  static bool fuzzing_;
187
  static int tests_being_run_;
188
  static int current_;
189
  static int active_tests_;
190
  static bool NextThread();
191
  int test_number_;
192
  v8::internal::Semaphore gate_;
193
  bool active_;
194
  void ContextSwitch();
195
  static int GetNextTestNumber();
196
  static v8::internal::Semaphore all_tests_done_;
197
};
198

    
199

    
200
#define THREADED_TEST(Name)                                          \
201
  static void Test##Name();                                          \
202
  RegisterThreadedTest register_##Name(Test##Name, #Name);           \
203
  /* */ TEST(Name)
204

    
205

    
206
class RegisterThreadedTest {
207
 public:
208
  explicit RegisterThreadedTest(CcTest::TestFunction* callback,
209
                                const char* name)
210
      : fuzzer_(NULL), callback_(callback), name_(name) {
211
    prev_ = first_;
212
    first_ = this;
213
    count_++;
214
  }
215
  static int count() { return count_; }
216
  static RegisterThreadedTest* nth(int i) {
217
    CHECK(i < count());
218
    RegisterThreadedTest* current = first_;
219
    while (i > 0) {
220
      i--;
221
      current = current->prev_;
222
    }
223
    return current;
224
  }
225
  CcTest::TestFunction* callback() { return callback_; }
226
  ApiTestFuzzer* fuzzer_;
227
  const char* name() { return name_; }
228

    
229
 private:
230
  static RegisterThreadedTest* first_;
231
  static int count_;
232
  CcTest::TestFunction* callback_;
233
  RegisterThreadedTest* prev_;
234
  const char* name_;
235
};
236

    
237
// A LocalContext holds a reference to a v8::Context.
238
class LocalContext {
239
 public:
240
  LocalContext(v8::Isolate* isolate,
241
               v8::ExtensionConfiguration* extensions = 0,
242
               v8::Handle<v8::ObjectTemplate> global_template =
243
                   v8::Handle<v8::ObjectTemplate>(),
244
               v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) {
245
    Initialize(isolate, extensions, global_template, global_object);
246
  }
247

    
248
  LocalContext(v8::ExtensionConfiguration* extensions = 0,
249
               v8::Handle<v8::ObjectTemplate> global_template =
250
                   v8::Handle<v8::ObjectTemplate>(),
251
               v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>()) {
252
    Initialize(CcTest::isolate(), extensions, global_template, global_object);
253
  }
254

    
255
  virtual ~LocalContext() {
256
    v8::HandleScope scope(isolate_);
257
    v8::Local<v8::Context>::New(isolate_, context_)->Exit();
258
    context_.Dispose();
259
  }
260

    
261
  v8::Context* operator->() {
262
    return *reinterpret_cast<v8::Context**>(&context_);
263
  }
264
  v8::Context* operator*() { return operator->(); }
265
  bool IsReady() { return !context_.IsEmpty(); }
266

    
267
  v8::Local<v8::Context> local() {
268
    return v8::Local<v8::Context>::New(isolate_, context_);
269
  }
270

    
271
 private:
272
  void Initialize(v8::Isolate* isolate,
273
                  v8::ExtensionConfiguration* extensions,
274
                  v8::Handle<v8::ObjectTemplate> global_template,
275
                  v8::Handle<v8::Value> global_object) {
276
     v8::HandleScope scope(isolate);
277
     v8::Local<v8::Context> context = v8::Context::New(isolate,
278
                                                       extensions,
279
                                                       global_template,
280
                                                       global_object);
281
     context_.Reset(isolate, context);
282
     context->Enter();
283
     // We can't do this later perhaps because of a fatal error.
284
     isolate_ = isolate;
285
  }
286

    
287
  v8::Persistent<v8::Context> context_;
288
  v8::Isolate* isolate_;
289
};
290

    
291
static inline v8::Local<v8::Value> v8_num(double x) {
292
  return v8::Number::New(x);
293
}
294

    
295

    
296
static inline v8::Local<v8::String> v8_str(const char* x) {
297
  return v8::String::New(x);
298
}
299

    
300

    
301
static inline v8::Local<v8::Script> v8_compile(const char* x) {
302
  return v8::Script::Compile(v8_str(x));
303
}
304

    
305

    
306
// Helper function that compiles and runs the source.
307
static inline v8::Local<v8::Value> CompileRun(const char* source) {
308
  return v8::Script::Compile(v8::String::New(source))->Run();
309
}
310

    
311

    
312
// Helper function that compiles and runs the source with given origin.
313
static inline v8::Local<v8::Value> CompileRunWithOrigin(const char* source,
314
                                                        const char* origin_url,
315
                                                        int line_number,
316
                                                        int column_number) {
317
  v8::ScriptOrigin origin(v8::String::New(origin_url),
318
                          v8::Integer::New(line_number),
319
                          v8::Integer::New(column_number));
320
  return v8::Script::Compile(v8::String::New(source), &origin)->Run();
321
}
322

    
323

    
324
// Pick a slightly different port to allow tests to be run in parallel.
325
static inline int FlagDependentPortOffset() {
326
  return ::v8::internal::FLAG_crankshaft == false ? 100 :
327
         ::v8::internal::FLAG_always_opt ? 200 : 0;
328
}
329

    
330

    
331
// Helper function that simulates a full new-space in the heap.
332
static inline void SimulateFullSpace(v8::internal::NewSpace* space) {
333
  int new_linear_size = static_cast<int>(
334
      *space->allocation_limit_address() - *space->allocation_top_address());
335
  v8::internal::MaybeObject* maybe = space->AllocateRaw(new_linear_size);
336
  v8::internal::FreeListNode* node = v8::internal::FreeListNode::cast(maybe);
337
  node->set_size(space->heap(), new_linear_size);
338
}
339

    
340

    
341
// Helper function that simulates a full old-space in the heap.
342
static inline void SimulateFullSpace(v8::internal::PagedSpace* space) {
343
  int old_linear_size = static_cast<int>(space->limit() - space->top());
344
  space->Free(space->top(), old_linear_size);
345
  space->SetTop(space->limit(), space->limit());
346
  space->ResetFreeList();
347
  space->ClearStats();
348
}
349

    
350

    
351
// Helper class for new allocations tracking and checking.
352
// To use checking of JS allocations tracking in a test,
353
// just create an instance of this class.
354
class HeapObjectsTracker {
355
 public:
356
  HeapObjectsTracker() {
357
    heap_profiler_ = i::Isolate::Current()->heap_profiler();
358
    CHECK_NE(NULL, heap_profiler_);
359
    heap_profiler_->StartHeapAllocationsRecording();
360
  }
361

    
362
  ~HeapObjectsTracker() {
363
    i::Isolate::Current()->heap()->CollectAllAvailableGarbage();
364
    CHECK_EQ(0, heap_profiler_->FindUntrackedObjects());
365
    heap_profiler_->StopHeapAllocationsRecording();
366
  }
367

    
368
 private:
369
  i::HeapProfiler* heap_profiler_;
370
};
371

    
372

    
373
#endif  // ifndef CCTEST_H_