LCOV - code coverage report
Current view: top level - test/cctest - cctest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 131 137 95.6 %
Date: 2019-01-20 Functions: 20 22 90.9 %

          Line data    Source code
       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 "src/objects-inl.h"
      34             : #include "src/trap-handler/trap-handler.h"
      35             : #include "test/cctest/print-extension.h"
      36             : #include "test/cctest/profiler-extension.h"
      37             : #include "test/cctest/trace-extension.h"
      38             : 
      39             : #if V8_OS_WIN
      40             : #include <windows.h>  // NOLINT
      41             : #if V8_CC_MSVC
      42             : #include <crtdbg.h>
      43             : #endif
      44             : #endif
      45             : 
      46             : enum InitializationState { kUnset, kUninitialized, kInitialized };
      47             : static InitializationState initialization_state_ = kUnset;
      48             : static bool disable_automatic_dispose_ = false;
      49             : 
      50             : CcTest* CcTest::last_ = nullptr;
      51             : bool CcTest::initialize_called_ = false;
      52             : v8::base::Atomic32 CcTest::isolate_used_ = 0;
      53             : v8::ArrayBuffer::Allocator* CcTest::allocator_ = nullptr;
      54             : v8::Isolate* CcTest::isolate_ = nullptr;
      55             : 
      56   162257662 : CcTest::CcTest(TestFunction* callback, const char* file, const char* name,
      57             :                bool enabled, bool initialize)
      58             :     : callback_(callback),
      59             :       name_(name),
      60             :       enabled_(enabled),
      61             :       initialize_(initialize),
      62   162257662 :       prev_(last_) {
      63             :   // Find the base name of this test (const_cast required on Windows).
      64             :   char *basename = strrchr(const_cast<char *>(file), '/');
      65   162257662 :   if (!basename) {
      66             :     basename = strrchr(const_cast<char *>(file), '\\');
      67             :   }
      68   162257662 :   if (!basename) {
      69           0 :     basename = v8::internal::StrDup(file);
      70             :   } else {
      71   162257662 :     basename = v8::internal::StrDup(basename + 1);
      72             :   }
      73             :   // Drop the extension, if there is one.
      74             :   char *extension = strrchr(basename, '.');
      75   162257662 :   if (extension) *extension = 0;
      76             :   // Install this test in the list of tests
      77   162257662 :   file_ = basename;
      78   162257662 :   prev_ = last_;
      79   162257662 :   last_ = this;
      80   162257662 : }
      81             : 
      82             : 
      83       28335 : void CcTest::Run() {
      84       28335 :   if (!initialize_) {
      85         376 :     CHECK_NE(initialization_state_, kInitialized);
      86         376 :     initialization_state_ = kUninitialized;
      87         376 :     CHECK_NULL(CcTest::isolate_);
      88             :   } else {
      89       27959 :     CHECK_NE(initialization_state_, kUninitialized);
      90       27959 :     initialization_state_ = kInitialized;
      91       27959 :     if (isolate_ == nullptr) {
      92             :       v8::Isolate::CreateParams create_params;
      93       27959 :       create_params.array_buffer_allocator = allocator_;
      94       27959 :       isolate_ = v8::Isolate::New(create_params);
      95             :     }
      96       27959 :     isolate_->Enter();
      97             :   }
      98             : #ifdef DEBUG
      99             :   const size_t active_isolates = i::Isolate::non_disposed_isolates();
     100             : #endif  // DEBUG
     101       28335 :   callback_();
     102             : #ifdef DEBUG
     103             :   // This DCHECK ensures that all Isolates are properly disposed after finishing
     104             :   // the test. Stray Isolates lead to stray tasks in the platform which can
     105             :   // interact weirdly when swapping in new platforms (for testing) or during
     106             :   // shutdown.
     107             :   DCHECK_EQ(active_isolates, i::Isolate::non_disposed_isolates());
     108             : #endif  // DEBUG
     109       28320 :   if (initialize_) {
     110       27944 :     if (v8::Locker::IsActive()) {
     111         143 :       v8::Locker locker(isolate_);
     112         143 :       EmptyMessageQueues(isolate_);
     113             :     } else {
     114       27801 :       EmptyMessageQueues(isolate_);
     115             :     }
     116       27944 :     isolate_->Exit();
     117             :   }
     118       28320 : }
     119             : 
     120      649302 : i::Heap* CcTest::heap() { return i_isolate()->heap(); }
     121             : 
     122        2439 : void CcTest::CollectGarbage(i::AllocationSpace space) {
     123        2439 :   heap()->CollectGarbage(space, i::GarbageCollectionReason::kTesting);
     124        2439 : }
     125             : 
     126        4076 : void CcTest::CollectAllGarbage(i::Isolate* isolate) {
     127        4076 :   i::Isolate* iso = isolate ? isolate : i_isolate();
     128             :   iso->heap()->CollectAllGarbage(i::Heap::kNoGCFlags,
     129        4076 :                                  i::GarbageCollectionReason::kTesting);
     130        4076 : }
     131             : 
     132         352 : void CcTest::CollectAllAvailableGarbage(i::Isolate* isolate) {
     133         352 :   i::Isolate* iso = isolate ? isolate : i_isolate();
     134         352 :   iso->heap()->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
     135         352 : }
     136             : 
     137         173 : void CcTest::PreciseCollectAllGarbage(i::Isolate* isolate) {
     138         173 :   i::Isolate* iso = isolate ? isolate : i_isolate();
     139             :   iso->heap()->PreciseCollectAllGarbage(i::Heap::kNoGCFlags,
     140         173 :                                         i::GarbageCollectionReason::kTesting);
     141         173 : }
     142             : 
     143          55 : v8::base::RandomNumberGenerator* CcTest::random_number_generator() {
     144          55 :   return InitIsolateOnce()->random_number_generator();
     145             : }
     146             : 
     147        6932 : v8::Local<v8::Object> CcTest::global() {
     148       13864 :   return isolate()->GetCurrentContext()->Global();
     149             : }
     150             : 
     151       18886 : void CcTest::InitializeVM() {
     152       18886 :   CHECK(!v8::base::Relaxed_Load(&isolate_used_));
     153       18886 :   CHECK(!initialize_called_);
     154       18886 :   initialize_called_ = true;
     155       18886 :   v8::HandleScope handle_scope(CcTest::isolate());
     156       37772 :   v8::Context::New(CcTest::isolate())->Enter();
     157       18886 : }
     158             : 
     159           0 : void CcTest::TearDown() {
     160       28322 :   if (isolate_ != nullptr) isolate_->Dispose();
     161           0 : }
     162             : 
     163          78 : v8::Local<v8::Context> CcTest::NewContext(CcTestExtensionFlags extension_flags,
     164             :                                           v8::Isolate* isolate) {
     165             :   const char* extension_names[kMaxExtensions];
     166             :   int extension_count = 0;
     167         390 :   for (int i = 0; i < kMaxExtensions; ++i) {
     168         312 :     if (!extension_flags.contains(static_cast<CcTestExtensionId>(i))) continue;
     169          83 :     extension_names[extension_count] = kExtensionName[i];
     170          83 :     ++extension_count;
     171             :   }
     172             :   v8::ExtensionConfiguration config(extension_count, extension_names);
     173          78 :   v8::Local<v8::Context> context = v8::Context::New(isolate, &config);
     174          78 :   CHECK(!context.IsEmpty());
     175          78 :   return context;
     176             : }
     177             : 
     178           5 : void CcTest::DisableAutomaticDispose() {
     179           5 :   CHECK_EQ(kUninitialized, initialization_state_);
     180           5 :   disable_automatic_dispose_ = true;
     181           5 : }
     182             : 
     183       12285 : LocalContext::~LocalContext() {
     184       12285 :   v8::HandleScope scope(isolate_);
     185       24570 :   v8::Local<v8::Context>::New(isolate_, context_)->Exit();
     186       12285 :   context_.Reset();
     187       12285 : }
     188             : 
     189       12285 : void LocalContext::Initialize(v8::Isolate* isolate,
     190             :                               v8::ExtensionConfiguration* extensions,
     191             :                               v8::Local<v8::ObjectTemplate> global_template,
     192             :                               v8::Local<v8::Value> global_object) {
     193       12285 :   v8::HandleScope scope(isolate);
     194             :   v8::Local<v8::Context> context =
     195       12285 :       v8::Context::New(isolate, extensions, global_template, global_object);
     196             :   context_.Reset(isolate, context);
     197       12285 :   context->Enter();
     198             :   // We can't do this later perhaps because of a fatal error.
     199       12285 :   isolate_ = isolate;
     200       12285 : }
     201             : 
     202             : // This indirection is needed because HandleScopes cannot be heap-allocated, and
     203             : // we don't want any unnecessary #includes in cctest.h.
     204             : class InitializedHandleScopeImpl {
     205             :  public:
     206             :   explicit InitializedHandleScopeImpl(i::Isolate* isolate)
     207             :       : handle_scope_(isolate) {}
     208             : 
     209             :  private:
     210             :   i::HandleScope handle_scope_;
     211             : };
     212             : 
     213     1759035 : InitializedHandleScope::InitializedHandleScope()
     214     1759035 :     : main_isolate_(CcTest::InitIsolateOnce()),
     215             :       initialized_handle_scope_impl_(
     216     3518070 :           new InitializedHandleScopeImpl(main_isolate_)) {}
     217             : 
     218             : InitializedHandleScope::~InitializedHandleScope() = default;
     219             : 
     220     1756750 : HandleAndZoneScope::HandleAndZoneScope()
     221     3513500 :     : main_zone_(new i::Zone(&allocator_, ZONE_NAME)) {}
     222             : 
     223             : HandleAndZoneScope::~HandleAndZoneScope() = default;
     224             : 
     225       34358 : static void PrintTestList(CcTest* current) {
     226       22908 :   if (current == nullptr) return;
     227       11452 :   PrintTestList(current->prev());
     228             :   printf("%s/%s\n", current->file(), current->name());
     229             : }
     230             : 
     231             : 
     232             : static void SuggestTestHarness(int tests) {
     233       28335 :   if (tests == 0) return;
     234             :   printf("Running multiple tests in sequence is deprecated and may cause "
     235             :          "bogus failure.  Consider using tools/run-tests.py instead.\n");
     236             : }
     237             : 
     238             : 
     239       28337 : int main(int argc, char* argv[]) {
     240             : #if V8_OS_WIN
     241             :   UINT new_flags =
     242             :       SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
     243             :   UINT existing_flags = SetErrorMode(new_flags);
     244             :   SetErrorMode(existing_flags | new_flags);
     245             : #if V8_CC_MSVC
     246             :   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
     247             :   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
     248             :   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
     249             :   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
     250             :   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
     251             :   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
     252             :   _set_error_mode(_OUT_TO_STDERR);
     253             : #endif  // V8_CC_MSVC
     254             : #endif  // V8_OS_WIN
     255             : 
     256             :   // hack to print cctest specific flags
     257      141653 :   for (int i = 1; i < argc; i++) {
     258      113316 :     char* arg = argv[i];
     259      113316 :     if ((strcmp(arg, "--help") == 0) || (strcmp(arg, "-h") == 0)) {
     260           0 :       printf("Usage: %s [--list] [[V8_FLAGS] CCTEST]\n", argv[0]);
     261             :       printf("\n");
     262             :       printf("Options:\n");
     263             :       printf("  --list:   list all cctests\n");
     264             :       printf("  CCTEST:   cctest identfier returned by --list\n");
     265             :       printf("  D8_FLAGS: see d8 output below\n");
     266             :       printf("\n\n");
     267             :     }
     268             :   }
     269             : 
     270       28337 :   v8::V8::InitializeICUDefaultLocation(argv[0]);
     271       56674 :   std::unique_ptr<v8::Platform> platform(v8::platform::NewDefaultPlatform());
     272       28337 :   v8::V8::InitializePlatform(platform.get());
     273       28337 :   v8::internal::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
     274       28337 :   v8::V8::Initialize();
     275       28337 :   v8::V8::InitializeExternalStartupData(argv[0]);
     276             : 
     277       28337 :   if (V8_TRAP_HANDLER_SUPPORTED && i::FLAG_wasm_trap_handler) {
     278             :     constexpr bool use_default_signal_handler = true;
     279       28337 :     CHECK(v8::V8::EnableWebAssemblyTrapHandler(use_default_signal_handler));
     280             :   }
     281             : 
     282             :   CcTest::set_array_buffer_allocator(
     283       28337 :       v8::ArrayBuffer::Allocator::NewDefaultAllocator());
     284             : 
     285       28337 :   i::PrintExtension print_extension;
     286       28337 :   v8::RegisterExtension(&print_extension);
     287       28337 :   i::ProfilerExtension profiler_extension;
     288       28337 :   v8::RegisterExtension(&profiler_extension);
     289       28337 :   i::TraceExtension trace_extension;
     290       28337 :   v8::RegisterExtension(&trace_extension);
     291             : 
     292             :   int tests_run = 0;
     293             :   bool print_run_count = true;
     294       67976 :   for (int i = 1; i < argc; i++) {
     295       39654 :     char* arg = argv[i];
     296       39654 :     if (strcmp(arg, "--list") == 0) {
     297           2 :       PrintTestList(CcTest::last());
     298             :       print_run_count = false;
     299             : 
     300             :     } else {
     301       39652 :       char* arg_copy = v8::internal::StrDup(arg);
     302             :       char* testname = strchr(arg_copy, '/');
     303       39652 :       if (testname) {
     304             :         // Split the string in two by nulling the slash and then run
     305             :         // exact matches.
     306       28335 :         *testname = 0;
     307             :         char* file = arg_copy;
     308       28335 :         char* name = testname + 1;
     309   495110722 :         CcTest* test = CcTest::last();
     310   162282165 :         while (test != nullptr) {
     311   162225510 :           if (test->enabled()
     312   162225510 :               && strcmp(test->file(), file) == 0
     313   170659717 :               && strcmp(test->name(), name) == 0) {
     314       28335 :             SuggestTestHarness(tests_run++);
     315       28335 :             test->Run();
     316             :           }
     317             :           test = test->prev();
     318             :         }
     319             : 
     320             :       } else {
     321             :         // Run all tests with the specified file or test name.
     322             :         char* file_or_name = arg_copy;
     323   259204568 :         CcTest* test = CcTest::last();
     324    64823776 :         while (test != nullptr) {
     325    64801142 :           if (test->enabled()
     326   129602284 :               && (strcmp(test->file(), file_or_name) == 0
     327    64801142 :                   || strcmp(test->name(), file_or_name) == 0)) {
     328           0 :             SuggestTestHarness(tests_run++);
     329           0 :             test->Run();
     330             :           }
     331             :           test = test->prev();
     332             :         }
     333             :       }
     334             :       v8::internal::DeleteArray<char>(arg_copy);
     335             :     }
     336             :   }
     337       28322 :   if (print_run_count && tests_run != 1)
     338             :     printf("Ran %i tests.\n", tests_run);
     339             :   CcTest::TearDown();
     340             :   // TODO(svenpanne) See comment above.
     341             :   // if (!disable_automatic_dispose_) v8::V8::Dispose();
     342       28322 :   v8::V8::ShutdownPlatform();
     343             :   return 0;
     344             : }
     345             : 
     346             : RegisterThreadedTest* RegisterThreadedTest::first_ = nullptr;
     347       85011 : int RegisterThreadedTest::count_ = 0;

Generated by: LCOV version 1.10