15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/modules/timer.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/handle.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/object_template_builder.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/public/isolate_holder.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/shell_runner.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/test/v8_test.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/try_catch.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/wrappable.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "v8/include/v8.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gin {
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Result : public Wrappable<Result> {
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static WrapperInfo kWrapperInfo;
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static Handle<Result> Create(v8::Isolate* isolate) {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return CreateHandle(isolate, new Result());
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int count() const { return count_; }
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void set_count(int count) { count_ = count; }
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Quit() {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::MessageLoop::current()->QuitNow();
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Result() : count_(0) {
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~Result() {
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      v8::Isolate* isolate) OVERRIDE {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Wrappable<Result>::GetObjectTemplateBuilder(isolate)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        .SetProperty("count", &Result::count, &Result::set_count)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        .SetMethod("quit", &Result::Quit);
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int count_;
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WrapperInfo Result::kWrapperInfo = { gin::kEmbedderNativeGin };
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct TestHelper {
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestHelper(v8::Isolate* isolate)
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : runner(new ShellRunner(&delegate, isolate)),
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        scope(runner.get()),
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        timer_module(TimerModule::Create(isolate)),
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        result(Result::Create(isolate)) {
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_FALSE(runner->global().IsEmpty());
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    runner->global()->Set(StringToV8(isolate, "timer"),
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          timer_module->GetWrapper(isolate));
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    runner->global()->Set(StringToV8(isolate, "result"),
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          result->GetWrapper(isolate));
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void QuitSoon() {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         base::TimeDelta::FromMilliseconds(0));
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ShellRunnerDelegate delegate;
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<ShellRunner> runner;
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Runner::Scope scope;
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Handle<TimerModule> timer_module;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Handle<Result> result;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::MessageLoop loop;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef V8Test TimerUnittest;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(TimerUnittest, OneShot) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestHelper helper(instance_->isolate());
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string source =
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "timer.createOneShot(0, function() {"
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "  result.count++;"
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "});";
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.runner->Run(source, "script");
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, helper.result->count());
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.QuitSoon();
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.loop.Run();
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, helper.result->count());
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(TimerUnittest, OneShotCancel) {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestHelper helper(instance_->isolate());
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string source =
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "var t = timer.createOneShot(0, function() {"
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "  result.count++;"
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "});"
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "t.cancel()";
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.runner->Run(source, "script");
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, helper.result->count());
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.QuitSoon();
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.loop.Run();
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, helper.result->count());
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(TimerUnittest, Repeating) {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestHelper helper(instance_->isolate());
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(aa): Cannot do: if (++result.count == 3) because of v8 bug. Create
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // test case and report.
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string source =
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "timer.createRepeating(0, function() {"
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "  result.count++;"
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "  if (result.count == 3) {"
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "    result.quit();"
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "  }"
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "});";
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.runner->Run(source, "script");
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, helper.result->count());
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.loop.Run();
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(3, helper.result->count());
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(TimerUnittest, TimerCallbackToDestroyedRunner) {
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestHelper helper(instance_->isolate());
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string source =
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "timer.createOneShot(0, function() {"
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "  result.count++;"
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     "});";
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.runner->Run(source, "script");
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, helper.result->count());
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Destroy runner, which should destroy the timer object we created.
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.QuitSoon();
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.runner.reset(NULL);
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.loop.Run();
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Timer should not have run because it was deleted.
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, helper.result->count());
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace gin
156