blob: 10cad6e2b779f144e65b315efb0700bed7cef79e [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>
Darin Petkov002c58e2012-06-19 02:56:05 +02009
10#include "shill/error.h"
11#include "shill/mock_dbus_service_proxy.h"
Ben Chana55469d2014-01-27 16:35:29 -080012#include "shill/mock_proxy_factory.h"
13#include "shill/testing.h"
Darin Petkov002c58e2012-06-19 02:56:05 +020014
15using base::Bind;
Ben Chan084faca2013-07-02 14:25:12 -070016using base::Unretained;
Darin Petkov002c58e2012-06-19 02:56:05 +020017using std::string;
Ben Chan084faca2013-07-02 14:25:12 -070018using testing::Invoke;
19using testing::SaveArg;
20using testing::WithArg;
Darin Petkov002c58e2012-06-19 02:56:05 +020021using testing::_;
22
23namespace shill {
24
Ben Chan084faca2013-07-02 14:25:12 -070025namespace {
26
27const char kName1[] = "org.chromium.Service1";
28const char kOwner1[] = ":1.17";
29const char kName2[] = "org.chromium.Service2";
30const char kOwner2[] = ":1.27";
31
32void SetErrorOperationFailed(Error *error) {
33 error->Populate(Error::kOperationFailed);
34}
35
36} // namespace
37
Darin Petkov002c58e2012-06-19 02:56:05 +020038class DBusManagerTest : public testing::Test {
39 public:
40 DBusManagerTest()
41 : proxy_(new MockDBusServiceProxy()),
Ben Chan084faca2013-07-02 14:25:12 -070042 manager_(new DBusManager()) {}
Darin Petkov002c58e2012-06-19 02:56:05 +020043
44 virtual void SetUp() {
45 // Replaces the real proxy factory with a local one providing mock proxies.
Ben Chan084faca2013-07-02 14:25:12 -070046 manager_->proxy_factory_ = &proxy_factory_;
Darin Petkov002c58e2012-06-19 02:56:05 +020047 }
48
49 protected:
Ben Chan084faca2013-07-02 14:25:12 -070050 class DBusNameWatcherCallbackObserver {
Darin Petkov002c58e2012-06-19 02:56:05 +020051 public:
Ben Chan084faca2013-07-02 14:25:12 -070052 DBusNameWatcherCallbackObserver()
53 : name_appeared_callback_(
54 Bind(&DBusNameWatcherCallbackObserver::OnNameAppeared,
55 Unretained(this))),
56 name_vanished_callback_(
57 Bind(&DBusNameWatcherCallbackObserver::OnNameVanished,
58 Unretained(this))) {}
Darin Petkov002c58e2012-06-19 02:56:05 +020059
Ben Chan084faca2013-07-02 14:25:12 -070060 virtual ~DBusNameWatcherCallbackObserver() {}
Darin Petkov002c58e2012-06-19 02:56:05 +020061
Ben Chan084faca2013-07-02 14:25:12 -070062 MOCK_CONST_METHOD2(OnNameAppeared, void(const string &name,
63 const string &owner));
64 MOCK_CONST_METHOD1(OnNameVanished, void(const string &name));
65
66 const DBusNameWatcher::NameAppearedCallback &name_appeared_callback()
67 const {
68 return name_appeared_callback_;
Darin Petkov002c58e2012-06-19 02:56:05 +020069 }
70
Ben Chan084faca2013-07-02 14:25:12 -070071 const DBusNameWatcher::NameVanishedCallback &name_vanished_callback()
72 const {
73 return name_vanished_callback_;
Darin Petkov002c58e2012-06-19 02:56:05 +020074 }
75
76 private:
Ben Chan084faca2013-07-02 14:25:12 -070077 DBusNameWatcher::NameAppearedCallback name_appeared_callback_;
78 DBusNameWatcher::NameVanishedCallback name_vanished_callback_;
Darin Petkov002c58e2012-06-19 02:56:05 +020079
Ben Chan084faca2013-07-02 14:25:12 -070080 DISALLOW_COPY_AND_ASSIGN(DBusNameWatcherCallbackObserver);
Darin Petkov002c58e2012-06-19 02:56:05 +020081 };
82
Ben Chana55469d2014-01-27 16:35:29 -080083 MockDBusServiceProxy *ExpectCreateDBusServiceProxy() {
84 EXPECT_CALL(proxy_factory_, CreateDBusServiceProxy())
85 .WillOnce(ReturnAndReleasePointee(&proxy_));
86 return proxy_.get();
87 }
88
Darin Petkov002c58e2012-06-19 02:56:05 +020089 scoped_ptr<MockDBusServiceProxy> proxy_;
Ben Chana55469d2014-01-27 16:35:29 -080090 MockProxyFactory proxy_factory_;
Ben Chan084faca2013-07-02 14:25:12 -070091 scoped_ptr<DBusManager> manager_;
Darin Petkov002c58e2012-06-19 02:56:05 +020092};
93
Ben Chan084faca2013-07-02 14:25:12 -070094TEST_F(DBusManagerTest, GetNameOwnerFails) {
Ben Chana55469d2014-01-27 16:35:29 -080095 MockDBusServiceProxy *proxy = ExpectCreateDBusServiceProxy();
Darin Petkov002c58e2012-06-19 02:56:05 +020096
Ben Chan084faca2013-07-02 14:25:12 -070097 EXPECT_CALL(*proxy, set_name_owner_changed_callback(_));
98 manager_->Start();
99
100 EXPECT_CALL(*proxy, GetNameOwner(kName1, _, _, _))
101 .WillOnce(WithArg<1>(Invoke(SetErrorOperationFailed)));
102
103 DBusNameWatcherCallbackObserver observer;
104 EXPECT_CALL(observer, OnNameAppeared(_, _)).Times(0);
105 EXPECT_CALL(observer, OnNameVanished(kName1));
106
107 scoped_ptr<DBusNameWatcher> watcher(
108 manager_->CreateNameWatcher(kName1,
109 observer.name_appeared_callback(),
110 observer.name_vanished_callback()));
111}
112
113TEST_F(DBusManagerTest,
114 GetNameOwnerReturnsAfterDBusManagerAndNameWatcherDestroyed)
115{
Ben Chana55469d2014-01-27 16:35:29 -0800116 MockDBusServiceProxy *proxy = ExpectCreateDBusServiceProxy();
Ben Chan084faca2013-07-02 14:25:12 -0700117
118 EXPECT_CALL(*proxy, set_name_owner_changed_callback(_));
119 manager_->Start();
120
121 StringCallback get_name_owner_callback;
122 EXPECT_CALL(*proxy, GetNameOwner(kName1, _, _, _))
123 .WillOnce(SaveArg<2>(&get_name_owner_callback));
124 scoped_ptr<DBusNameWatcher> watcher(
125 manager_->CreateNameWatcher(kName1,
126 DBusNameWatcher::NameAppearedCallback(),
127 DBusNameWatcher::NameVanishedCallback()));
128
129 // Expect no crash if the GetNameOwner callback is invoked after the
130 // DBusNameWatcher object is destroyed.
131 watcher.reset();
132 get_name_owner_callback.Run(kOwner1, Error());
133
134 // Expect no crash if the GetNameOwner callback is invoked after the
135 // DBusManager object is destroyed.
136 manager_.reset();
137 get_name_owner_callback.Run(kOwner1, Error());
138}
139
140TEST_F(DBusManagerTest, NameWatchers) {
Ben Chana55469d2014-01-27 16:35:29 -0800141 MockDBusServiceProxy *proxy = ExpectCreateDBusServiceProxy();
Darin Petkov002c58e2012-06-19 02:56:05 +0200142
143 // Start the DBus service manager.
144 EXPECT_CALL(*proxy, set_name_owner_changed_callback(_));
Ben Chan084faca2013-07-02 14:25:12 -0700145 manager_->Start();
146 EXPECT_TRUE(manager_->proxy_.get());
Darin Petkov002c58e2012-06-19 02:56:05 +0200147
Ben Chan084faca2013-07-02 14:25:12 -0700148 // Expect no crash when DBusManager::Start() is invoked again.
149 manager_->Start();
Darin Petkov002c58e2012-06-19 02:56:05 +0200150
Ben Chan084faca2013-07-02 14:25:12 -0700151 StringCallback get_name_owner_callback;
Darin Petkov002c58e2012-06-19 02:56:05 +0200152
Ben Chan084faca2013-07-02 14:25:12 -0700153 // Register a name watcher 1a for kName1.
154 EXPECT_CALL(*proxy, GetNameOwner(kName1, _, _, _))
155 .WillOnce(SaveArg<2>(&get_name_owner_callback));
156 DBusNameWatcherCallbackObserver observer1a;
157 scoped_ptr<DBusNameWatcher> watcher1a(
158 manager_->CreateNameWatcher(kName1,
159 observer1a.name_appeared_callback(),
160 observer1a.name_vanished_callback()));
Darin Petkov002c58e2012-06-19 02:56:05 +0200161
Ben Chan084faca2013-07-02 14:25:12 -0700162 // Observer 1a should be notified on the initial owner.
163 EXPECT_CALL(observer1a, OnNameAppeared(kName1, kOwner1));
164 EXPECT_CALL(observer1a, OnNameVanished(_)).Times(0);
165 get_name_owner_callback.Run(kOwner1, Error());
Darin Petkov002c58e2012-06-19 02:56:05 +0200166
Ben Chan084faca2013-07-02 14:25:12 -0700167 // Register an appear-only watcher 1b for kName1.
168 EXPECT_CALL(*proxy, GetNameOwner(kName1, _, _, _))
169 .WillOnce(SaveArg<2>(&get_name_owner_callback));
170 DBusNameWatcherCallbackObserver observer1b;
171 scoped_ptr<DBusNameWatcher> watcher1b(
172 manager_->CreateNameWatcher(kName1,
173 observer1b.name_appeared_callback(),
174 DBusNameWatcher::NameVanishedCallback()));
Darin Petkov002c58e2012-06-19 02:56:05 +0200175
Ben Chan084faca2013-07-02 14:25:12 -0700176 // Observer 1b should be notified on the initial owner. Observer 1a should
177 // not get any notification.
178 EXPECT_CALL(observer1a, OnNameAppeared(_, _)).Times(0);
179 EXPECT_CALL(observer1b, OnNameAppeared(kName1, kOwner1));
180 get_name_owner_callback.Run(kOwner1, Error());
Darin Petkov002c58e2012-06-19 02:56:05 +0200181
Ben Chan084faca2013-07-02 14:25:12 -0700182 // Register a name watcher 2a for kName2.
183 EXPECT_CALL(*proxy, GetNameOwner(kName2, _, _, _))
184 .WillOnce(SaveArg<2>(&get_name_owner_callback));
185 DBusNameWatcherCallbackObserver observer2a;
186 scoped_ptr<DBusNameWatcher> watcher2a(
187 manager_->CreateNameWatcher(kName2,
188 observer2a.name_appeared_callback(),
189 observer2a.name_vanished_callback()));
Darin Petkov002c58e2012-06-19 02:56:05 +0200190
Ben Chan084faca2013-07-02 14:25:12 -0700191 // Observer 2a should be notified on the lack of initial owner.
192 EXPECT_CALL(observer2a, OnNameAppeared(_, _)).Times(0);
193 EXPECT_CALL(observer2a, OnNameVanished(kName2));
194 get_name_owner_callback.Run(string(), Error());
Darin Petkov002c58e2012-06-19 02:56:05 +0200195
Ben Chan084faca2013-07-02 14:25:12 -0700196 // Register a vanish-only watcher 2b for kName2.
197 EXPECT_CALL(*proxy, GetNameOwner(kName2, _, _, _))
198 .WillOnce(SaveArg<2>(&get_name_owner_callback));
199 DBusNameWatcherCallbackObserver observer2b;
200 scoped_ptr<DBusNameWatcher> watcher2b(
201 manager_->CreateNameWatcher(kName2,
202 DBusNameWatcher::NameAppearedCallback(),
203 observer2b.name_vanished_callback()));
Darin Petkov002c58e2012-06-19 02:56:05 +0200204
Ben Chan084faca2013-07-02 14:25:12 -0700205 // Observer 2b should be notified on the lack of initial owner. Observer 2a
206 // should not get any notification.
207 EXPECT_CALL(observer2a, OnNameVanished(_)).Times(0);
208 EXPECT_CALL(observer2b, OnNameVanished(kName2));
209 get_name_owner_callback.Run(string(), Error());
210
211 EXPECT_EQ(2, manager_->name_watchers_[kName1].size());
212 EXPECT_EQ(2, manager_->name_watchers_[kName2].size());
Darin Petkov002c58e2012-06-19 02:56:05 +0200213
214 // Toggle kName1 owner.
Ben Chan084faca2013-07-02 14:25:12 -0700215 EXPECT_CALL(observer1a, OnNameVanished(kName1));
216 EXPECT_CALL(observer1b, OnNameVanished(_)).Times(0);
217 manager_->OnNameOwnerChanged(kName1, kOwner1, string());
218 EXPECT_CALL(observer1a, OnNameAppeared(kName1, kOwner1));
219 EXPECT_CALL(observer1b, OnNameAppeared(kName1, kOwner1));
220 manager_->OnNameOwnerChanged(kName1, string(), kOwner1);
Darin Petkov002c58e2012-06-19 02:56:05 +0200221
222 // Toggle kName2 owner.
Ben Chan084faca2013-07-02 14:25:12 -0700223 EXPECT_CALL(observer2a, OnNameAppeared(kName2, kOwner2));
224 EXPECT_CALL(observer2b, OnNameAppeared(_, _)).Times(0);
225 manager_->OnNameOwnerChanged(kName2, string(), kOwner2);
226 EXPECT_CALL(observer2a, OnNameVanished(kName2));
227 EXPECT_CALL(observer2b, OnNameVanished(kName2));
228 manager_->OnNameOwnerChanged(kName2, kOwner2, string());
Darin Petkov002c58e2012-06-19 02:56:05 +0200229
230 // Invalidate kName1 callbacks, ensure no crashes.
231 watcher1a.reset();
232 watcher1b.reset();
Ben Chan084faca2013-07-02 14:25:12 -0700233 manager_->OnNameOwnerChanged(kName1, kOwner1, string());
234 manager_->OnNameOwnerChanged(kName1, string(), kOwner1);
Darin Petkov002c58e2012-06-19 02:56:05 +0200235
236 // Stop the DBus service manager.
Ben Chan084faca2013-07-02 14:25:12 -0700237 manager_->Stop();
238 EXPECT_FALSE(manager_->proxy_.get());
239 EXPECT_TRUE(manager_->name_watchers_.empty());
Darin Petkov002c58e2012-06-19 02:56:05 +0200240
Ben Chan084faca2013-07-02 14:25:12 -0700241 // Ensure no crash if DBusManager::Stop() is inovked again.
242 manager_->Stop();
Darin Petkov002c58e2012-06-19 02:56:05 +0200243}
244
245} // namespace shill