1// Copyright (c) 2012 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 "media/base/bind_to_current_loop.h"
6
7#include "base/message_loop/message_loop.h"
8#include "base/synchronization/waitable_event.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace media {
12
13void BoundBoolSet(bool* var, bool val) {
14  *var = val;
15}
16
17void BoundBoolSetFromScopedPtr(bool* var, scoped_ptr<bool> val) {
18  *var = *val;
19}
20
21void BoundBoolSetFromScopedPtrFreeDeleter(
22    bool* var,
23    scoped_ptr<bool, base::FreeDeleter> val) {
24  *var = val;
25}
26
27void BoundBoolSetFromScopedArray(bool* var, scoped_ptr<bool[]> val) {
28  *var = val[0];
29}
30
31void BoundBoolSetFromConstRef(bool* var, const bool& val) {
32  *var = val;
33}
34
35void BoundIntegersSet(int* a_var, int* b_var, int a_val, int b_val) {
36  *a_var = a_val;
37  *b_var = b_val;
38}
39
40// Various tests that check that the bound function is only actually executed
41// on the message loop, not during the original Run.
42class BindToCurrentLoopTest : public ::testing::Test {
43 protected:
44  base::MessageLoop loop_;
45};
46
47TEST_F(BindToCurrentLoopTest, Closure) {
48  // Test the closure is run inside the loop, not outside it.
49  base::WaitableEvent waiter(false, false);
50  base::Closure cb = BindToCurrentLoop(base::Bind(
51      &base::WaitableEvent::Signal, base::Unretained(&waiter)));
52  cb.Run();
53  EXPECT_FALSE(waiter.IsSignaled());
54  loop_.RunUntilIdle();
55  EXPECT_TRUE(waiter.IsSignaled());
56}
57
58TEST_F(BindToCurrentLoopTest, Bool) {
59  bool bool_var = false;
60  base::Callback<void(bool)> cb = BindToCurrentLoop(base::Bind(
61      &BoundBoolSet, &bool_var));
62  cb.Run(true);
63  EXPECT_FALSE(bool_var);
64  loop_.RunUntilIdle();
65  EXPECT_TRUE(bool_var);
66}
67
68TEST_F(BindToCurrentLoopTest, BoundScopedPtrBool) {
69  bool bool_val = false;
70  scoped_ptr<bool> scoped_ptr_bool(new bool(true));
71  base::Closure cb = BindToCurrentLoop(base::Bind(
72      &BoundBoolSetFromScopedPtr, &bool_val, base::Passed(&scoped_ptr_bool)));
73  cb.Run();
74  EXPECT_FALSE(bool_val);
75  loop_.RunUntilIdle();
76  EXPECT_TRUE(bool_val);
77}
78
79TEST_F(BindToCurrentLoopTest, PassedScopedPtrBool) {
80  bool bool_val = false;
81  scoped_ptr<bool> scoped_ptr_bool(new bool(true));
82  base::Callback<void(scoped_ptr<bool>)> cb = BindToCurrentLoop(base::Bind(
83      &BoundBoolSetFromScopedPtr, &bool_val));
84  cb.Run(scoped_ptr_bool.Pass());
85  EXPECT_FALSE(bool_val);
86  loop_.RunUntilIdle();
87  EXPECT_TRUE(bool_val);
88}
89
90TEST_F(BindToCurrentLoopTest, BoundScopedArrayBool) {
91  bool bool_val = false;
92  scoped_ptr<bool[]> scoped_array_bool(new bool[1]);
93  scoped_array_bool[0] = true;
94  base::Closure cb = BindToCurrentLoop(base::Bind(
95      &BoundBoolSetFromScopedArray, &bool_val,
96      base::Passed(&scoped_array_bool)));
97  cb.Run();
98  EXPECT_FALSE(bool_val);
99  loop_.RunUntilIdle();
100  EXPECT_TRUE(bool_val);
101}
102
103TEST_F(BindToCurrentLoopTest, PassedScopedArrayBool) {
104  bool bool_val = false;
105  scoped_ptr<bool[]> scoped_array_bool(new bool[1]);
106  scoped_array_bool[0] = true;
107  base::Callback<void(scoped_ptr<bool[]>)> cb = BindToCurrentLoop(base::Bind(
108      &BoundBoolSetFromScopedArray, &bool_val));
109  cb.Run(scoped_array_bool.Pass());
110  EXPECT_FALSE(bool_val);
111  loop_.RunUntilIdle();
112  EXPECT_TRUE(bool_val);
113}
114
115TEST_F(BindToCurrentLoopTest, BoundScopedPtrFreeDeleterBool) {
116  bool bool_val = false;
117  scoped_ptr<bool, base::FreeDeleter> scoped_ptr_free_deleter_bool(
118      static_cast<bool*>(malloc(sizeof(bool))));
119  *scoped_ptr_free_deleter_bool = true;
120  base::Closure cb = BindToCurrentLoop(base::Bind(
121      &BoundBoolSetFromScopedPtrFreeDeleter, &bool_val,
122      base::Passed(&scoped_ptr_free_deleter_bool)));
123  cb.Run();
124  EXPECT_FALSE(bool_val);
125  loop_.RunUntilIdle();
126  EXPECT_TRUE(bool_val);
127}
128
129TEST_F(BindToCurrentLoopTest, PassedScopedPtrFreeDeleterBool) {
130  bool bool_val = false;
131  scoped_ptr<bool, base::FreeDeleter> scoped_ptr_free_deleter_bool(
132      static_cast<bool*>(malloc(sizeof(bool))));
133  *scoped_ptr_free_deleter_bool = true;
134  base::Callback<void(scoped_ptr<bool, base::FreeDeleter>)> cb =
135      BindToCurrentLoop(base::Bind(&BoundBoolSetFromScopedPtrFreeDeleter,
136      &bool_val));
137  cb.Run(scoped_ptr_free_deleter_bool.Pass());
138  EXPECT_FALSE(bool_val);
139  loop_.RunUntilIdle();
140  EXPECT_TRUE(bool_val);
141}
142
143TEST_F(BindToCurrentLoopTest, BoolConstRef) {
144  bool bool_var = false;
145  bool true_var = true;
146  const bool& true_ref = true_var;
147  base::Closure cb = BindToCurrentLoop(base::Bind(
148      &BoundBoolSetFromConstRef, &bool_var, true_ref));
149  cb.Run();
150  EXPECT_FALSE(bool_var);
151  loop_.RunUntilIdle();
152  EXPECT_TRUE(bool_var);
153}
154
155TEST_F(BindToCurrentLoopTest, Integers) {
156  int a = 0;
157  int b = 0;
158  base::Callback<void(int, int)> cb = BindToCurrentLoop(base::Bind(
159      &BoundIntegersSet, &a, &b));
160  cb.Run(1, -1);
161  EXPECT_EQ(a, 0);
162  EXPECT_EQ(b, 0);
163  loop_.RunUntilIdle();
164  EXPECT_EQ(a, 1);
165  EXPECT_EQ(b, -1);
166}
167
168}  // namespace media
169