1// Copyright 2014 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 "base/basictypes.h"
6#include "base/bind.h"
7#include "base/location.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/message_loop/message_loop_proxy.h"
10#include "base/run_loop.h"
11#include "base/time/time.h"
12#include "storage/browser/fileapi/timed_task_helper.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15using storage::TimedTaskHelper;
16
17namespace content {
18
19namespace {
20
21class Embedder {
22 public:
23  Embedder()
24      : timer_(base::MessageLoopProxy::current().get()), timer_fired_(false) {}
25
26  void OnTimerFired() {
27    timer_fired_ = true;
28  }
29
30  TimedTaskHelper* timer() { return &timer_; }
31  bool timer_fired() const { return timer_fired_; }
32
33 private:
34  TimedTaskHelper timer_;
35  bool timer_fired_;
36};
37
38}  // namespace
39
40TEST(TimedTaskHelper, FireTimerWhenAlive) {
41  base::MessageLoop message_loop;
42  Embedder embedder;
43
44  ASSERT_FALSE(embedder.timer_fired());
45  ASSERT_FALSE(embedder.timer()->IsRunning());
46
47  embedder.timer()->Start(
48      FROM_HERE,
49      base::TimeDelta::FromSeconds(0),
50      base::Bind(&Embedder::OnTimerFired, base::Unretained(&embedder)));
51
52  ASSERT_TRUE(embedder.timer()->IsRunning());
53  embedder.timer()->Reset();
54  ASSERT_TRUE(embedder.timer()->IsRunning());
55
56  base::RunLoop().RunUntilIdle();
57
58  ASSERT_TRUE(embedder.timer_fired());
59}
60
61TEST(TimedTaskHelper, FireTimerWhenAlreadyDeleted) {
62  base::MessageLoop message_loop;
63
64  // Run message loop after embedder is already deleted to make sure callback
65  // doesn't cause a crash for use after free.
66  {
67    Embedder embedder;
68
69    ASSERT_FALSE(embedder.timer_fired());
70    ASSERT_FALSE(embedder.timer()->IsRunning());
71
72    embedder.timer()->Start(
73        FROM_HERE,
74        base::TimeDelta::FromSeconds(0),
75        base::Bind(&Embedder::OnTimerFired, base::Unretained(&embedder)));
76
77    ASSERT_TRUE(embedder.timer()->IsRunning());
78  }
79
80  // At this point the callback is still in the message queue but
81  // embedder is gone.
82  base::RunLoop().RunUntilIdle();
83}
84
85}  // namespace content
86