• 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 #include "include/v8.h"
29 #include "test/cctest/cctest.h"
30 
31 #include "include/libplatform/libplatform.h"
32 #include "src/debug/debug.h"
33 #include "test/cctest/print-extension.h"
34 #include "test/cctest/profiler-extension.h"
35 #include "test/cctest/trace-extension.h"
36 
37 #if V8_OS_WIN
38 #include <windows.h>  // NOLINT
39 #if V8_CC_MSVC
40 #include <crtdbg.h>
41 #endif
42 #endif
43 
44 enum InitializationState {kUnset, kUnintialized, kInitialized};
45 static InitializationState initialization_state_  = kUnset;
46 static bool disable_automatic_dispose_ = false;
47 
48 CcTest* CcTest::last_ = NULL;
49 bool CcTest::initialize_called_ = false;
50 v8::base::Atomic32 CcTest::isolate_used_ = 0;
51 v8::ArrayBuffer::Allocator* CcTest::allocator_ = NULL;
52 v8::Isolate* CcTest::isolate_ = NULL;
53 
CcTest(TestFunction * callback,const char * file,const char * name,bool enabled,bool initialize)54 CcTest::CcTest(TestFunction* callback, const char* file, const char* name,
55                bool enabled, bool initialize)
56     : callback_(callback),
57       name_(name),
58       enabled_(enabled),
59       initialize_(initialize),
60       prev_(last_) {
61   // Find the base name of this test (const_cast required on Windows).
62   char *basename = strrchr(const_cast<char *>(file), '/');
63   if (!basename) {
64     basename = strrchr(const_cast<char *>(file), '\\');
65   }
66   if (!basename) {
67     basename = v8::internal::StrDup(file);
68   } else {
69     basename = v8::internal::StrDup(basename + 1);
70   }
71   // Drop the extension, if there is one.
72   char *extension = strrchr(basename, '.');
73   if (extension) *extension = 0;
74   // Install this test in the list of tests
75   file_ = basename;
76   prev_ = last_;
77   last_ = this;
78 }
79 
80 
Run()81 void CcTest::Run() {
82   if (!initialize_) {
83     CHECK(initialization_state_ != kInitialized);
84     initialization_state_ = kUnintialized;
85     CHECK(CcTest::isolate_ == NULL);
86   } else {
87     CHECK(initialization_state_ != kUnintialized);
88     initialization_state_ = kInitialized;
89     if (isolate_ == NULL) {
90       v8::Isolate::CreateParams create_params;
91       create_params.array_buffer_allocator = allocator_;
92       isolate_ = v8::Isolate::New(create_params);
93     }
94     isolate_->Enter();
95   }
96   callback_();
97   if (initialize_) {
98     if (v8::Locker::IsActive()) {
99       v8::Locker locker(isolate_);
100       EmptyMessageQueues(isolate_);
101     } else {
102       EmptyMessageQueues(isolate_);
103     }
104     isolate_->Exit();
105   }
106 }
107 
108 
NewContext(CcTestExtensionFlags extensions,v8::Isolate * isolate)109 v8::Local<v8::Context> CcTest::NewContext(CcTestExtensionFlags extensions,
110                                           v8::Isolate* isolate) {
111     const char* extension_names[kMaxExtensions];
112     int extension_count = 0;
113   #define CHECK_EXTENSION_FLAG(Name, Id) \
114     if (extensions.Contains(Name##_ID)) extension_names[extension_count++] = Id;
115     EXTENSION_LIST(CHECK_EXTENSION_FLAG)
116   #undef CHECK_EXTENSION_FLAG
117     v8::ExtensionConfiguration config(extension_count, extension_names);
118     v8::Local<v8::Context> context = v8::Context::New(isolate, &config);
119     CHECK(!context.IsEmpty());
120     return context;
121 }
122 
123 
DisableAutomaticDispose()124 void CcTest::DisableAutomaticDispose() {
125   CHECK_EQ(kUnintialized, initialization_state_);
126   disable_automatic_dispose_ = true;
127 }
128 
129 
PrintTestList(CcTest * current)130 static void PrintTestList(CcTest* current) {
131   if (current == NULL) return;
132   PrintTestList(current->prev());
133   printf("%s/%s\n", current->file(), current->name());
134 }
135 
136 
137 class CcTestArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
Allocate(size_t length)138   virtual void* Allocate(size_t length) {
139     void* data = AllocateUninitialized(length == 0 ? 1 : length);
140     return data == NULL ? data : memset(data, 0, length);
141   }
AllocateUninitialized(size_t length)142   virtual void* AllocateUninitialized(size_t length) {
143     return malloc(length == 0 ? 1 : length);
144   }
Free(void * data,size_t length)145   virtual void Free(void* data, size_t length) { free(data); }
146   // TODO(dslomov): Remove when v8:2823 is fixed.
Free(void * data)147   virtual void Free(void* data) { UNREACHABLE(); }
148 };
149 
150 
SuggestTestHarness(int tests)151 static void SuggestTestHarness(int tests) {
152   if (tests == 0) return;
153   printf("Running multiple tests in sequence is deprecated and may cause "
154          "bogus failure.  Consider using tools/run-tests.py instead.\n");
155 }
156 
157 
main(int argc,char * argv[])158 int main(int argc, char* argv[]) {
159 #if V8_OS_WIN
160   UINT new_flags =
161       SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
162   UINT existing_flags = SetErrorMode(new_flags);
163   SetErrorMode(existing_flags | new_flags);
164 #if V8_CC_MSVC
165   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
166   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
167   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
168   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
169   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
170   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
171   _set_error_mode(_OUT_TO_STDERR);
172 #endif  // V8_CC_MSVC
173 #endif  // V8_OS_WIN
174 
175   // hack to print cctest specific flags
176   for (int i = 1; i < argc; i++) {
177     char* arg = argv[i];
178     if ((strcmp(arg, "--help") == 0) || (strcmp(arg, "-h") == 0)) {
179       printf("Usage: %s [--list] [[V8_FLAGS] CCTEST]\n", argv[0]);
180       printf("\n");
181       printf("Options:\n");
182       printf("  --list:   list all cctests\n");
183       printf("  CCTEST:   cctest identfier returned by --list\n");
184       printf("  D8_FLAGS: see d8 output below\n");
185       printf("\n\n");
186     }
187   }
188 
189   v8::V8::InitializeICUDefaultLocation(argv[0]);
190   v8::Platform* platform = v8::platform::CreateDefaultPlatform();
191   v8::V8::InitializePlatform(platform);
192   v8::internal::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
193   v8::V8::Initialize();
194   v8::V8::InitializeExternalStartupData(argv[0]);
195 
196   CcTestArrayBufferAllocator array_buffer_allocator;
197   CcTest::set_array_buffer_allocator(&array_buffer_allocator);
198 
199   i::PrintExtension print_extension;
200   v8::RegisterExtension(&print_extension);
201   i::ProfilerExtension profiler_extension;
202   v8::RegisterExtension(&profiler_extension);
203   i::TraceExtension trace_extension;
204   v8::RegisterExtension(&trace_extension);
205 
206   int tests_run = 0;
207   bool print_run_count = true;
208   for (int i = 1; i < argc; i++) {
209     char* arg = argv[i];
210     if (strcmp(arg, "--list") == 0) {
211       PrintTestList(CcTest::last());
212       print_run_count = false;
213 
214     } else {
215       char* arg_copy = v8::internal::StrDup(arg);
216       char* testname = strchr(arg_copy, '/');
217       if (testname) {
218         // Split the string in two by nulling the slash and then run
219         // exact matches.
220         *testname = 0;
221         char* file = arg_copy;
222         char* name = testname + 1;
223         CcTest* test = CcTest::last();
224         while (test != NULL) {
225           if (test->enabled()
226               && strcmp(test->file(), file) == 0
227               && strcmp(test->name(), name) == 0) {
228             SuggestTestHarness(tests_run++);
229             test->Run();
230           }
231           test = test->prev();
232         }
233 
234       } else {
235         // Run all tests with the specified file or test name.
236         char* file_or_name = arg_copy;
237         CcTest* test = CcTest::last();
238         while (test != NULL) {
239           if (test->enabled()
240               && (strcmp(test->file(), file_or_name) == 0
241                   || strcmp(test->name(), file_or_name) == 0)) {
242             SuggestTestHarness(tests_run++);
243             test->Run();
244           }
245           test = test->prev();
246         }
247       }
248       v8::internal::DeleteArray<char>(arg_copy);
249     }
250   }
251   if (print_run_count && tests_run != 1)
252     printf("Ran %i tests.\n", tests_run);
253   CcTest::TearDown();
254   // TODO(svenpanne) See comment above.
255   // if (!disable_automatic_dispose_) v8::V8::Dispose();
256   v8::V8::ShutdownPlatform();
257   delete platform;
258   return 0;
259 }
260 
261 RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
262 int RegisterThreadedTest::count_ = 0;
263