cctest.h 19.2 KB
Newer Older
1
// Copyright 2008 the V8 project authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef CCTEST_H_
#define CCTEST_H_

31
#include "include/libplatform/libplatform.h"
32
#include "src/isolate-inl.h"  // TODO(everyone): Make cctest IWYU.
33
#include "src/objects-inl.h"  // TODO(everyone): Make cctest IWYU.
34
#include "src/v8.h"
35

36
#ifndef TEST
37 38 39
#define TEST(Name)                                                      \
  static void Test##Name();                                             \
  CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, true); \
40 41 42 43
  static void Test##Name()
#endif

#ifndef UNINITIALIZED_TEST
44 45 46
#define UNINITIALIZED_TEST(Name)                                         \
  static void Test##Name();                                              \
  CcTest register_test_##Name(Test##Name, __FILE__, #Name, true, false); \
47 48 49
  static void Test##Name()
#endif

50
#ifndef DISABLED_TEST
51 52 53
#define DISABLED_TEST(Name)                                              \
  static void Test##Name();                                              \
  CcTest register_test_##Name(Test##Name, __FILE__, #Name, false, true); \
54 55 56
  static void Test##Name()
#endif

57 58 59 60 61
#define EXTENSION_LIST(V)                                                      \
  V(GC_EXTENSION,       "v8/gc")                                               \
  V(PRINT_EXTENSION,    "v8/print")                                            \
  V(PROFILER_EXTENSION, "v8/profiler")                                         \
  V(TRACE_EXTENSION,    "v8/trace")
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

#define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
enum CcTestExtensionIds {
  EXTENSION_LIST(DEFINE_EXTENSION_ID)
  kMaxExtensions
};
#undef DEFINE_EXTENSION_ID

