summaryrefslogtreecommitdiffstats
path: root/gin/modules
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-06 22:23:26 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-06 22:23:26 +0000
commit6f61c193736b7b7150ec5123b8705e6eb51e143c (patch)
tree82cd286a1df5a74943b58c12721f99edba990c32 /gin/modules
parent294084df84a7fea99c330b877207bec4186439ee (diff)
downloadchromium_src-6f61c193736b7b7150ec5123b8705e6eb51e143c.zip
chromium_src-6f61c193736b7b7150ec5123b8705e6eb51e143c.tar.gz
chromium_src-6f61c193736b7b7150ec5123b8705e6eb51e143c.tar.bz2
Added a test for destroying an isolate while a timer is outstanding.
Cleaned up a few of the existing tests. BUG= R=abarth@chromium.org Review URL: https://codereview.chromium.org/100143006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243185 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gin/modules')
-rw-r--r--gin/modules/timer.cc13
-rw-r--r--gin/modules/timer_unittest.cc120
2 files changed, 86 insertions, 47 deletions
diff --git a/gin/modules/timer.cc b/gin/modules/timer.cc
index ebe75bb..6baf2d2 100644
--- a/gin/modules/timer.cc
+++ b/gin/modules/timer.cc
@@ -18,7 +18,7 @@ v8::Handle<v8::String> GetHiddenPropertyName(v8::Isolate* isolate) {
} // namespace
-// Timer
+// Timer =======================================================================
gin::WrapperInfo Timer::kWrapperInfo = { gin::kEmbedderNativeGin };
@@ -30,6 +30,8 @@ Handle<Timer> Timer::Create(TimerType type, v8::Isolate* isolate, int delay_ms,
}
ObjectTemplateBuilder Timer::GetObjectTemplateBuilder(v8::Isolate* isolate) {
+ // We use Unretained() here because we directly own timer_, so we know it will
+ // be alive when these methods are called.
return Wrappable<Timer>::GetObjectTemplateBuilder(isolate)
.SetMethod("cancel",
base::Bind(&base::Timer::Stop, base::Unretained(&timer_)))
@@ -53,8 +55,13 @@ Timer::~Timer() {
}
void Timer::OnTimerFired() {
- if (!runner_)
+ // This can happen in spite of the weak callback because it is possible for
+ // a gin::Handle<> to keep this object alive past when the isolate it is part
+ // of is destroyed.
+ if (!runner_.get()) {
return;
+ }
+
Runner::Scope scope(runner_.get());
v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(
GetWrapper(runner_->isolate())->GetHiddenValue(
@@ -63,7 +70,7 @@ void Timer::OnTimerFired() {
}
-// TimerModule
+// TimerModule =================================================================
WrapperInfo TimerModule::kWrapperInfo = { kEmbedderNativeGin };
diff --git a/gin/modules/timer_unittest.cc b/gin/modules/timer_unittest.cc
index 96972d5..aaffbde 100644
--- a/gin/modules/timer_unittest.cc
+++ b/gin/modules/timer_unittest.cc
@@ -4,6 +4,7 @@
#include "gin/modules/timer.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
@@ -28,8 +29,8 @@ class Result : public Wrappable<Result> {
int count() const { return count_; }
void set_count(int count) { count_ = count; }
- void quit() {
- base::MessageLoop::current()->Quit();
+ void Quit() {
+ base::MessageLoop::current()->QuitNow();
}
private:
@@ -43,7 +44,7 @@ class Result : public Wrappable<Result> {
v8::Isolate* isolate) OVERRIDE {
return Wrappable<Result>::GetObjectTemplateBuilder(isolate)
.SetProperty("count", &Result::count, &Result::set_count)
- .SetMethod("quit", &Result::quit);
+ .SetMethod("quit", &Result::Quit);
}
int count_;
@@ -51,74 +52,105 @@ class Result : public Wrappable<Result> {
WrapperInfo Result::kWrapperInfo = { gin::kEmbedderNativeGin };
-} // namespace
-
-typedef V8Test TimerUnittest;
+struct TestHelper {
+ TestHelper(v8::Isolate* isolate)
+ : runner(new Runner(&delegate, isolate)),
+ scope(runner.get()),
+ timer_module(TimerModule::Create(isolate)),
+ result(Result::Create(isolate)),
+ loop(base::MessageLoop::TYPE_DEFAULT) {
+ EXPECT_FALSE(runner->global().IsEmpty());
+ runner->global()->Set(StringToV8(isolate, "timer"),
+ timer_module->GetWrapper(isolate));
+ runner->global()->Set(StringToV8(isolate, "result"),
+ result->GetWrapper(isolate));
+ }
-TEST_F(TimerUnittest, OneShot) {
- v8::Isolate* isolate = instance_->isolate();
+ void QuitSoon() {
+ loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ base::TimeDelta::FromMilliseconds(0));
+ }
RunnerDelegate delegate;
- Runner runner(&delegate, isolate);
- Runner::Scope scope(&runner);
+ scoped_ptr<Runner> runner;
+ Runner::Scope scope;
+ Handle<TimerModule> timer_module;
+ Handle<Result> result;
+ base::MessageLoop loop;
+};
- Handle<TimerModule> timer_module = TimerModule::Create(isolate);
- Handle<Result> result = Result::Create(isolate);
+} // namespace
- EXPECT_FALSE(runner.global().IsEmpty());
- runner.global()->Set(StringToV8(isolate, "timer"),
- timer_module->GetWrapper(isolate));
- runner.global()->Set(StringToV8(isolate, "result"),
- result->GetWrapper(isolate));
+typedef V8Test TimerUnittest;
+TEST_F(TimerUnittest, OneShot) {
+ TestHelper helper(instance_->isolate());
std::string source =
- "timer.createOneShot(100, function() {"
+ "timer.createOneShot(0, function() {"
" result.count++;"
- " result.quit();"
"});";
- base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
- runner.Run(source, "script");
- EXPECT_EQ(0, result->count());
+ helper.runner->Run(source, "script");
+ EXPECT_EQ(0, helper.result->count());
- loop.Run();
- loop.RunUntilIdle();
-
- EXPECT_EQ(1, result->count());
+ helper.QuitSoon();
+ helper.loop.Run();
+ EXPECT_EQ(1, helper.result->count());
}
-TEST_F(TimerUnittest, Repeating) {
- v8::Isolate* isolate = instance_->isolate();
+TEST_F(TimerUnittest, OneShotCancel) {
+ TestHelper helper(instance_->isolate());
+ std::string source =
+ "var t = timer.createOneShot(0, function() {"
+ " result.count++;"
+ "});"
+ "t.cancel()";
- RunnerDelegate delegate;
- Runner runner(&delegate, isolate);
- Runner::Scope scope(&runner);
+ helper.runner->Run(source, "script");
+ EXPECT_EQ(0, helper.result->count());
- Handle<TimerModule> timer_module = TimerModule::Create(isolate);
- Handle<Result> result = Result::Create(isolate);
+ helper.QuitSoon();
+ helper.loop.Run();
+ EXPECT_EQ(0, helper.result->count());
+}
- EXPECT_FALSE(runner.global().IsEmpty());
- runner.global()->Set(StringToV8(isolate, "timer"),
- timer_module->GetWrapper(isolate));
- runner.global()->Set(StringToV8(isolate, "result"),
- result->GetWrapper(isolate));
+TEST_F(TimerUnittest, Repeating) {
+ TestHelper helper(instance_->isolate());
// TODO(aa): Cannot do: if (++result.count == 3) because of v8 bug. Create
// test case and report.
std::string source =
- "timer.createRepeating(10, function() {"
+ "timer.createRepeating(0, function() {"
" result.count++;"
" if (result.count == 3) {"
" result.quit();"
" }"
"});";
- base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
- runner.Run(source, "script");
- EXPECT_EQ(0, result->count());
+ helper.runner->Run(source, "script");
+ EXPECT_EQ(0, helper.result->count());
+
+ helper.loop.Run();
+ EXPECT_EQ(3, helper.result->count());
+}
+
+TEST_F(TimerUnittest, TimerCallbackToDestroyedRunner) {
+ TestHelper helper(instance_->isolate());
+ std::string source =
+ "timer.createOneShot(0, function() {"
+ " result.count++;"
+ "});";
+
+ helper.runner->Run(source, "script");
+ EXPECT_EQ(0, helper.result->count());
+
+ // Destroy runner, which should destroy the timer object we created.
+ helper.QuitSoon();
+ helper.runner.reset(NULL);
+ helper.loop.Run();
- loop.Run();
- EXPECT_EQ(3, result->count());
+ // Timer should not have run because it was deleted.
+ EXPECT_EQ(0, helper.result->count());
}
} // namespace gin