Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 1 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 9 | |
| 10 | #include "shill/error.h" |
| 11 | #include "shill/mock_dbus_service_proxy.h" |
Ben Chan | a55469d | 2014-01-27 16:35:29 -0800 | [diff] [blame^] | 12 | #include "shill/mock_proxy_factory.h" |
| 13 | #include "shill/testing.h" |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 14 | |
| 15 | using base::Bind; |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 16 | using base::Unretained; |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 17 | using std::string; |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 18 | using testing::Invoke; |
| 19 | using testing::SaveArg; |
| 20 | using testing::WithArg; |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 21 | using testing::_; |
| 22 | |
| 23 | namespace shill { |
| 24 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 25 | namespace { |
| 26 | |
| 27 | const char kName1[] = "org.chromium.Service1"; |
| 28 | const char kOwner1[] = ":1.17"; |
| 29 | const char kName2[] = "org.chromium.Service2"; |
| 30 | const char kOwner2[] = ":1.27"; |
| 31 | |
| 32 | void SetErrorOperationFailed(Error *error) { |
| 33 | error->Populate(Error::kOperationFailed); |
| 34 | } |
| 35 | |
| 36 | } // namespace |
| 37 | |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 38 | class DBusManagerTest : public testing::Test { |
| 39 | public: |
| 40 | DBusManagerTest() |
| 41 | : proxy_(new MockDBusServiceProxy()), |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 42 | manager_(new DBusManager()) {} |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 43 | |
| 44 | virtual void SetUp() { |
| 45 | // Replaces the real proxy factory with a local one providing mock proxies. |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 46 | manager_->proxy_factory_ = &proxy_factory_; |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | protected: |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 50 | class DBusNameWatcherCallbackObserver { |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 51 | public: |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 52 | DBusNameWatcherCallbackObserver() |
| 53 | : name_appeared_callback_( |
| 54 | Bind(&DBusNameWatcherCallbackObserver::OnNameAppeared, |
| 55 | Unretained(this))), |
| 56 | name_vanished_callback_( |
| 57 | Bind(&DBusNameWatcherCallbackObserver::OnNameVanished, |
| 58 | Unretained(this))) {} |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 59 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 60 | virtual ~DBusNameWatcherCallbackObserver() {} |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 61 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 62 | 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 69 | } |
| 70 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 71 | const DBusNameWatcher::NameVanishedCallback &name_vanished_callback() |
| 72 | const { |
| 73 | return name_vanished_callback_; |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | private: |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 77 | DBusNameWatcher::NameAppearedCallback name_appeared_callback_; |
| 78 | DBusNameWatcher::NameVanishedCallback name_vanished_callback_; |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 79 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 80 | DISALLOW_COPY_AND_ASSIGN(DBusNameWatcherCallbackObserver); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 81 | }; |
| 82 | |
Ben Chan | a55469d | 2014-01-27 16:35:29 -0800 | [diff] [blame^] | 83 | MockDBusServiceProxy *ExpectCreateDBusServiceProxy() { |
| 84 | EXPECT_CALL(proxy_factory_, CreateDBusServiceProxy()) |
| 85 | .WillOnce(ReturnAndReleasePointee(&proxy_)); |
| 86 | return proxy_.get(); |
| 87 | } |
| 88 | |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 89 | scoped_ptr<MockDBusServiceProxy> proxy_; |
Ben Chan | a55469d | 2014-01-27 16:35:29 -0800 | [diff] [blame^] | 90 | MockProxyFactory proxy_factory_; |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 91 | scoped_ptr<DBusManager> manager_; |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 92 | }; |
| 93 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 94 | TEST_F(DBusManagerTest, GetNameOwnerFails) { |
Ben Chan | a55469d | 2014-01-27 16:35:29 -0800 | [diff] [blame^] | 95 | MockDBusServiceProxy *proxy = ExpectCreateDBusServiceProxy(); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 96 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 97 | 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 | |
| 113 | TEST_F(DBusManagerTest, |
| 114 | GetNameOwnerReturnsAfterDBusManagerAndNameWatcherDestroyed) |
| 115 | { |
Ben Chan | a55469d | 2014-01-27 16:35:29 -0800 | [diff] [blame^] | 116 | MockDBusServiceProxy *proxy = ExpectCreateDBusServiceProxy(); |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 117 | |
| 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 | |
| 140 | TEST_F(DBusManagerTest, NameWatchers) { |
Ben Chan | a55469d | 2014-01-27 16:35:29 -0800 | [diff] [blame^] | 141 | MockDBusServiceProxy *proxy = ExpectCreateDBusServiceProxy(); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 142 | |
| 143 | // Start the DBus service manager. |
| 144 | EXPECT_CALL(*proxy, set_name_owner_changed_callback(_)); |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 145 | manager_->Start(); |
| 146 | EXPECT_TRUE(manager_->proxy_.get()); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 147 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 148 | // Expect no crash when DBusManager::Start() is invoked again. |
| 149 | manager_->Start(); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 150 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 151 | StringCallback get_name_owner_callback; |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 152 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 153 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 161 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 162 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 166 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 167 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 175 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 176 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 181 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 182 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 190 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 191 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 195 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 196 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 204 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 205 | // 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 213 | |
| 214 | // Toggle kName1 owner. |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 215 | 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 221 | |
| 222 | // Toggle kName2 owner. |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 223 | 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 Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 229 | |
| 230 | // Invalidate kName1 callbacks, ensure no crashes. |
| 231 | watcher1a.reset(); |
| 232 | watcher1b.reset(); |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 233 | manager_->OnNameOwnerChanged(kName1, kOwner1, string()); |
| 234 | manager_->OnNameOwnerChanged(kName1, string(), kOwner1); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 235 | |
| 236 | // Stop the DBus service manager. |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 237 | manager_->Stop(); |
| 238 | EXPECT_FALSE(manager_->proxy_.get()); |
| 239 | EXPECT_TRUE(manager_->name_watchers_.empty()); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 240 | |
Ben Chan | 084faca | 2013-07-02 14:25:12 -0700 | [diff] [blame] | 241 | // Ensure no crash if DBusManager::Stop() is inovked again. |
| 242 | manager_->Stop(); |
Darin Petkov | 002c58e | 2012-06-19 02:56:05 +0200 | [diff] [blame] | 243 | } |
| 244 | |
| 245 | } // namespace shill |