typedef v8::internal::EnumSet<CcTestExtensionIds> CcTestExtensionFlags;
#define DEFINE_EXTENSION_FLAG(Name, Ident)                               \
  static const CcTestExtensionFlags Name(1 << Name##_ID);
  static const CcTestExtensionFlags NO_EXTENSIONS(0);
  static const CcTestExtensionFlags ALL_EXTENSIONS((1 << kMaxExtensions) - 1);
  EXTENSION_LIST(DEFINE_EXTENSION_FLAG)
#undef DEFINE_EXTENSION_FLAG

78

79 80 81
class CcTest {
 public:
  typedef void (TestFunction)();
82
  CcTest(TestFunction* callback, const char* file, const char* name,
83
         bool enabled, bool initialize);
84
  ~CcTest() { i::DeleteArray(file_); }
85
  void Run();
86
  static CcTest* last() { return last_; }
87 88 89
  CcTest* prev() { return prev_; }
  const char* file() { return file_; }
  const char* name() { return name_; }
90
  bool enabled() { return enabled_; }
91

92
  static v8::Isolate* isolate() {
93
    CHECK(isolate_ != NULL);
94
    v8::base::NoBarrier_Store(&isolate_used_, 1);
95
    return isolate_;
96
  }
97

98 99 100 101 102
  static i::Isolate* InitIsolateOnce() {
    if (!initialize_called_) InitializeVM();
    return i_isolate();
  }

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

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

111 112 113 114
  static v8::base::RandomNumberGenerator* random_number_generator() {
    return InitIsolateOnce()->random_number_generator();
  }

115 116 117 118
  static v8::Local<v8::Object> global() {
    return isolate()->GetCurrentContext()->Global();
  }

119 120 121 122 123 124 125 126 127
  static v8::ArrayBuffer::Allocator* array_buffer_allocator() {
    return allocator_;
  }

  static void set_array_buffer_allocator(
      v8::ArrayBuffer::Allocator* allocator) {
    allocator_ = allocator;
  }

128 129 130
  // TODO(dcarney): Remove.
  // This must be called first in a test.
  static void InitializeVM() {
131
    CHECK(!v8::base::NoBarrier_Load(&isolate_used_));
132 133 134 135 136 137
    CHECK(!initialize_called_);
    initialize_called_ = true;
    v8::HandleScope handle_scope(CcTest::isolate());
    v8::Context::New(CcTest::isolate())->Enter();
  }

138 139 140
  // Only for UNINITIALIZED_TESTs
  static void DisableAutomaticDispose();

141 142 143 144 145
  // Helper function to configure a context.
  // Must be in a HandleScope.
  static v8::Local<v8::Context> NewContext(
      CcTestExtensionFlags extensions,
      v8::Isolate* isolate = CcTest::isolate());
146

147
  static void TearDown() {
148
    if (isolate_ != NULL) isolate_->Dispose();
149 150
  }

151
 private:
152
  friend int main(int argc, char** argv);
153 154 155
  TestFunction* callback_;
  const char* file_;
  const char* name_;
156
  bool enabled_;
157
  bool initialize_;
158
  CcTest* prev_;
159
  static CcTest* last_;
160
  static v8::ArrayBuffer::Allocator* allocator_;
161 162
  static v8::Isolate* isolate_;
  static bool initialize_called_;
163
  static v8::base::Atomic32 isolate_used_;
164 165
};

166 167 168 169 170 171 172 173 174 175
// Switches between all the Api tests using the threading support.
// In order to get a surprising but repeatable pattern of thread
// switching it has extra semaphores to control the order in which
// the tests alternate, not relying solely on the big V8 lock.
//
// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
// callbacks.  This will have no effect when we are not running the
// thread fuzzing test.  In the thread fuzzing test it will
// pseudorandomly select a successor thread and switch execution
// to that thread, suspending the current test.
176
class ApiTestFuzzer: public v8::base::Thread {
177 178 179 180 181 182
 public:
  void CallTest();

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

183 184 185 186 187
  enum PartOfTest { FIRST_PART,
                    SECOND_PART,
                    THIRD_PART,
                    FOURTH_PART,
                    LAST_PART = FOURTH_PART };
188

189
  static void SetUp(PartOfTest part);
190 191 192 193 194
  static void RunAllTests();
  static void TearDown();
  // This method switches threads if we are running the Threading test.
  // Otherwise it does nothing.
  static void Fuzz();
195

196
 private:
197
  explicit ApiTestFuzzer(int num)
198
      : Thread(Options("ApiTestFuzzer")),
199
        test_number_(num),
200
        gate_(0),
201
        active_(true) {}
202
  ~ApiTestFuzzer() {}
203

204 205 206 207 208 209
  static bool fuzzing_;
  static int tests_being_run_;
  static int current_;
  static int active_tests_;
  static bool NextThread();
  int test_number_;
210
  v8::base::Semaphore gate_;
211 212 213
  bool active_;
  void ContextSwitch();
  static int GetNextTestNumber();
214
  static v8::base::Semaphore all_tests_done_;
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
};


#define THREADED_TEST(Name)                                          \
  static void Test##Name();                                          \
  RegisterThreadedTest register_##Name(Test##Name, #Name);           \
  /* */ TEST(Name)


class RegisterThreadedTest {
 public:
  explicit RegisterThreadedTest(CcTest::TestFunction* callback,
                                const char* name)
      : fuzzer_(NULL), callback_(callback), name_(name) {
    prev_ = first_;
    first_ = this;
    count_++;
  }
  static int count() { return count_; }
  static RegisterThreadedTest* nth(int i) {
    CHECK(i < count());
    RegisterThreadedTest* current = first_;
    while (i > 0) {
      i--;
      current = current->prev_;
    }
    return current;
  }
  CcTest::TestFunction* callback() { return callback_; }
  ApiTestFuzzer* fuzzer_;
  const char* name() { return name_; }

 private:
  static RegisterThreadedTest* first_;
  static int count_;
  CcTest::TestFunction* callback_;
  RegisterThreadedTest* prev_;
  const char* name_;
};

// A LocalContext holds a reference to a v8::Context.
class LocalContext {
 public:
258 259 260 261
  LocalContext(v8::Isolate* isolate, v8::ExtensionConfiguration* extensions = 0,
               v8::Local<v8::ObjectTemplate> global_template =
                   v8::Local<v8::ObjectTemplate>(),
               v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
262 263 264
    Initialize(isolate, extensions, global_template, global_object);
  }

265
  LocalContext(v8::ExtensionConfiguration* extensions = 0,
266 267 268
               v8::Local<v8::ObjectTemplate> global_template =
                   v8::Local<v8::ObjectTemplate>(),
               v8::Local<v8::Value> global_object = v8::Local<v8::Value>()) {
269
    Initialize(CcTest::isolate(), extensions, global_template, global_object);
270 271 272
  }

  virtual ~LocalContext() {
273 274
    v8::HandleScope scope(isolate_);
    v8::Local<v8::Context>::New(isolate_, context_)->Exit();
275
    context_.Reset();
276 277
  }

278 279 280 281
  v8::Context* operator->() {
    return *reinterpret_cast<v8::Context**>(&context_);
  }
  v8::Context* operator*() { return operator->(); }
282 283 284
  bool IsReady() { return !context_.IsEmpty(); }

  v8::Local<v8::Context> local() {
285
    return v8::Local<v8::Context>::New(isolate_, context_);
286 287 288
  }

 private:
289 290 291
  void Initialize(v8::Isolate* isolate, v8::ExtensionConfiguration* extensions,
                  v8::Local<v8::ObjectTemplate> global_template,
                  v8::Local<v8::Value> global_object) {
292 293 294 295 296 297 298 299 300 301 302
     v8::HandleScope scope(isolate);
     v8::Local<v8::Context> context = v8::Context::New(isolate,
                                                       extensions,
                                                       global_template,
                                                       global_object);
     context_.Reset(isolate, context);
     context->Enter();
     // We can't do this later perhaps because of a fatal error.
     isolate_ = isolate;
  }

303
  v8::Persistent<v8::Context> context_;
304
  v8::Isolate* isolate_;
305 306
};

307 308 309 310 311 312 313 314 315

static inline uint16_t* AsciiToTwoByteString(const char* source) {
  int array_length = i::StrLength(source) + 1;
  uint16_t* converted = i::NewArray<uint16_t>(array_length);
  for (int i = 0; i < array_length; i++) converted[i] = source[i];
  return converted;
}


316
static inline v8::Local<v8::Value> v8_num(double x) {
317
  return v8::Number::New(v8::Isolate::GetCurrent(), x);
318 319 320 321
}


static inline v8::Local<v8::String> v8_str(const char* x) {
322 323 324
  return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x,
                                 v8::NewStringType::kNormal)
      .ToLocalChecked();
325 326 327
}


