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 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 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 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 124 void CcTest::DisableAutomaticDispose() { 125 CHECK_EQ(kUnintialized, initialization_state_); 126 disable_automatic_dispose_ = true; 127 } 128 129 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 { 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 } 142 virtual void* AllocateUninitialized(size_t length) { 143 return malloc(length == 0 ? 1 : length); 144 } 145 virtual void Free(void* data, size_t length) { free(data); } 146 // TODO(dslomov): Remove when v8:2823 is fixed. 147 virtual void Free(void* data) { UNREACHABLE(); } 148 }; 149 150 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 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