1 // Copyright 2018 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 "chromeos/services/secure_channel/public/cpp/client/client_channel_impl.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/callback_helpers.h"
10 #include "base/memory/scoped_refptr.h"
11 #include "base/no_destructor.h"
12 #include "base/optional.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/test/null_task_runner.h"
16 #include "base/test/task_environment.h"
17 #include "base/test/test_simple_task_runner.h"
18 #include "chromeos/components/multidevice/remote_device_test_util.h"
19 #include "chromeos/services/secure_channel/fake_channel.h"
20 #include "chromeos/services/secure_channel/fake_secure_channel.h"
21 #include "chromeos/services/secure_channel/public/cpp/client/client_channel_impl.h"
22 #include "chromeos/services/secure_channel/public/cpp/client/connection_attempt.h"
23 #include "chromeos/services/secure_channel/public/cpp/client/connection_attempt_impl.h"
24 #include "chromeos/services/secure_channel/public/cpp/client/fake_client_channel_observer.h"
25 #include "chromeos/services/secure_channel/public/cpp/client/fake_connection_attempt.h"
26 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
27 #include "chromeos/services/secure_channel/secure_channel_impl.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29
30 namespace chromeos {
31
32 namespace secure_channel {
33
34 class SecureChannelClientChannelImplTest : public testing::Test {
35 protected:
36 SecureChannelClientChannelImplTest() = default;
37
38 // testing::Test:
SetUp()39 void SetUp() override {
40 fake_channel_ = std::make_unique<FakeChannel>();
41
42 client_channel_ = ClientChannelImpl::Factory::Create(
43 fake_channel_->GenerateRemote(),
44 message_receiver_remote_.BindNewPipeAndPassReceiver());
45
46 fake_observer_ = std::make_unique<FakeClientChannelObserver>();
47 client_channel_->AddObserver(fake_observer_.get());
48 }
49
TearDown()50 void TearDown() override {
51 client_channel_->RemoveObserver(fake_observer_.get());
52 }
53
CallGetConnectionMetadata()54 mojom::ConnectionMetadataPtr CallGetConnectionMetadata() {
55 EXPECT_FALSE(connection_metadata_);
56
57 base::RunLoop run_loop;
58 EXPECT_TRUE(client_channel_->GetConnectionMetadata(base::BindOnce(
59 &SecureChannelClientChannelImplTest::OnGetConnectionMetadata,
60 base::Unretained(this), run_loop.QuitClosure())));
61 run_loop.Run();
62
63 return std::move(connection_metadata_);
64 }
65
CallSendMessage(const std::string & message)66 int CallSendMessage(const std::string& message) {
67 static int message_counter = 0;
68 int counter_for_this_message = message_counter++;
69 bool success = client_channel_->SendMessage(
70 message,
71 base::BindOnce(&SecureChannelClientChannelImplTest::OnMessageSent,
72 base::Unretained(this), counter_for_this_message));
73 EXPECT_TRUE(success);
74 SendPendingMojoMessages();
75 return counter_for_this_message;
76 }
77
CallSendMessageCallback(base::OnceClosure callback)78 void CallSendMessageCallback(base::OnceClosure callback) {
79 base::RunLoop run_loop;
80 message_sent_callback_ = run_loop.QuitClosure();
81 std::move(callback).Run();
82 run_loop.Run();
83 }
84
VerifyChannelDisconnected()85 void VerifyChannelDisconnected() {
86 EXPECT_TRUE(client_channel_->is_disconnected());
87 EXPECT_TRUE(fake_observer_->is_disconnected());
88
89 // Ensure that these methods do not work once the ClientChannel is
90 // disconnected.
91 EXPECT_FALSE(client_channel_->GetConnectionMetadata(base::NullCallback()));
92 EXPECT_FALSE(client_channel_->SendMessage("message", base::NullCallback()));
93 }
94
SendPendingMojoMessages()95 void SendPendingMojoMessages() {
96 static_cast<ClientChannelImpl*>(client_channel_.get())->FlushForTesting();
97 }
98
99 base::test::TaskEnvironment task_environment_;
100
101 std::unique_ptr<FakeChannel> fake_channel_;
102 mojo::Remote<mojom::MessageReceiver> message_receiver_remote_;
103 std::unique_ptr<FakeClientChannelObserver> fake_observer_;
104
105 mojom::ConnectionMetadataPtr connection_metadata_;
106 base::OnceClosure message_sent_callback_;
107 std::set<int> message_counters_received_;
108
109 std::unique_ptr<ClientChannel> client_channel_;
110
111 private:
OnGetConnectionMetadata(base::OnceClosure callback,mojom::ConnectionMetadataPtr connection_metadata)112 void OnGetConnectionMetadata(
113 base::OnceClosure callback,
114 mojom::ConnectionMetadataPtr connection_metadata) {
115 connection_metadata_ = std::move(connection_metadata);
116 std::move(callback).Run();
117 }
118
OnMessageSent(int message_counter)119 void OnMessageSent(int message_counter) {
120 message_counters_received_.insert(message_counter);
121 std::move(message_sent_callback_).Run();
122 }
123
124 DISALLOW_COPY_AND_ASSIGN(SecureChannelClientChannelImplTest);
125 };
126
TEST_F(SecureChannelClientChannelImplTest,TestGetConnectionMetadata)127 TEST_F(SecureChannelClientChannelImplTest, TestGetConnectionMetadata) {
128 std::vector<mojom::ConnectionCreationDetail> creation_details{
129 mojom::ConnectionCreationDetail::
130 REMOTE_DEVICE_USED_BACKGROUND_BLE_ADVERTISING};
131
132 mojom::ConnectionMetadataPtr metadata = mojom::ConnectionMetadata::New(
133 creation_details,
134 mojom::BluetoothConnectionMetadata::New(-24 /* current_rssi */),
135 "channel_binding_data");
136 fake_channel_->set_connection_metadata_for_next_call(std::move(metadata));
137
138 metadata = CallGetConnectionMetadata();
139 EXPECT_EQ(creation_details, metadata->creation_details);
140 EXPECT_EQ(-24, metadata->bluetooth_connection_metadata->current_rssi);
141 }
142
TEST_F(SecureChannelClientChannelImplTest,TestSendMessage)143 TEST_F(SecureChannelClientChannelImplTest, TestSendMessage) {
144 int message_1_counter = CallSendMessage("payload1");
145 int message_2_counter = CallSendMessage("payload2");
146
147 std::vector<std::pair<std::string, mojom::Channel::SendMessageCallback>>&
148 sent_messages = fake_channel_->sent_messages();
149
150 EXPECT_EQ(2u, sent_messages.size());
151 EXPECT_EQ("payload1", sent_messages[0].first);
152 EXPECT_EQ("payload2", sent_messages[1].first);
153
154 CallSendMessageCallback(std::move(sent_messages[0].second));
155 CallSendMessageCallback(std::move(sent_messages[1].second));
156
157 EXPECT_TRUE(base::Contains(message_counters_received_, message_1_counter));
158 EXPECT_TRUE(base::Contains(message_counters_received_, message_2_counter));
159 }
160
TEST_F(SecureChannelClientChannelImplTest,TestReceiveMessage)161 TEST_F(SecureChannelClientChannelImplTest, TestReceiveMessage) {
162 message_receiver_remote_->OnMessageReceived("payload");
163 message_receiver_remote_.FlushForTesting();
164
165 EXPECT_EQ(1u, fake_observer_->received_messages().size());
166 EXPECT_EQ("payload", fake_observer_->received_messages()[0]);
167 }
168
TEST_F(SecureChannelClientChannelImplTest,TestDisconnectRemotely)169 TEST_F(SecureChannelClientChannelImplTest, TestDisconnectRemotely) {
170 fake_channel_->DisconnectGeneratedRemote();
171
172 SendPendingMojoMessages();
173
174 VerifyChannelDisconnected();
175 }
176
177 } // namespace secure_channel
178
179 } // namespace chromeos
180