328 329 330 331 332 333 334
static inline v8::Local<v8::String> v8_str(v8::Isolate* isolate,
                                           const char* x) {
  return v8::String::NewFromUtf8(isolate, x, v8::NewStringType::kNormal)
      .ToLocalChecked();
}


335 336 337 338 339
static inline v8::Local<v8::Symbol> v8_symbol(const char* name) {
  return v8::Symbol::New(v8::Isolate::GetCurrent(), v8_str(name));
}


340 341 342 343 344 345 346
static inline v8::Local<v8::Script> v8_compile(v8::Local<v8::String> x) {
  v8::Local<v8::Script> result;
  if (v8::Script::Compile(v8::Isolate::GetCurrent()->GetCurrentContext(), x)
          .ToLocal(&result)) {
    return result;
  }
  return v8::Local<v8::Script>();
347 348 349
}


350 351
static inline v8::Local<v8::Script> v8_compile(const char* x) {
  return v8_compile(v8_str(x));
352 353 354
}


355 356 357 358 359 360
static inline int32_t v8_run_int32value(v8::Local<v8::Script> script) {
  v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
  return script->Run(context).ToLocalChecked()->Int32Value(context).FromJust();
}


361 362 363
static inline v8::Local<v8::Script> CompileWithOrigin(
    v8::Local<v8::String> source, v8::Local<v8::String> origin_url) {
  v8::ScriptOrigin origin(origin_url);
364
  v8::ScriptCompiler::Source script_source(source, origin);
365
  return v8::ScriptCompiler::Compile(
366 367
             v8::Isolate::GetCurrent()->GetCurrentContext(), &script_source)
      .ToLocalChecked();
368 369 370 371 372
}


