Home | History | Annotate | Download | only in modules
      1 // Copyright 2013 The Chromium 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 
      5 #include "gin/modules/timer.h"
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "gin/handle.h"
     10 #include "gin/object_template_builder.h"
     11 #include "gin/public/isolate_holder.h"
     12 #include "gin/shell_runner.h"
     13 #include "gin/test/v8_test.h"
     14 #include "gin/try_catch.h"
     15 #include "gin/wrappable.h"
     16 #include "v8/include/v8.h"
     17 
     18 namespace gin {
     19 
     20 namespace {
     21 
     22 class Result : public Wrappable<Result> {
     23  public:
     24   static WrapperInfo kWrapperInfo;
     25   static Handle<Result> Create(v8::Isolate* isolate) {
     26     return CreateHandle(isolate, new Result());
     27   }
     28 
     29   int count() const { return count_; }
     30   void set_count(int count) { count_ = count; }
     31 
     32   void Quit() {
     33     base::MessageLoop::current()->QuitNow();
     34   }
     35 
     36  private:
     37   Result() : count_(0) {
     38   }
     39 
     40   virtual ~Result() {
     41   }
     42 
     43   virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
     44       v8::Isolate* isolate) OVERRIDE {
     45     return Wrappable<Result>::GetObjectTemplateBuilder(isolate)
     46         .SetProperty("count", &Result::count, &Result::set_count)
     47         .SetMethod("quit", &Result::Quit);
     48   }
     49 
     50   int count_;
     51 };
     52 
     53 WrapperInfo Result::kWrapperInfo = { gin::kEmbedderNativeGin };
     54 
     55 struct TestHelper {
     56   TestHelper(v8::Isolate* isolate)
     57       : runner(new ShellRunner(&delegate, isolate)),
     58         scope(runner.get()),
     59         timer_module(TimerModule::Create(isolate)),
     60         result(Result::Create(isolate)) {
     61     EXPECT_FALSE(runner->global().IsEmpty());
     62     runner->global()->Set(StringToV8(isolate, "timer"),
     63                           timer_module->GetWrapper(isolate));
     64     runner->global()->Set(StringToV8(isolate, "result"),
     65                           result->GetWrapper(isolate));
     66   }
     67 
     68   void QuitSoon() {
     69     loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
     70                          base::TimeDelta::FromMilliseconds(0));
     71   }
     72 
     73   ShellRunnerDelegate delegate;
     74   scoped_ptr<ShellRunner> runner;
     75   Runner::Scope scope;
     76   Handle<TimerModule> timer_module;
     77   Handle<Result> result;
     78   base::MessageLoop loop;
     79 };
     80 
     81 }  // namespace
     82 
     83 typedef V8Test TimerUnittest;
     84 
     85 TEST_F(TimerUnittest, OneShot) {
     86   TestHelper helper(instance_->isolate());
     87   std::string source =
     88      "timer.createOneShot(0, function() {"
     89      "  result.count++;"
     90      "});";
     91 
     92   helper.runner->Run(source, "script");
     93   EXPECT_EQ(0, helper.result->count());
     94 
     95   helper.QuitSoon();
     96   helper.loop.Run();
     97   EXPECT_EQ(1, helper.result->count());
     98 }
     99 
    100 TEST_F(TimerUnittest, OneShotCancel) {
    101   TestHelper helper(instance_->isolate());
    102   std::string source =
    103      "var t = timer.createOneShot(0, function() {"
    104      "  result.count++;"
    105      "});"
    106      "t.cancel()";
    107 
    108   helper.runner->Run(source, "script");
    109   EXPECT_EQ(0, helper.result->count());
    110 
    111   helper.QuitSoon();
    112   helper.loop.Run();
    113   EXPECT_EQ(0, helper.result->count());
    114 }
    115 
    116 TEST_F(TimerUnittest, Repeating) {
    117   TestHelper helper(instance_->isolate());
    118 
    119   // TODO(aa): Cannot do: if (++result.count == 3) because of v8 bug. Create
    120   // test case and report.
    121   std::string source =
    122      "timer.createRepeating(0, function() {"
    123      "  result.count++;"
    124      "  if (result.count == 3) {"
    125      "    result.quit();"
    126      "  }"
    127      "});";
    128 
    129   helper.runner->Run(source, "script");
    130   EXPECT_EQ(0, helper.result->count());
    131 
    132   helper.loop.Run();
    133   EXPECT_EQ(3, helper.result->count());
    134 }
    135 
    136 TEST_F(TimerUnittest, TimerCallbackToDestroyedRunner) {
    137   TestHelper helper(instance_->isolate());
    138   std::string source =
    139      "timer.createOneShot(0, function() {"
    140      "  result.count++;"
    141      "});";
    142 
    143   helper.runner->Run(source, "script");
    144   EXPECT_EQ(0, helper.result->count());
    145 
    146   // Destroy runner, which should destroy the timer object we created.
    147   helper.QuitSoon();
    148   helper.runner.reset(NULL);
    149   helper.loop.Run();
    150 
    151   // Timer should not have run because it was deleted.
    152   EXPECT_EQ(0, helper.result->count());
    153 }
    154 
    155 }  // namespace gin
    156