LCOV - code coverage report
Current view: top level - test/cctest - cctest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 137 143 95.8 %
Date: 2019-04-17 Functions: 21 23 91.3 %

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

Generated by: LCOV version 1.10