static inline v8::Local<v8::Script> CompileWithOrigin(
    v8::Local<v8::String> source, const char* origin_url) {
373 374 375 376 377 378 379
  return CompileWithOrigin(source, v8_str(origin_url));
}


static inline v8::Local<v8::Script> CompileWithOrigin(const char* source,
                                                      const char* origin_url) {
  return CompileWithOrigin(v8_str(source), v8_str(origin_url));
380 381 382 383
}


// Helper functions that compile and run the source.
384 385 386 387 388 389 390 391
static inline v8::MaybeLocal<v8::Value> CompileRun(
    v8::Local<v8::Context> context, const char* source) {
  return v8::Script::Compile(context, v8_str(source))
      .ToLocalChecked()
      ->Run(context);
}


392 393 394 395 396 397 398 399 400 401 402 403
static inline v8::Local<v8::Value> CompileRunChecked(v8::Isolate* isolate,
                                                     const char* source) {
  v8::Local<v8::String> source_string =
      v8::String::NewFromUtf8(isolate, source, v8::NewStringType::kNormal)
          .ToLocalChecked();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Script> script =
      v8::Script::Compile(context, source_string).ToLocalChecked();
  return script->Run(context).ToLocalChecked();
}


404 405 406 407 408 409 410 411
static inline v8::Local<v8::Value> CompileRun(v8::Local<v8::String> source) {
  v8::Local<v8::Value> result;
  if (v8_compile(source)
          ->Run(v8::Isolate::GetCurrent()->GetCurrentContext())
          .ToLocal(&result)) {
    return result;
  }
  return v8::Local<v8::Value>();
412 413 414
}


415
// Helper functions that compile and run the source.
416 417
static inline v8::Local<v8::Value> CompileRun(const char* source) {
  return CompileRun(v8_str(source));
418 419 420
}


421 422 423 424 425 426 427 428 429 430 431
static inline v8::Local<v8::Value> CompileRun(
    v8::Local<v8::Context> context, v8::ScriptCompiler::Source* script_source,
    v8::ScriptCompiler::CompileOptions options) {
  v8::Local<v8::Value> result;
  if (v8::ScriptCompiler::Compile(context, script_source, options)
          .ToLocalChecked()
          ->Run(context)
          .ToLocal(&result)) {
    return result;
  }
  return v8::Local<v8::Value>();
432 433
}

434

435
static inline v8::Local<v8::Value> ParserCacheCompileRun(const char* source) {
436 437
  // Compile once just to get the preparse data, then compile the second time
  // using the data.
438
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
439
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
440
  v8::ScriptCompiler::Source script_source(v8_str(source));
441 442 443
  v8::ScriptCompiler::Compile(context, &script_source,
                              v8::ScriptCompiler::kProduceParserCache)
      .ToLocalChecked();
444 445 446 447 448 449

  // Check whether we received cached data, and if so use it.
  v8::ScriptCompiler::CompileOptions options =
      script_source.GetCachedData() ? v8::ScriptCompiler::kConsumeParserCache
                                    : v8::ScriptCompiler::kNoCompileOptions;

450
  return CompileRun(context, &script_source, options);
451 452 453
}


454
// Helper functions that compile and run the source with given origin.
455 456 457 458
static inline v8::Local<v8::Value> CompileRunWithOrigin(const char* source,
                                                        const char* origin_url,
                                                        int line_number,
                                                        int column_number) {
459
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
460
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
461
  v8::ScriptOrigin origin(v8_str(origin_url),
462 463
                          v8::Integer::New(isolate, line_number),
                          v8::Integer::New(isolate, column_number));
464
  v8::ScriptCompiler::Source script_source(v8_str(source), origin);
465 466
  return CompileRun(context, &script_source,
                    v8::ScriptCompiler::CompileOptions());
467 468 469 470
}


