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