| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "dbus/object_proxy.h" |
| #include "base/bind.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/run_loop.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "dbus/bus.h" |
| #include "dbus/test_service.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace dbus { |
| namespace { |
| |
| class ObjectProxyTest : public testing::Test { |
| protected: |
| ObjectProxyTest() {} |
| |
| void SetUp() override { |
| Bus::Options bus_options; |
| bus_options.bus_type = Bus::SESSION; |
| bus_options.connection_type = Bus::PRIVATE; |
| bus_ = new Bus(bus_options); |
| } |
| |
| void TearDown() override { bus_->ShutdownAndBlock(); } |
| |
| base::test::ScopedTaskEnvironment task_environment_{ |
| base::test::ScopedTaskEnvironment::MainThreadType::IO}; |
| |
| scoped_refptr<Bus> bus_; |
| }; |
| |
| // Used as a WaitForServiceToBeAvailableCallback. |
| void OnServiceIsAvailable(bool* dest_service_is_available, |
| int* num_calls, |
| bool src_service_is_available) { |
| *dest_service_is_available = src_service_is_available; |
| (*num_calls)++; |
| } |
| |
| // Used as a callback for TestService::RequestOwnership(). |
| void OnOwnershipRequestDone(bool success) { |
| ASSERT_TRUE(success); |
| } |
| |
| // Used as a callback for TestService::ReleaseOwnership(). |
| void OnOwnershipReleased() {} |
| |
| TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableRunOnce) { |
| TestService::Options options; |
| TestService test_service(options); |
| ObjectProxy* object_proxy = bus_->GetObjectProxy( |
| test_service.service_name(), ObjectPath("/org/chromium/TestObject")); |
| |
| // The callback is not yet called because the service is not available. |
| int num_calls = 0; |
| bool service_is_available = false; |
| object_proxy->WaitForServiceToBeAvailable( |
| base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls)); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(0, num_calls); |
| |
| // Start the service. The callback should be called asynchronously. |
| ASSERT_TRUE(test_service.StartService()); |
| test_service.WaitUntilServiceIsStarted(); |
| ASSERT_TRUE(test_service.has_ownership()); |
| num_calls = 0; |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, num_calls); |
| EXPECT_TRUE(service_is_available); |
| |
| // Release the service's ownership of its name. The callback should not be |
| // invoked again. |
| test_service.ReleaseOwnership(base::Bind(&OnOwnershipReleased)); |
| num_calls = 0; |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(0, num_calls); |
| |
| // Take ownership of the name and check that the callback is not called. |
| test_service.RequestOwnership(base::Bind(&OnOwnershipRequestDone)); |
| num_calls = 0; |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(0, num_calls); |
| } |
| |
| TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableAlreadyRunning) { |
| TestService::Options options; |
| TestService test_service(options); |
| ObjectProxy* object_proxy = bus_->GetObjectProxy( |
| test_service.service_name(), ObjectPath("/org/chromium/TestObject")); |
| |
| ASSERT_TRUE(test_service.StartService()); |
| test_service.WaitUntilServiceIsStarted(); |
| ASSERT_TRUE(test_service.has_ownership()); |
| |
| // Since the service is already running, the callback should be invoked |
| // immediately (but asynchronously, rather than the callback being invoked |
| // directly within WaitForServiceToBeAvailable()). |
| int num_calls = 0; |
| bool service_is_available = false; |
| object_proxy->WaitForServiceToBeAvailable( |
| base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls)); |
| EXPECT_EQ(0, num_calls); |
| |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, num_calls); |
| EXPECT_TRUE(service_is_available); |
| } |
| |
| TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableMultipleCallbacks) { |
| TestService::Options options; |
| TestService test_service(options); |
| ObjectProxy* object_proxy = bus_->GetObjectProxy( |
| test_service.service_name(), ObjectPath("/org/chromium/TestObject")); |
| |
| // Register two callbacks. |
| int num_calls_1 = 0, num_calls_2 = 0; |
| bool service_is_available_1 = false, service_is_available_2 = false; |
| object_proxy->WaitForServiceToBeAvailable( |
| base::Bind(&OnServiceIsAvailable, &service_is_available_1, &num_calls_1)); |
| object_proxy->WaitForServiceToBeAvailable( |
| base::Bind(&OnServiceIsAvailable, &service_is_available_2, &num_calls_2)); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(0, num_calls_1); |
| EXPECT_EQ(0, num_calls_2); |
| |
| // Start the service and confirm that both callbacks are invoked. |
| ASSERT_TRUE(test_service.StartService()); |
| test_service.WaitUntilServiceIsStarted(); |
| ASSERT_TRUE(test_service.has_ownership()); |
| num_calls_1 = 0; |
| num_calls_2 = 0; |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, num_calls_1); |
| EXPECT_EQ(1, num_calls_2); |
| EXPECT_TRUE(service_is_available_1); |
| EXPECT_TRUE(service_is_available_2); |
| } |
| |
| } // namespace |
| } // namespace dbus |