#include "dbus/object_proxy.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/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(std::move(bus_options));
}
void TearDown() override { bus_->ShutdownAndBlock(); }
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::MainThreadType::IO};
scoped_refptr<Bus> bus_;
};
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)++;
}
void OnOwnershipRequestDone(bool success) {
ASSERT_TRUE(success);
}
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"));
int num_calls = 0;
bool service_is_available = false;
object_proxy->WaitForServiceToBeAvailable(
base::BindOnce(&OnServiceIsAvailable, &service_is_available, &num_calls));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, num_calls);
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);
test_service.ReleaseOwnership(base::BindOnce(&OnOwnershipReleased));
num_calls = 0;
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, num_calls);
test_service.RequestOwnership(base::BindOnce(&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());
int num_calls = 0;
bool service_is_available = false;
object_proxy->WaitForServiceToBeAvailable(
base::BindOnce(&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"));
int num_calls_1 = 0, num_calls_2 = 0;
bool service_is_available_1 = false, service_is_available_2 = false;
object_proxy->WaitForServiceToBeAvailable(base::BindOnce(
&OnServiceIsAvailable, &service_is_available_1, &num_calls_1));
object_proxy->WaitForServiceToBeAvailable(base::BindOnce(
&OnServiceIsAvailable, &service_is_available_2, &num_calls_2));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, num_calls_1);
EXPECT_EQ(0, num_calls_2);
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);
}
}
}