1// Copyright (c) 2012 The Chromium 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 "base/memory/ref_counted.h"
6#include "base/memory/scoped_ptr.h"
7#include "dbus/bus.h"
8#include "dbus/message.h"
9#include "dbus/object_path.h"
10#include "dbus/object_proxy.h"
11#include "dbus/test_service.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace dbus {
15
16// The end-to-end test exercises the synchronous APIs in ObjectProxy and
17// ExportedObject. The test will launch a thread for the service side
18// operations (i.e. ExportedObject side).
19class EndToEndSyncTest : public testing::Test {
20 public:
21  EndToEndSyncTest() {
22  }
23
24  virtual void SetUp() {
25    // Start the test service;
26    TestService::Options options;
27    test_service_.reset(new TestService(options));
28    ASSERT_TRUE(test_service_->StartService());
29    ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
30    ASSERT_FALSE(test_service_->HasDBusThread());
31
32    // Create the client.
33    Bus::Options client_bus_options;
34    client_bus_options.bus_type = Bus::SESSION;
35    client_bus_options.connection_type = Bus::PRIVATE;
36    client_bus_ = new Bus(client_bus_options);
37    object_proxy_ = client_bus_->GetObjectProxy(
38        "org.chromium.TestService",
39        ObjectPath("/org/chromium/TestObject"));
40    ASSERT_FALSE(client_bus_->HasDBusThread());
41  }
42
43  virtual void TearDown() {
44    test_service_->ShutdownAndBlock();
45    test_service_->Stop();
46    client_bus_->ShutdownAndBlock();
47  }
48
49 protected:
50  scoped_ptr<TestService> test_service_;
51  scoped_refptr<Bus> client_bus_;
52  ObjectProxy* object_proxy_;
53};
54
55TEST_F(EndToEndSyncTest, Echo) {
56  const std::string kHello = "hello";
57
58  // Create the method call.
59  MethodCall method_call("org.chromium.TestInterface", "Echo");
60  MessageWriter writer(&method_call);
61  writer.AppendString(kHello);
62
63  // Call the method.
64  const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
65  scoped_ptr<Response> response(
66      object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
67  ASSERT_TRUE(response.get());
68
69  // Check the response. kHello should be echoed back.
70  MessageReader reader(response.get());
71  std::string returned_message;
72  ASSERT_TRUE(reader.PopString(&returned_message));
73  EXPECT_EQ(kHello, returned_message);
74}
75
76TEST_F(EndToEndSyncTest, Timeout) {
77  const std::string kHello = "hello";
78
79  // Create the method call.
80  MethodCall method_call("org.chromium.TestInterface", "DelayedEcho");
81  MessageWriter writer(&method_call);
82  writer.AppendString(kHello);
83
84  // Call the method with timeout of 0ms.
85  const int timeout_ms = 0;
86  scoped_ptr<Response> response(
87      object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
88  // Should fail because of timeout.
89  ASSERT_FALSE(response.get());
90}
91
92TEST_F(EndToEndSyncTest, NonexistentMethod) {
93  MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
94
95  const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
96  scoped_ptr<Response> response(
97      object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
98  ASSERT_FALSE(response.get());
99}
100
101TEST_F(EndToEndSyncTest, BrokenMethod) {
102  MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
103
104  const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
105  scoped_ptr<Response> response(
106      object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
107  ASSERT_FALSE(response.get());
108}
109
110TEST_F(EndToEndSyncTest, InvalidObjectPath) {
111  // Trailing '/' is only allowed for the root path.
112  const ObjectPath invalid_object_path("/org/chromium/TestObject/");
113
114  // Replace object proxy with new one.
115  object_proxy_ = client_bus_->GetObjectProxy("org.chromium.TestService",
116                                              invalid_object_path);
117
118  MethodCall method_call("org.chromium.TestInterface", "Echo");
119
120  const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
121  scoped_ptr<Response> response(
122      object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
123  ASSERT_FALSE(response.get());
124}
125
126TEST_F(EndToEndSyncTest, InvalidServiceName) {
127  // Bus name cannot contain '/'.
128  const std::string invalid_service_name = ":1/2";
129
130  // Replace object proxy with new one.
131  object_proxy_ = client_bus_->GetObjectProxy(
132      invalid_service_name, ObjectPath("org.chromium.TestObject"));
133
134  MethodCall method_call("org.chromium.TestInterface", "Echo");
135
136  const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
137  scoped_ptr<Response> response(
138      object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
139  ASSERT_FALSE(response.get());
140}
141
142}  // namespace dbus
143