| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/native_messaging/native_messaging_reader.h" | 5 #include "remoting/host/native_messaging/native_messaging_reader.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <cstdint> |
| 8 | |
| 9 #include <memory> | 8 #include <memory> |
| 10 #include <utility> | 9 #include <utility> |
| 11 | 10 |
| 12 #include "base/bind.h" | 11 #include "base/bind.h" |
| 13 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
| 14 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
| 15 #include "base/values.h" | 14 #include "base/values.h" |
| 16 #include "remoting/host/setup/test_util.h" | 15 #include "remoting/host/setup/test_util.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 17 |
| 19 namespace remoting { | 18 namespace remoting { |
| 20 | 19 |
| 21 class NativeMessagingReaderTest : public testing::Test { | 20 class NativeMessagingReaderTest : public testing::Test { |
| 22 public: | 21 public: |
| 23 NativeMessagingReaderTest(); | 22 NativeMessagingReaderTest(); |
| 24 ~NativeMessagingReaderTest() override; | 23 ~NativeMessagingReaderTest() override; |
| 25 | 24 |
| 26 void SetUp() override; | 25 void SetUp() override; |
| 27 | 26 |
| 28 // Starts the reader and runs the MessageLoop to completion. | 27 // Runs the MessageLoop to completion. |
| 29 void Run(); | 28 void RunAndWaitForOperationComplete(); |
| 30 | 29 |
| 31 // MessageCallback passed to the Reader. Stores |message| so it can be | 30 // MessageCallback passed to the Reader. Stores |message| so it can be |
| 32 // verified by tests. | 31 // verified by tests. |
| 33 void OnMessage(std::unique_ptr<base::Value> message); | 32 void OnMessage(std::unique_ptr<base::Value> message); |
| 34 | 33 |
| 34 // Closure passed to the Reader, called back when the reader detects an error. |
| 35 void OnError(); |
| 36 |
| 35 // Writes a message (header+body) to the write-end of the pipe. | 37 // Writes a message (header+body) to the write-end of the pipe. |
| 36 void WriteMessage(const std::string& message); | 38 void WriteMessage(const std::string& message); |
| 37 | 39 |
| 38 // Writes some data to the write-end of the pipe. | 40 // Writes some data to the write-end of the pipe. |
| 39 void WriteData(const char* data, int length); | 41 void WriteData(const char* data, int length); |
| 40 | 42 |
| 41 protected: | 43 protected: |
| 42 std::unique_ptr<NativeMessagingReader> reader_; | 44 std::unique_ptr<NativeMessagingReader> reader_; |
| 43 base::File read_file_; | 45 base::File read_file_; |
| 44 base::File write_file_; | 46 base::File write_file_; |
| 47 bool on_error_signaled_ = false; |
| 45 std::unique_ptr<base::Value> message_; | 48 std::unique_ptr<base::Value> message_; |
| 46 | 49 |
| 47 private: | 50 private: |
| 48 // MessageLoop declared here, since the NativeMessageReader ctor requires a | 51 // MessageLoop declared here, since the NativeMessageReader ctor requires a |
| 49 // MessageLoop to have been created. | 52 // MessageLoop to have been created. |
| 50 base::MessageLoopForIO message_loop_; | 53 base::MessageLoopForIO message_loop_; |
| 51 base::RunLoop run_loop_; | 54 std::unique_ptr<base::RunLoop> run_loop_; |
| 52 }; | 55 }; |
| 53 | 56 |
| 54 NativeMessagingReaderTest::NativeMessagingReaderTest() {} | 57 NativeMessagingReaderTest::NativeMessagingReaderTest() {} |
| 58 |
| 55 NativeMessagingReaderTest::~NativeMessagingReaderTest() {} | 59 NativeMessagingReaderTest::~NativeMessagingReaderTest() {} |
| 56 | 60 |
| 57 void NativeMessagingReaderTest::SetUp() { | 61 void NativeMessagingReaderTest::SetUp() { |
| 58 ASSERT_TRUE(MakePipe(&read_file_, &write_file_)); | 62 ASSERT_TRUE(MakePipe(&read_file_, &write_file_)); |
| 59 reader_.reset(new NativeMessagingReader(std::move(read_file_))); | 63 reader_.reset(new NativeMessagingReader(std::move(read_file_))); |
| 60 } | 64 run_loop_.reset(new base::RunLoop()); |
| 61 | |
| 62 void NativeMessagingReaderTest::Run() { | |
| 63 // Close the write-end, so the reader doesn't block waiting for more data. | |
| 64 write_file_.Close(); | |
| 65 | 65 |
| 66 // base::Unretained is safe since no further tasks can run after | 66 // base::Unretained is safe since no further tasks can run after |
| 67 // RunLoop::Run() returns. | 67 // RunLoop::Run() returns. |
| 68 reader_->Start( | 68 reader_->Start( |
| 69 base::Bind(&NativeMessagingReaderTest::OnMessage, base::Unretained(this)), | 69 base::Bind(&NativeMessagingReaderTest::OnMessage, base::Unretained(this)), |
| 70 run_loop_.QuitClosure()); | 70 base::Bind(&NativeMessagingReaderTest::OnError, base::Unretained(this))); |
| 71 run_loop_.Run(); | 71 } |
| 72 |
| 73 void NativeMessagingReaderTest::RunAndWaitForOperationComplete() { |
| 74 run_loop_->Run(); |
| 75 run_loop_.reset(new base::RunLoop()); |
| 72 } | 76 } |
| 73 | 77 |
| 74 void NativeMessagingReaderTest::OnMessage( | 78 void NativeMessagingReaderTest::OnMessage( |
| 75 std::unique_ptr<base::Value> message) { | 79 std::unique_ptr<base::Value> message) { |
| 76 message_ = std::move(message); | 80 message_ = std::move(message); |
| 81 run_loop_->Quit(); |
| 82 } |
| 83 |
| 84 void NativeMessagingReaderTest::OnError() { |
| 85 on_error_signaled_ = true; |
| 86 run_loop_->Quit(); |
| 77 } | 87 } |
| 78 | 88 |
| 79 void NativeMessagingReaderTest::WriteMessage(const std::string& message) { | 89 void NativeMessagingReaderTest::WriteMessage(const std::string& message) { |
| 80 uint32_t length = message.length(); | 90 uint32_t length = message.length(); |
| 81 WriteData(reinterpret_cast<char*>(&length), 4); | 91 WriteData(reinterpret_cast<char*>(&length), 4); |
| 82 WriteData(message.data(), length); | 92 WriteData(message.data(), length); |
| 83 } | 93 } |
| 84 | 94 |
| 85 void NativeMessagingReaderTest::WriteData(const char* data, int length) { | 95 void NativeMessagingReaderTest::WriteData(const char* data, int length) { |
| 86 int written = write_file_.WriteAtCurrentPos(data, length); | 96 int written = write_file_.WriteAtCurrentPos(data, length); |
| 87 ASSERT_EQ(length, written); | 97 ASSERT_EQ(length, written); |
| 88 } | 98 } |
| 89 | 99 |
| 90 TEST_F(NativeMessagingReaderTest, GoodMessage) { | 100 TEST_F(NativeMessagingReaderTest, ReaderDestroyedByClosingPipe) { |
| 91 WriteMessage("{\"foo\": 42}"); | 101 WriteMessage("{\"foo\": 42}"); |
| 92 Run(); | 102 RunAndWaitForOperationComplete(); |
| 93 EXPECT_TRUE(message_); | 103 ASSERT_FALSE(on_error_signaled_); |
| 104 |
| 105 // Close the write end of the pipe while the reader is waiting for more data. |
| 106 write_file_.Close(); |
| 107 RunAndWaitForOperationComplete(); |
| 108 ASSERT_TRUE(on_error_signaled_); |
| 109 } |
| 110 |
| 111 #if defined(OS_WIN) |
| 112 // This scenario is only a problem on Windows as closing the write pipe there |
| 113 // does not trigger the parent process to close the read pipe. |
| 114 TEST_F(NativeMessagingReaderTest, ReaderDestroyedByOwner) { |
| 115 WriteMessage("{\"foo\": 42}"); |
| 116 RunAndWaitForOperationComplete(); |
| 117 ASSERT_FALSE(on_error_signaled_); |
| 118 |
| 119 // Destroy the reader while it is waiting for more data. |
| 120 reader_.reset(); |
| 121 ASSERT_FALSE(on_error_signaled_); |
| 122 } |
| 123 #endif // defined(OS_WIN) |
| 124 |
| 125 TEST_F(NativeMessagingReaderTest, SingleGoodMessage) { |
| 126 WriteMessage("{\"foo\": 42}"); |
| 127 RunAndWaitForOperationComplete(); |
| 128 ASSERT_FALSE(on_error_signaled_); |
| 129 ASSERT_TRUE(message_); |
| 94 base::DictionaryValue* message_dict; | 130 base::DictionaryValue* message_dict; |
| 95 EXPECT_TRUE(message_->GetAsDictionary(&message_dict)); | 131 ASSERT_TRUE(message_->GetAsDictionary(&message_dict)); |
| 96 int result; | 132 int result; |
| 97 EXPECT_TRUE(message_dict->GetInteger("foo", &result)); | 133 ASSERT_TRUE(message_dict->GetInteger("foo", &result)); |
| 98 EXPECT_EQ(42, result); | 134 ASSERT_EQ(42, result); |
| 135 } |
| 136 |
| 137 TEST_F(NativeMessagingReaderTest, MultipleGoodMessages) { |
| 138 WriteMessage("{}"); |
| 139 RunAndWaitForOperationComplete(); |
| 140 ASSERT_FALSE(on_error_signaled_); |
| 141 ASSERT_TRUE(message_); |
| 142 base::DictionaryValue* message_dict; |
| 143 ASSERT_TRUE(message_->GetAsDictionary(&message_dict)); |
| 144 |
| 145 int result; |
| 146 WriteMessage("{\"foo\": 42}"); |
| 147 RunAndWaitForOperationComplete(); |
| 148 ASSERT_FALSE(on_error_signaled_); |
| 149 ASSERT_TRUE(message_); |
| 150 ASSERT_TRUE(message_->GetAsDictionary(&message_dict)); |
| 151 ASSERT_TRUE(message_dict->GetInteger("foo", &result)); |
| 152 ASSERT_EQ(42, result); |
| 153 |
| 154 WriteMessage("{\"bar\": 43}"); |
| 155 RunAndWaitForOperationComplete(); |
| 156 ASSERT_FALSE(on_error_signaled_); |
| 157 ASSERT_TRUE(message_); |
| 158 ASSERT_TRUE(message_->GetAsDictionary(&message_dict)); |
| 159 ASSERT_TRUE(message_dict->GetInteger("bar", &result)); |
| 160 ASSERT_EQ(43, result); |
| 161 |
| 162 WriteMessage("{\"baz\": 44}"); |
| 163 RunAndWaitForOperationComplete(); |
| 164 ASSERT_FALSE(on_error_signaled_); |
| 165 ASSERT_TRUE(message_); |
| 166 ASSERT_TRUE(message_->GetAsDictionary(&message_dict)); |
| 167 ASSERT_TRUE(message_dict->GetInteger("baz", &result)); |
| 168 ASSERT_EQ(44, result); |
| 99 } | 169 } |
| 100 | 170 |
| 101 TEST_F(NativeMessagingReaderTest, InvalidLength) { | 171 TEST_F(NativeMessagingReaderTest, InvalidLength) { |
| 102 uint32_t length = 0xffffffff; | 172 uint32_t length = 0xffffffff; |
| 103 WriteData(reinterpret_cast<char*>(&length), 4); | 173 WriteData(reinterpret_cast<char*>(&length), 4); |
| 104 Run(); | 174 RunAndWaitForOperationComplete(); |
| 105 EXPECT_FALSE(message_); | 175 ASSERT_FALSE(message_); |
| 176 ASSERT_TRUE(on_error_signaled_); |
| 106 } | 177 } |
| 107 | 178 |
| 108 TEST_F(NativeMessagingReaderTest, EmptyFile) { | 179 TEST_F(NativeMessagingReaderTest, EmptyFile) { |
| 109 Run(); | 180 write_file_.Close(); |
| 110 EXPECT_FALSE(message_); | 181 RunAndWaitForOperationComplete(); |
| 182 ASSERT_FALSE(message_); |
| 183 ASSERT_TRUE(on_error_signaled_); |
| 111 } | 184 } |
| 112 | 185 |
| 113 TEST_F(NativeMessagingReaderTest, ShortHeader) { | 186 TEST_F(NativeMessagingReaderTest, ShortHeader) { |
| 114 // Write only 3 bytes - the message length header is supposed to be 4 bytes. | 187 // Write only 3 bytes - the message length header is supposed to be 4 bytes. |
| 115 WriteData("xxx", 3); | 188 WriteData("xxx", 3); |
| 116 Run(); | 189 write_file_.Close(); |
| 117 EXPECT_FALSE(message_); | 190 RunAndWaitForOperationComplete(); |
| 191 ASSERT_FALSE(message_); |
| 192 ASSERT_TRUE(on_error_signaled_); |
| 118 } | 193 } |
| 119 | 194 |
| 120 TEST_F(NativeMessagingReaderTest, EmptyBody) { | 195 TEST_F(NativeMessagingReaderTest, EmptyBody) { |
| 121 uint32_t length = 1; | 196 uint32_t length = 1; |
| 122 WriteData(reinterpret_cast<char*>(&length), 4); | 197 WriteData(reinterpret_cast<char*>(&length), 4); |
| 123 Run(); | 198 write_file_.Close(); |
| 124 EXPECT_FALSE(message_); | 199 RunAndWaitForOperationComplete(); |
| 200 ASSERT_FALSE(message_); |
| 201 ASSERT_TRUE(on_error_signaled_); |
| 125 } | 202 } |
| 126 | 203 |
| 127 TEST_F(NativeMessagingReaderTest, ShortBody) { | 204 TEST_F(NativeMessagingReaderTest, ShortBody) { |
| 128 uint32_t length = 2; | 205 uint32_t length = 2; |
| 129 WriteData(reinterpret_cast<char*>(&length), 4); | 206 WriteData(reinterpret_cast<char*>(&length), 4); |
| 130 | 207 |
| 131 // Only write 1 byte, where the header indicates there should be 2 bytes. | 208 // Only write 1 byte, where the header indicates there should be 2 bytes. |
| 132 WriteData("x", 1); | 209 WriteData("x", 1); |
| 133 Run(); | 210 write_file_.Close(); |
| 134 EXPECT_FALSE(message_); | 211 RunAndWaitForOperationComplete(); |
| 212 ASSERT_FALSE(message_); |
| 213 ASSERT_TRUE(on_error_signaled_); |
| 135 } | 214 } |
| 136 | 215 |
| 137 TEST_F(NativeMessagingReaderTest, InvalidJSON) { | 216 TEST_F(NativeMessagingReaderTest, InvalidJSON) { |
| 138 std::string text = "{"; | 217 std::string text = "{"; |
| 139 WriteMessage(text); | 218 WriteMessage(text); |
| 140 Run(); | 219 write_file_.Close(); |
| 141 EXPECT_FALSE(message_); | 220 RunAndWaitForOperationComplete(); |
| 142 } | 221 ASSERT_FALSE(message_); |
| 143 | 222 ASSERT_TRUE(on_error_signaled_); |
| 144 TEST_F(NativeMessagingReaderTest, SecondMessage) { | |
| 145 WriteMessage("{}"); | |
| 146 WriteMessage("{\"foo\": 42}"); | |
| 147 Run(); | |
| 148 EXPECT_TRUE(message_); | |
| 149 base::DictionaryValue* message_dict; | |
| 150 EXPECT_TRUE(message_->GetAsDictionary(&message_dict)); | |
| 151 int result; | |
| 152 EXPECT_TRUE(message_dict->GetInteger("foo", &result)); | |
| 153 EXPECT_EQ(42, result); | |
| 154 } | 223 } |
| 155 | 224 |
| 156 } // namespace remoting | 225 } // namespace remoting |
| OLD | NEW |