Home | History | Annotate | Download | only in cctest
      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);  \
     37   static void Test##Name()
     38 #endif
     39 
     40 #ifndef DEPENDENT_TEST
     41 #define DEPENDENT_TEST(Name, Dep)                                        \
     42   static void Test##Name();                                              \
     43   CcTest register_test_##Name(Test##Name, __FILE__, #Name, #Dep, true);  \
     44   static void Test##Name()
     45 #endif
     46 
     47 #ifndef DISABLED_TEST
     48 #define DISABLED_TEST(Name)                                              \
     49   static void Test##Name();                                              \
     50   CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, false); \
     51   static void Test##Name()
     52 #endif
     53 
     54 class CcTest {
     55  public:
     56   typedef void (TestFunction)();
     57   CcTest(TestFunction* callback, const char* file, const char* name,
     58          const char* dependency, bool enabled);
     59   void Run() { callback_(); }
     60   static int test_count();
     61   static CcTest* last() { return last_; }
     62   CcTest* prev() { return prev_; }
     63   const char* file() { return file_; }
     64   const char* name() { return name_; }
     65   const char* dependency() { return dependency_; }
     66   bool enabled() { return enabled_; }
     67  private:
     68   TestFunction* callback_;
     69   const char* file_;
     70   const char* name_;
     71   const char* dependency_;
     72   bool enabled_;
     73   static CcTest* last_;
     74   CcTest* prev_;
     75 };
     76 
     77 // Switches between all the Api tests using the threading support.
     78 // In order to get a surprising but repeatable pattern of thread
     79 // switching it has extra semaphores to control the order in which
     80 // the tests alternate, not relying solely on the big V8 lock.
     81 //
     82 // A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
     83 // callbacks.  This will have no effect when we are not running the
     84 // thread fuzzing test.  In the thread fuzzing test it will
     85 // pseudorandomly select a successor thread and switch execution
     86 // to that thread, suspending the current test.
     87 class ApiTestFuzzer: public v8::internal::Thread {
     88  public:
     89   void CallTest();
     90   explicit ApiTestFuzzer(int num)
     91       : test_number_(num),
     92         gate_(v8::internal::OS::CreateSemaphore(0)),
     93         active_(true) {
     94   }
     95   ~ApiTestFuzzer() { delete gate_; }
     96 
     97   // The ApiTestFuzzer is also a Thread, so it has a Run method.
     98   virtual void Run();
     99 
    100   enum PartOfTest { FIRST_PART, SECOND_PART };
    101 
    102   static void Setup(PartOfTest part);
    103   static void RunAllTests();
    104   static void TearDown();
    105   // This method switches threads if we are running the Threading test.
    106   // Otherwise it does nothing.
    107   static void Fuzz();
    108  private:
    109   static bool fuzzing_;
    110   static int tests_being_run_;
    111   static int current_;
    112   static int active_tests_;
    113   static bool NextThread();
    114   int test_number_;
    115   v8::internal::Semaphore* gate_;
    116   bool active_;
    117   void ContextSwitch();
    118   static int GetNextTestNumber();
    119   static v8::internal::Semaphore* all_tests_done_;
    120 };
    121 
    122 
    123 #define THREADED_TEST(Name)                                          \
    124   static void Test##Name();                                          \
    125   RegisterThreadedTest register_##Name(Test##Name, #Name);           \
    126   /* */ TEST(Name)
    127 
    128 
    129 class RegisterThreadedTest {
    130  public:
    131   explicit RegisterThreadedTest(CcTest::TestFunction* callback,
    132                                 const char* name)
    133       : fuzzer_(NULL), callback_(callback), name_(name) {
    134     prev_ = first_;
    135     first_ = this;
    136     count_++;
    137   }
    138   static int count() { return count_; }
    139   static RegisterThreadedTest* nth(int i) {
    140     CHECK(i < count());
    141     RegisterThreadedTest* current = first_;
    142     while (i > 0) {
    143       i--;
    144       current = current->prev_;
    145     }
    146     return current;
    147   }
    148   CcTest::TestFunction* callback() { return callback_; }
    149   ApiTestFuzzer* fuzzer_;
    150   const char* name() { return name_; }
    151 
    152  private:
    153   static RegisterThreadedTest* first_;
    154   static int count_;
    155   CcTest::TestFunction* callback_;
    156   RegisterThreadedTest* prev_;
    157   const char* name_;
    158 };
    159 
    160 
    161 // A LocalContext holds a reference to a v8::Context.
    162 class LocalContext {
    163  public:
    164   LocalContext(v8::ExtensionConfiguration* extensions = 0,
    165                v8::Handle<v8::ObjectTemplate> global_template =
    166                    v8::Handle<v8::ObjectTemplate>(),
    167                v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
    168     : context_(v8::Context::New(extensions, global_template, global_object)) {
    169     context_->Enter();
    170   }
    171 
    172   virtual ~LocalContext() {
    173     context_->Exit();
    174     context_.Dispose();
    175   }
    176 
    177   v8::Context* operator->() { return *context_; }
    178   v8::Context* operator*() { return *context_; }
    179   bool IsReady() { return !context_.IsEmpty(); }
    180 
    181   v8::Local<v8::Context> local() {
    182     return v8::Local<v8::Context>::New(context_);
    183   }
    184 
    185  private:
    186   v8::Persistent<v8::Context> context_;
    187 };
    188 
    189 
    190 static inline v8::Local<v8::Value> v8_num(double x) {
    191   return v8::Number::New(x);
    192 }
    193 
    194 
    195 static inline v8::Local<v8::String> v8_str(const char* x) {
    196   return v8::String::New(x);
    197 }
    198 
    199 
    200 static inline v8::Local<v8::Script> v8_compile(const char* x) {
    201   return v8::Script::Compile(v8_str(x));
    202 }
    203 
    204 
    205 // Helper function that compiles and runs the source.
    206 static inline v8::Local<v8::Value> CompileRun(const char* source) {
    207   return v8::Script::Compile(v8::String::New(source))->Run();
    208 }
    209 
    210 
    211 #endif  // ifndef CCTEST_H_
    212