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// This test is relatively complicated. Here's the summary of what it does:
6//
7// - Set up mock D-Bus related objects to mock out D-Bus calls.
8// - Set up a mock proxy resolver to mock out the proxy resolution.
9// - Create ProxyResolutionServiceProvider by injecting the mocks
10// - Start the service provider.
11// - Request ProxyResolutionServiceProvider to resolve proxy for kSourceURL.
12// - ProxyResolutionServiceProvider will return the result as a signal.
13// - Confirm that we receive the signal and check the contents of the signal.
14
15#include "chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h"
16
17#include "base/bind.h"
18#include "chrome/browser/chromeos/dbus/service_provider_test_helper.h"
19#include "dbus/message.h"
20#include "dbus/mock_exported_object.h"
21#include "third_party/cros_system_api/dbus/service_constants.h"
22
23using ::testing::_;
24
25namespace chromeos {
26
27// We want to know about the proxy info for the URL.
28const char kSourceURL[] = "http://www.gmail.com/";
29
30// ProxyResolutionServiceProvider will return the proxy info as a D-Bus
31// signal, to the following signal interface and the signal name.
32const char kReturnSignalInterface[] = "org.chromium.TestInterface";
33const char kReturnSignalName[] = "TestSignal";
34
35// The returned proxy info.
36const char kReturnProxyInfo[] = "PROXY cache.example.com:12345";
37
38// The error message is empty if proxy resolution is successful.
39const char kReturnEmptyErrorMessage[] = "";
40
41// Mock for ProxyResolverInterface. We'll inject this to
42// ProxyResolutionServiceProvider to mock out the proxy resolution.
43class MockProxyResolver : public ProxyResolverInterface {
44 public:
45  MOCK_METHOD4(ResolveProxy,
46               void(const std::string& source_url,
47                    const std::string& signal_interface,
48                    const std::string& signal_name,
49                    scoped_refptr<dbus::ExportedObject> exported_object));
50};
51
52class ProxyResolutionServiceProviderTest : public testing::Test {
53 public:
54  ProxyResolutionServiceProviderTest()
55      : signal_received_successfully_(false) {
56  }
57
58  virtual void SetUp() OVERRIDE {
59    // Create a mock proxy resolver. Will be owned by
60    // |proxy_resolution_service|.
61    MockProxyResolver* mock_resolver = new MockProxyResolver;
62    // |mock_resolver_|'s ResolveProxy() will use MockResolveProxy().
63    EXPECT_CALL(*mock_resolver,
64                ResolveProxy(kSourceURL, kReturnSignalInterface,
65                             kReturnSignalName, _))
66        .WillOnce(Invoke(
67            this,
68            &ProxyResolutionServiceProviderTest::MockResolveProxy));
69
70    // Create the proxy resolution service with the mock bus and the mock
71    // resolver injected.
72    service_provider_.reset(
73        ProxyResolutionServiceProvider::CreateForTesting(mock_resolver));
74
75    test_helper_.SetUp(kResolveNetworkProxy, service_provider_.get());
76
77    // Connect to the signal that will be sent to kReturnSignalInterface and
78    // kReturnSignalName. ResolveNetworkProxy() will send the result as a
79    // signal. OnSignalReceived() will be called upon the delivery.
80    test_helper_.SetUpReturnSignal(
81        kReturnSignalInterface,
82        kReturnSignalName,
83        base::Bind(&ProxyResolutionServiceProviderTest::OnSignalReceived,
84                   base::Unretained(this)),
85        base::Bind(&ProxyResolutionServiceProviderTest::OnConnectedToSignal,
86                   base::Unretained(this)));
87  }
88
89  virtual void TearDown() OVERRIDE {
90    test_helper_.TearDown();
91    service_provider_.reset();
92  }
93
94 protected:
95  // Called when a signal is received.
96  void OnSignalReceived(dbus::Signal* signal) {
97    ASSERT_EQ(kReturnSignalInterface, signal->GetInterface());
98    ASSERT_EQ(kReturnSignalName, signal->GetMember());
99
100    std::string source_url;
101    std::string proxy_info;
102    std::string error_message;
103
104    // The signal should contain three strings.
105    dbus::MessageReader reader(signal);
106    ASSERT_TRUE(reader.PopString(&source_url));
107    ASSERT_TRUE(reader.PopString(&proxy_info));
108    ASSERT_TRUE(reader.PopString(&error_message));
109
110    // Check the signal contents.
111    EXPECT_EQ(kSourceURL, source_url);
112    EXPECT_EQ(kReturnProxyInfo, proxy_info);
113    EXPECT_EQ(kReturnEmptyErrorMessage, error_message);
114
115    // Mark that the signal is received successfully.
116    signal_received_successfully_ = true;
117  }
118
119  // Called when connected to a signal.
120  void OnConnectedToSignal(const std::string& signal_interface,
121                           const std::string& signal_name,
122                           bool success){
123    ASSERT_EQ(kReturnSignalInterface, signal_interface);
124    ASSERT_EQ(kReturnSignalName, signal_name);
125
126    ASSERT_TRUE(success);
127  }
128
129  // Behaves as |mock_resolver_|'s ResolveProxy().
130  void MockResolveProxy(const std::string& source_url,
131                        const std::string& signal_interface,
132                        const std::string& signal_name,
133                        scoped_refptr<dbus::ExportedObject> exported_object) {
134    if (source_url == kSourceURL) {
135      dbus::Signal signal(signal_interface,
136                          signal_name);
137      dbus::MessageWriter writer(&signal);
138      writer.AppendString(kSourceURL);
139      writer.AppendString(kReturnProxyInfo);
140      writer.AppendString(kReturnEmptyErrorMessage);
141      // Send the signal back to the requested signal interface and the
142      // signal name.
143      exported_object->SendSignal(&signal);
144      return;
145    }
146
147    LOG(ERROR) << "Unexpected source URL: " << source_url;
148  }
149
150  bool signal_received_successfully_;
151  ServiceProviderTestHelper test_helper_;
152  scoped_ptr<CrosDBusService::ServiceProviderInterface> service_provider_;
153};
154
155TEST_F(ProxyResolutionServiceProviderTest, ResolveProxy) {
156  // The signal is not yet received.
157  ASSERT_FALSE(signal_received_successfully_);
158
159  // Create a method call to resolve proxy config for kSourceURL.
160  dbus::MethodCall method_call(kLibCrosServiceInterface, kResolveNetworkProxy);
161  dbus::MessageWriter writer(&method_call);
162  writer.AppendString(kSourceURL);
163  writer.AppendString(kReturnSignalInterface);
164  writer.AppendString(kReturnSignalName);
165
166  // Call the ResolveNetworkProxy method.
167  scoped_ptr<dbus::Response> response(test_helper_.CallMethod(&method_call));
168
169  // An empty response should be returned.
170  ASSERT_TRUE(response.get());
171  dbus::MessageReader reader(response.get());
172  ASSERT_FALSE(reader.HasMoreData());
173
174  // Confirm that the signal is received successfully.
175  // The contents of the signal are checked in OnSignalReceived().
176  ASSERT_TRUE(signal_received_successfully_);
177}
178
179}  // namespace chromeos
180