LCOV - code coverage report
Current view: top level - test/cctest/libsampler - test-sampler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 44 90 48.9 %
Date: 2019-04-18 Functions: 7 20 35.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : // Tests of sampler functionalities.
       5             : 
       6             : #include "src/libsampler/sampler.h"
       7             : 
       8             : #include "src/base/platform/platform.h"
       9             : #include "src/base/platform/time.h"
      10             : #include "test/cctest/cctest.h"
      11             : 
      12             : 
      13             : namespace v8 {
      14             : namespace sampler {
      15             : 
      16             : namespace {
      17             : 
      18           0 : class TestSamplingThread : public base::Thread {
      19             :  public:
      20             :   static const int kSamplerThreadStackSize = 64 * 1024;
      21             : 
      22             :   explicit TestSamplingThread(Sampler* sampler)
      23             :       : Thread(base::Thread::Options("TestSamplingThread",
      24             :                                      kSamplerThreadStackSize)),
      25           0 :         sampler_(sampler) {}
      26             : 
      27             :   // Implement Thread::Run().
      28           0 :   void Run() override {
      29           0 :     while (sampler_->IsActive()) {
      30           0 :       sampler_->DoSample();
      31           0 :       base::OS::Sleep(base::TimeDelta::FromMilliseconds(1));
      32             :     }
      33           0 :   }
      34             : 
      35             :  private:
      36             :   Sampler* sampler_;
      37             : };
      38             : 
      39             : 
      40           0 : class TestSampler : public Sampler {
      41             :  public:
      42           0 :   explicit TestSampler(Isolate* isolate) : Sampler(isolate) {}
      43             : 
      44           0 :   void SampleStack(const v8::RegisterState& regs) override {
      45             :     void* frames[kMaxFramesCount];
      46             :     SampleInfo sample_info;
      47           0 :     isolate()->GetStackSample(regs, frames, kMaxFramesCount, &sample_info);
      48           0 :     if (is_counting_samples_) {
      49           0 :       if (sample_info.vm_state == JS) ++js_sample_count_;
      50           0 :       if (sample_info.vm_state == EXTERNAL) ++external_sample_count_;
      51             :     }
      52           0 :   }
      53             : };
      54             : 
      55             : 
      56             : class TestApiCallbacks {
      57             :  public:
      58             :   TestApiCallbacks() = default;
      59             : 
      60           0 :   static void Getter(v8::Local<v8::String> name,
      61             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
      62           0 :   }
      63             : 
      64           0 :   static void Setter(v8::Local<v8::String> name,
      65             :                      v8::Local<v8::Value> value,
      66             :                      const v8::PropertyCallbackInfo<void>& info) {
      67           0 :   }
      68             : };
      69             : 
      70             : 
      71           0 : static void RunSampler(v8::Local<v8::Context> env,
      72             :                        v8::Local<v8::Function> function,
      73             :                        v8::Local<v8::Value> argv[], int argc,
      74             :                        unsigned min_js_samples = 0,
      75             :                        unsigned min_external_samples = 0) {
      76           0 :   TestSampler sampler(env->GetIsolate());
      77             :   TestSamplingThread thread(&sampler);
      78           0 :   sampler.Start();
      79             :   sampler.StartCountingSamples();
      80           0 :   thread.StartSynchronously();
      81           0 :   do {
      82           0 :     function->Call(env, env->Global(), argc, argv).ToLocalChecked();
      83           0 :   } while (sampler.js_sample_count() < min_js_samples ||
      84             :            sampler.external_sample_count() < min_external_samples);
      85           0 :   sampler.Stop();
      86           0 :   thread.Join();
      87           0 : }
      88             : 
      89             : }  // namespace
      90             : 
      91             : static const char* sampler_test_source = "function start(count) {\n"
      92             : "  for (var i = 0; i < count; i++) {\n"
      93             : "    var o = instance.foo;\n"
      94             : "    instance.foo = o + 1;\n"
      95             : "  }\n"
      96             : "}\n";
      97             : 
      98           0 : static v8::Local<v8::Function> GetFunction(v8::Local<v8::Context> env,
      99             :                                            const char* name) {
     100             :   return v8::Local<v8::Function>::Cast(
     101           0 :       env->Global()->Get(env, v8_str(name)).ToLocalChecked());
     102             : }
     103             : 
     104             : 
     105       26656 : TEST(LibSamplerCollectSample) {
     106           0 :   LocalContext env;
     107           0 :   v8::Isolate* isolate = env->GetIsolate();
     108           0 :   v8::HandleScope scope(isolate);
     109             : 
     110             :   v8::Local<v8::FunctionTemplate> func_template =
     111           0 :       v8::FunctionTemplate::New(isolate);
     112             :   v8::Local<v8::ObjectTemplate> instance_template =
     113           0 :       func_template->InstanceTemplate();
     114             : 
     115             :   TestApiCallbacks accessors;
     116             :   v8::Local<v8::External> data =
     117           0 :       v8::External::New(isolate, &accessors);
     118           0 :   instance_template->SetAccessor(v8_str("foo"), &TestApiCallbacks::Getter,
     119           0 :                                  &TestApiCallbacks::Setter, data);
     120             :   v8::Local<v8::Function> func =
     121           0 :       func_template->GetFunction(env.local()).ToLocalChecked();
     122             :   v8::Local<v8::Object> instance =
     123             :       func->NewInstance(env.local()).ToLocalChecked();
     124           0 :   env->Global()->Set(env.local(), v8_str("instance"), instance).FromJust();
     125             : 
     126           0 :   CompileRun(sampler_test_source);
     127           0 :   v8::Local<v8::Function> function = GetFunction(env.local(), "start");
     128             : 
     129             :   int32_t repeat_count = 100;
     130           0 :   v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
     131           0 :   RunSampler(env.local(), function, args, arraysize(args), 100, 100);
     132           0 : }
     133             : 
     134             : #ifdef USE_SIGNALS
     135             : 
     136          10 : class CountingSampler : public Sampler {
     137             :  public:
     138          10 :   explicit CountingSampler(Isolate* isolate) : Sampler(isolate) {}
     139             : 
     140          10 :   void SampleStack(const v8::RegisterState& regs) override { sample_count_++; }
     141             : 
     142             :   int sample_count() { return sample_count_; }
     143             :   void set_active(bool active) { SetActive(active); }
     144             :   void set_should_record_sample() { SetShouldRecordSample(); }
     145             : 
     146             :  private:
     147             :   int sample_count_ = 0;
     148             : };
     149             : 
     150       26661 : TEST(SamplerManager_AddRemoveSampler) {
     151           5 :   LocalContext env;
     152           5 :   v8::Isolate* isolate = env->GetIsolate();
     153             : 
     154           5 :   SamplerManager* manager = SamplerManager::instance();
     155             :   CountingSampler sampler1(isolate);
     156             :   sampler1.set_active(true);
     157             :   sampler1.set_should_record_sample();
     158           5 :   CHECK_EQ(0, sampler1.sample_count());
     159             : 
     160           5 :   manager->AddSampler(&sampler1);
     161             : 
     162             :   RegisterState state;
     163           5 :   manager->DoSample(state);
     164           5 :   CHECK_EQ(1, sampler1.sample_count());
     165             : 
     166             :   sampler1.set_active(true);
     167             :   sampler1.set_should_record_sample();
     168           5 :   manager->RemoveSampler(&sampler1);
     169             :   sampler1.set_active(false);
     170             : 
     171           5 :   manager->DoSample(state);
     172           5 :   CHECK_EQ(1, sampler1.sample_count());
     173           5 : }
     174             : 
     175       26661 : TEST(SamplerManager_DoesNotReAdd) {
     176           5 :   LocalContext env;
     177           5 :   v8::Isolate* isolate = env->GetIsolate();
     178             : 
     179             :   // Add the same sampler twice, but check we only get one sample for it.
     180           5 :   SamplerManager* manager = SamplerManager::instance();
     181             :   CountingSampler sampler1(isolate);
     182             :   sampler1.set_active(true);
     183             :   sampler1.set_should_record_sample();
     184           5 :   manager->AddSampler(&sampler1);
     185           5 :   manager->AddSampler(&sampler1);
     186             : 
     187             :   RegisterState state;
     188           5 :   manager->DoSample(state);
     189           5 :   CHECK_EQ(1, sampler1.sample_count());
     190             :   sampler1.set_active(false);
     191           5 : }
     192             : 
     193       26661 : TEST(AtomicGuard_GetNonBlockingSuccess) {
     194           5 :   std::atomic_bool atomic{false};
     195             :   {
     196          10 :     AtomicGuard guard(&atomic, false);
     197           5 :     CHECK(guard.is_success());
     198             : 
     199          10 :     AtomicGuard guard2(&atomic, false);
     200           5 :     CHECK(!guard2.is_success());
     201             :   }
     202          10 :   AtomicGuard guard(&atomic, false);
     203           5 :   CHECK(guard.is_success());
     204           5 : }
     205             : 
     206       26661 : TEST(AtomicGuard_GetBlockingSuccess) {
     207           5 :   std::atomic_bool atomic{false};
     208             :   {
     209          10 :     AtomicGuard guard(&atomic);
     210           5 :     CHECK(guard.is_success());
     211             : 
     212          10 :     AtomicGuard guard2(&atomic, false);
     213           5 :     CHECK(!guard2.is_success());
     214             :   }
     215          10 :   AtomicGuard guard(&atomic);
     216           5 :   CHECK(guard.is_success());
     217           5 : }
     218             : 
     219             : #endif  // USE_SIGNALS
     220             : 
     221             : }  // namespace sampler
     222       79968 : }  // namespace v8

Generated by: LCOV version 1.10