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;
Create(v8::Isolate * isolate)25 static Handle<Result> Create(v8::Isolate* isolate) {
26 return CreateHandle(isolate, new Result());
27 }
28
count() const29 int count() const { return count_; }
set_count(int count)30 void set_count(int count) { count_ = count; }
31
Quit()32 void Quit() {
33 base::MessageLoop::current()->QuitNow();
34 }
35
36 private:
Result()37 Result() : count_(0) {
38 }
39
~Result()40 virtual ~Result() {
41 }
42
GetObjectTemplateBuilder(v8::Isolate * isolate)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 {
TestHelpergin::__anonab299e8b0111::TestHelper56 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
QuitSoongin::__anonab299e8b0111::TestHelper68 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
TEST_F(TimerUnittest,OneShot)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
TEST_F(TimerUnittest,OneShotCancel)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
TEST_F(TimerUnittest,Repeating)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
TEST_F(TimerUnittest,TimerCallbackToDestroyedRunner)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