• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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);
Run()59   void Run() { callback_(); }
60   static int test_count();
last()61   static CcTest* last() { return last_; }
prev()62   CcTest* prev() { return prev_; }
file()63   const char* file() { return file_; }
name()64   const char* name() { return name_; }
dependency()65   const char* dependency() { return dependency_; }
enabled()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();
ApiTestFuzzer(int num)90   explicit ApiTestFuzzer(int num)
91       : test_number_(num),
92         gate_(v8::internal::OS::CreateSemaphore(0)),
93         active_(true) {
94   }
~ApiTestFuzzer()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:
RegisterThreadedTest(CcTest::TestFunction * callback,const char * name)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   }
count()138   static int count() { return count_; }
nth(int i)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   }
callback()148   CcTest::TestFunction* callback() { return callback_; }
149   ApiTestFuzzer* fuzzer_;
name()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>())
context_(v8::Context::New (extensions,global_template,global_object))168     : context_(v8::Context::New(extensions, global_template, global_object)) {
169     context_->Enter();
170   }
171 
~LocalContext()172   virtual ~LocalContext() {
173     context_->Exit();
174     context_.Dispose();
175   }
176 
177   v8::Context* operator->() { return *context_; }
178   v8::Context* operator*() { return *context_; }
IsReady()179   bool IsReady() { return !context_.IsEmpty(); }
180 
local()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 
v8_num(double x)190 static inline v8::Local<v8::Value> v8_num(double x) {
191   return v8::Number::New(x);
192 }
193 
194 
v8_str(const char * x)195 static inline v8::Local<v8::String> v8_str(const char* x) {
196   return v8::String::New(x);
197 }
198 
199 
v8_compile(const char * x)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.
CompileRun(const char * 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