static inline v8::Local<v8::Value> CompileRunWithOrigin(
471
    v8::Local<v8::String> source, const char* origin_url) {
472 473
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
474 475
  v8::ScriptCompiler::Source script_source(
      source, v8::ScriptOrigin(v8_str(origin_url)));
476 477
  return CompileRun(context, &script_source,
                    v8::ScriptCompiler::CompileOptions());
478 479 480 481 482 483
}


static inline v8::Local<v8::Value> CompileRunWithOrigin(
    const char* source, const char* origin_url) {
  return CompileRunWithOrigin(v8_str(source), origin_url);
484 485
}

486

487 488 489 490 491

static inline void ExpectString(const char* code, const char* expected) {
  v8::Local<v8::Value> result = CompileRun(code);
  CHECK(result->IsString());
  v8::String::Utf8Value utf8(result);
492
  CHECK_EQ(0, strcmp(expected, *utf8));
493 494 495 496 497 498
}


static inline void ExpectInt32(const char* code, int expected) {
  v8::Local<v8::Value> result = CompileRun(code);
  CHECK(result->IsInt32());
499 500 501
  CHECK_EQ(expected,
           result->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext())
               .FromJust());
502 503 504 505 506 507
}


static inline void ExpectBoolean(const char* code, bool expected) {
  v8::Local<v8::Value> result = CompileRun(code);
  CHECK(result->IsBoolean());
508 509 510
  CHECK_EQ(expected,
           result->BooleanValue(v8::Isolate::GetCurrent()->GetCurrentContext())
               .FromJust());
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
}


static inline void ExpectTrue(const char* code) {
  ExpectBoolean(code, true);
}


static inline void ExpectFalse(const char* code) {
  ExpectBoolean(code, false);
}


static inline void ExpectObject(const char* code,
                                v8::Local<v8::Value> expected) {
  v8::Local<v8::Value> result = CompileRun(code);
  CHECK(result->SameValue(expected));
}


static inline void ExpectUndefined(const char* code) {
  v8::Local<v8::Value> result = CompileRun(code);
  CHECK(result->IsUndefined());
}


537 538 539 540 541 542
static inline void ExpectNull(const char* code) {
  v8::Local<v8::Value> result = CompileRun(code);
  CHECK(result->IsNull());
}


543 544 545 546 547 548 549
static inline void CheckDoubleEquals(double expected, double actual) {
  const double kEpsilon = 1e-10;
  CHECK_LE(expected, actual + kEpsilon);
  CHECK_GE(expected, actual - kEpsilon);
}


550 551 552 553
static void DummyDebugEventListener(
    const v8::Debug::EventDetails& event_details) {}


554 555
static inline void EnableDebugger(v8::Isolate* isolate) {
  v8::Debug::SetDebugEventListener(isolate, &DummyDebugEventListener);
556 557 558
}


559 560 561
static inline void DisableDebugger(v8::Isolate* isolate) {
  v8::Debug::SetDebugEventListener(isolate, nullptr);
}
562 563


564 565
static inline void EmptyMessageQueues(v8::Isolate* isolate) {
  while (v8::platform::PumpMessageLoop(v8::internal::V8::GetCurrentPlatform(),
566 567
                                       isolate)) {
  }
568 569 570
}


571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
class InitializedHandleScope {
 public:
  InitializedHandleScope()
      : main_isolate_(CcTest::InitIsolateOnce()),
        handle_scope_(main_isolate_) {}

  // Prefixing the below with main_ reduces a lot of naming clashes.
  i::Isolate* main_isolate() { return main_isolate_; }

 private:
  i::Isolate* main_isolate_;
  i::HandleScope handle_scope_;
};


class HandleAndZoneScope : public InitializedHandleScope {
 public:
588
  HandleAndZoneScope() : main_zone_(&allocator_) {}
589 590 591 592 593

  // Prefixing the below with main_ reduces a lot of naming clashes.
  i::Zone* main_zone() { return &main_zone_; }

 private:
594
  v8::base::AccountingAllocator allocator_;
595 596 597
  i::Zone main_zone_;
};

598
#endif  // ifndef CCTEST_H_