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