blob: 7d45a52d57c2dc0e504de626d18921f6592e715e [file] [log] [blame]
Andreea Costinase45d54b2020-03-10 09:21:14 +01001// Copyright 2020 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 "system-proxy/proxy_connect_job.h"
6
7#include <netinet/in.h>
8#include <sys/socket.h>
9#include <sys/types.h>
10
11#include <gmock/gmock.h>
12#include <gtest/gtest.h>
13#include <utility>
14
Andreea Costinase45d54b2020-03-10 09:21:14 +010015#include <base/bind.h>
16#include <base/bind_helpers.h>
17#include <base/callback_helpers.h>
18#include <base/files/file_util.h>
19#include <base/files/scoped_file.h>
20#include <brillo/message_loops/base_message_loop.h>
Garrick Evanscd8c2972020-04-14 14:35:52 +090021#include <chromeos/patchpanel/socket.h>
22#include <chromeos/patchpanel/socket_forwarder.h>
Andreea Costinase45d54b2020-03-10 09:21:14 +010023
24#include "bindings/worker_common.pb.h"
25#include "system-proxy/protobuf_util.h"
26
27namespace {
28constexpr char kProxyServerUrl[] = "172.0.0.1:8888";
29} // namespace
30
31namespace system_proxy {
32
33using ::testing::_;
34using ::testing::Return;
35
36class ProxyConnectJobTest : public ::testing::Test {
37 public:
38 ProxyConnectJobTest() = default;
39 ProxyConnectJobTest(const ProxyConnectJobTest&) = delete;
40 ProxyConnectJobTest& operator=(const ProxyConnectJobTest&) = delete;
41 ~ProxyConnectJobTest() = default;
42
43 void SetUp() override {
44 int fds[2];
45 ASSERT_NE(-1,
46 socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
47 0 /* protocol */, fds));
48 cros_client_socket_ =
49 std::make_unique<arc_networkd::Socket>(base::ScopedFD(fds[1]));
50
51 connect_job_ = std::make_unique<ProxyConnectJob>(
52 std::make_unique<arc_networkd::Socket>(base::ScopedFD(fds[0])), "",
53 base::BindOnce(&ProxyConnectJobTest::ResolveProxy,
54 base::Unretained(this)),
55 base::BindOnce(&ProxyConnectJobTest::OnConnectionSetupFinished,
56 base::Unretained(this)));
57 connect_job_->Start();
58 }
59
60 protected:
61 void ResolveProxy(
62 const std::string& target_url,
63 base::OnceCallback<void(const std::list<std::string>&)> callback) {
64 std::move(callback).Run({kProxyServerUrl});
65 }
66
67 void OnConnectionSetupFinished(
68 std::unique_ptr<arc_networkd::SocketForwarder> fwd,
69 ProxyConnectJob* connect_job) {
70 ASSERT_EQ(connect_job, connect_job_.get());
71 }
72
73 std::unique_ptr<ProxyConnectJob> connect_job_;
74 base::MessageLoopForIO loop_;
75 brillo::BaseMessageLoop brillo_loop_{&loop_};
76 std::unique_ptr<arc_networkd::Socket> cros_client_socket_;
77};
78
79TEST_F(ProxyConnectJobTest, SuccessfulConnection) {
80 char validConnRequest[] =
81 "CONNECT www.example.server.com:443 HTTP/1.1\r\n\r\n";
82 cros_client_socket_->SendTo(validConnRequest, std::strlen(validConnRequest));
83 brillo_loop_.RunOnce(false);
84
85 EXPECT_EQ("http://www.example.server.com:443", connect_job_->target_url_);
86 EXPECT_EQ(1, connect_job_->proxy_servers_.size());
87 EXPECT_EQ(kProxyServerUrl, connect_job_->proxy_servers_.front());
88}
89
90TEST_F(ProxyConnectJobTest, BadHttpRequestWrongMethod) {
91 char badConnRequest[] = "GET www.example.server.com:443 HTTP/1.1\r\n\r\n";
92 cros_client_socket_->SendTo(badConnRequest, std::strlen(badConnRequest));
93 brillo_loop_.RunOnce(false);
94
95 EXPECT_EQ("", connect_job_->target_url_);
96 EXPECT_EQ(0, connect_job_->proxy_servers_.size());
97 const std::string expected_http_response =
98 "HTTP/1.1 400 Bad Request - Origin: local proxy\r\n\r\n";
99 std::vector<char> buf(expected_http_response.size());
100 ASSERT_TRUE(
101 base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
102 std::string actual_response(buf.data(), buf.size());
103 EXPECT_EQ(expected_http_response, actual_response);
104}
105
106TEST_F(ProxyConnectJobTest, BadHttpRequestNoEmptyLine) {
107 // No empty line after http message.
108 char badConnRequest[] = "CONNECT www.example.server.com:443 HTTP/1.1\r\n";
109 cros_client_socket_->SendTo(badConnRequest, std::strlen(badConnRequest));
110 brillo_loop_.RunOnce(false);
111
112 EXPECT_EQ("", connect_job_->target_url_);
113 EXPECT_EQ(0, connect_job_->proxy_servers_.size());
114 const std::string expected_http_response =
115 "HTTP/1.1 400 Bad Request - Origin: local proxy\r\n\r\n";
116 std::vector<char> buf(expected_http_response.size());
117 ASSERT_TRUE(
118 base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
119 std::string actual_response(buf.data(), buf.size());
120 EXPECT_EQ(expected_http_response, actual_response);
121}
122
123} // namespace system_proxy