blob: db5bbc01bad49a4fc6ccad56f3ec5df9323cc83e [file] [log] [blame]
Darin Petkov002c58e2012-06-19 02:56:05 +02001// Copyright (c) 2012 The Chromium OS 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 "shill/dbus_manager.h"
6
7#include <base/bind.h>
8#include <base/memory/weak_ptr.h>
9#include <gmock/gmock.h>
10#include <gtest/gtest.h>
11
12#include "shill/error.h"
13#include "shill/mock_dbus_service_proxy.h"
14#include "shill/proxy_factory.h"
15
16using base::Bind;
17using std::string;
18using testing::_;
19
20namespace shill {
21
22class DBusManagerTest : public testing::Test {
23 public:
24 DBusManagerTest()
25 : proxy_(new MockDBusServiceProxy()),
26 proxy_factory_(this) {}
27
28 virtual void SetUp() {
29 // Replaces the real proxy factory with a local one providing mock proxies.
30 dbus_manager_.proxy_factory_ = &proxy_factory_;
31 }
32
33 protected:
34 class TestProxyFactory : public ProxyFactory {
35 public:
Darin Petkov2b8e44e2012-06-25 15:13:26 +020036 explicit TestProxyFactory(DBusManagerTest *test) : test_(test) {}
Darin Petkov002c58e2012-06-19 02:56:05 +020037
38 virtual DBusServiceProxyInterface *CreateDBusServiceProxy() {
39 return test_->proxy_.release();
40 }
41
42 private:
43 DBusManagerTest *test_;
44
45 DISALLOW_COPY_AND_ASSIGN(TestProxyFactory);
46 };
47
48 class NameWatcher : public base::SupportsWeakPtr<NameWatcher> {
49 public:
50 NameWatcher(const string &name)
51 : on_appear_(Bind(&NameWatcher::OnAppear, AsWeakPtr(), name)),
52 on_vanish_(Bind(&NameWatcher::OnVanish, AsWeakPtr(), name)) {}
53 virtual ~NameWatcher() {}
54
55 MOCK_METHOD2(OnAppear, void(const string &name, const string &owner));
56 MOCK_METHOD1(OnVanish, void(const string &name));
57
58 const DBusManager::AppearedCallback &on_appear() const {
59 return on_appear_;
60 }
61
62 const DBusManager::VanishedCallback &on_vanish() const {
63 return on_vanish_;
64 }
65
66 DBusManager::NameWatcher GetWatcher() const {
67 return DBusManager::NameWatcher(on_appear_, on_vanish_);
68 }
69
70 DBusManager::NameWatcher GetAppearWatcher() const {
71 return DBusManager::NameWatcher(on_appear_,
72 DBusManager::VanishedCallback());
73 }
74
75 DBusManager::NameWatcher GetVanishWatcher() const {
76 return DBusManager::NameWatcher(DBusManager::AppearedCallback(),
77 on_vanish_);
78 }
79
80 private:
81 DBusManager::AppearedCallback on_appear_;
82 DBusManager::VanishedCallback on_vanish_;
83
84 DISALLOW_COPY_AND_ASSIGN(NameWatcher);
85 };
86
87 scoped_ptr<MockDBusServiceProxy> proxy_;
88 TestProxyFactory proxy_factory_;
89 DBusManager dbus_manager_;
90};
91
92TEST_F(DBusManagerTest, NameWatchers) {
93 static const char kName1[] = "org.chromium.Service1";
94 static const char kOwner1[] = ":1.17";
95 static const char kName2[] = "org.chromium.Service2";
96 static const char kOwner2[] = ":1.27";
97
98 MockDBusServiceProxy *proxy = proxy_.get();
99
100 // Start the DBus service manager.
101 EXPECT_CALL(*proxy, set_name_owner_changed_callback(_));
102 dbus_manager_.Start();
103 EXPECT_TRUE(dbus_manager_.proxy_.get());
104
105 // Expect no crash.
106 dbus_manager_.Start();
107
108 // Register a name watcher 1A for kName1.
109 scoped_ptr<NameWatcher> watcher1a(new NameWatcher(kName1));
110 EXPECT_CALL(*proxy, GetNameOwner(kName1, _, _, _));
111 dbus_manager_.WatchName(
112 kName1, watcher1a->on_appear(), watcher1a->on_vanish());
113
114 // 1A should be notified on the initial owner.
115 EXPECT_CALL(*watcher1a, OnAppear(kName1, kOwner1));
116 EXPECT_CALL(*watcher1a, OnVanish(_)).Times(0);
117 dbus_manager_.OnGetNameOwnerComplete(
118 watcher1a->GetWatcher(), kOwner1, Error());
119
120 // Register an appear-only watcher 1B for kName1.
121 scoped_ptr<NameWatcher> watcher1b(new NameWatcher(kName1));
122 EXPECT_CALL(*proxy, GetNameOwner(kName1, _, _, _));
123 dbus_manager_.WatchName(
124 kName1, watcher1b->on_appear(), DBusManager::VanishedCallback());
125
126 // 1B should be notified on the initial owner. 1A should not get any
127 // notification.
128 EXPECT_CALL(*watcher1a, OnAppear(_, _)).Times(0);
129 EXPECT_CALL(*watcher1b, OnAppear(kName1, kOwner1));
130 dbus_manager_.OnGetNameOwnerComplete(
131 watcher1b->GetAppearWatcher(), kOwner1, Error());
132
133 // Register a name watcher 2A for kName2.
134 scoped_ptr<NameWatcher> watcher2a(new NameWatcher(kName2));
135 EXPECT_CALL(*proxy, GetNameOwner(kName2, _, _, _));
136 dbus_manager_.WatchName(
137 kName2, watcher2a->on_appear(), watcher2a->on_vanish());
138
139 // 2A should be notified on the lack of initial owner.
140 EXPECT_CALL(*watcher2a, OnAppear(_, _)).Times(0);
141 EXPECT_CALL(*watcher2a, OnVanish(kName2));
142 dbus_manager_.OnGetNameOwnerComplete(
143 watcher2a->GetWatcher(), string(), Error());
144
145 // Register a vanish-only watcher 2B for kName2.
146 scoped_ptr<NameWatcher> watcher2b(new NameWatcher(kName2));
147 EXPECT_CALL(*proxy, GetNameOwner(kName2, _, _, _));
148 dbus_manager_.WatchName(
149 kName2, DBusManager::AppearedCallback(), watcher2b->on_vanish());
150
151 // 2B should be notified on the lack of initial owner. 2A should not get any
152 // notification.
153 EXPECT_CALL(*watcher2a, OnVanish(_)).Times(0);
154 EXPECT_CALL(*watcher2b, OnVanish(kName2));
155 dbus_manager_.OnGetNameOwnerComplete(
156 watcher2b->GetVanishWatcher(), string(), Error());
157
158 EXPECT_EQ(2, dbus_manager_.name_watchers_[kName1].size());
159 EXPECT_EQ(2, dbus_manager_.name_watchers_[kName2].size());
160
161 // Toggle kName1 owner.
162 EXPECT_CALL(*watcher1a, OnVanish(kName1));
163 EXPECT_CALL(*watcher1b, OnVanish(_)).Times(0);
164 dbus_manager_.OnNameOwnerChanged(kName1, kOwner1, string());
165 EXPECT_CALL(*watcher1a, OnAppear(kName1, kOwner1));
166 EXPECT_CALL(*watcher1b, OnAppear(kName1, kOwner1));
167 dbus_manager_.OnNameOwnerChanged(kName1, string(), kOwner1);
168
169 // Toggle kName2 owner.
170 EXPECT_CALL(*watcher2a, OnAppear(kName2, kOwner2));
171 EXPECT_CALL(*watcher2b, OnAppear(_, _)).Times(0);
172 dbus_manager_.OnNameOwnerChanged(kName2, string(), kOwner2);
173 EXPECT_CALL(*watcher2a, OnVanish(kName2));
174 EXPECT_CALL(*watcher2b, OnVanish(kName2));
175 dbus_manager_.OnNameOwnerChanged(kName2, kOwner2, string());
176
177 // Invalidate kName1 callbacks, ensure no crashes.
178 watcher1a.reset();
179 watcher1b.reset();
180 dbus_manager_.OnNameOwnerChanged(kName1, kOwner1, string());
181 dbus_manager_.OnNameOwnerChanged(kName1, string(), kOwner1);
182
183 // Stop the DBus service manager.
184 dbus_manager_.Stop();
185 EXPECT_FALSE(dbus_manager_.proxy_.get());
186 EXPECT_TRUE(dbus_manager_.name_watchers_.empty());
187
188 // Ensure no crash.
189 dbus_manager_.Stop();
190}
191
192} // namespace shill