Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Unified Diff: remoting/host/native_messaging/native_messaging_reader_unittest.cc

Issue 2207153004: Fixing a hang in the native messaging hosts on Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding a comment describing why we need to cancel the pending read operation on Windows. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/host/native_messaging/native_messaging_reader_unittest.cc
diff --git a/remoting/host/native_messaging/native_messaging_reader_unittest.cc b/remoting/host/native_messaging/native_messaging_reader_unittest.cc
index e5e033c65a46326e44ca813c14a26c74b58d5952..733ace1d267a0e01035a72a305feeeb189fae01d 100644
--- a/remoting/host/native_messaging/native_messaging_reader_unittest.cc
+++ b/remoting/host/native_messaging/native_messaging_reader_unittest.cc
@@ -4,8 +4,7 @@
#include "remoting/host/native_messaging/native_messaging_reader.h"
-#include <stdint.h>
-
+#include <cstdint>
#include <memory>
#include <utility>
@@ -25,13 +24,16 @@ class NativeMessagingReaderTest : public testing::Test {
void SetUp() override;
- // Starts the reader and runs the MessageLoop to completion.
- void Run();
+ // Runs the MessageLoop to completion.
+ void RunAndWaitForOperationComplete();
// MessageCallback passed to the Reader. Stores |message| so it can be
// verified by tests.
void OnMessage(std::unique_ptr<base::Value> message);
+ // Closure passed to the Reader, called back when the reader detects an error.
+ void OnError();
+
// Writes a message (header+body) to the write-end of the pipe.
void WriteMessage(const std::string& message);
@@ -42,38 +44,46 @@ class NativeMessagingReaderTest : public testing::Test {
std::unique_ptr<NativeMessagingReader> reader_;
base::File read_file_;
base::File write_file_;
+ bool on_error_signaled_ = false;
std::unique_ptr<base::Value> message_;
private:
// MessageLoop declared here, since the NativeMessageReader ctor requires a
// MessageLoop to have been created.
base::MessageLoopForIO message_loop_;
- base::RunLoop run_loop_;
+ std::unique_ptr<base::RunLoop> run_loop_;
};
NativeMessagingReaderTest::NativeMessagingReaderTest() {}
+
NativeMessagingReaderTest::~NativeMessagingReaderTest() {}
void NativeMessagingReaderTest::SetUp() {
ASSERT_TRUE(MakePipe(&read_file_, &write_file_));
reader_.reset(new NativeMessagingReader(std::move(read_file_)));
-}
-
-void NativeMessagingReaderTest::Run() {
- // Close the write-end, so the reader doesn't block waiting for more data.
- write_file_.Close();
+ run_loop_.reset(new base::RunLoop());
// base::Unretained is safe since no further tasks can run after
// RunLoop::Run() returns.
reader_->Start(
base::Bind(&NativeMessagingReaderTest::OnMessage, base::Unretained(this)),
- run_loop_.QuitClosure());
- run_loop_.Run();
+ base::Bind(&NativeMessagingReaderTest::OnError, base::Unretained(this)));
+}
+
+void NativeMessagingReaderTest::RunAndWaitForOperationComplete() {
+ run_loop_->Run();
+ run_loop_.reset(new base::RunLoop());
}
void NativeMessagingReaderTest::OnMessage(
std::unique_ptr<base::Value> message) {
message_ = std::move(message);
+ run_loop_->Quit();
+}
+
+void NativeMessagingReaderTest::OnError() {
+ on_error_signaled_ = true;
+ run_loop_->Quit();
}
void NativeMessagingReaderTest::WriteMessage(const std::string& message) {
@@ -87,41 +97,108 @@ void NativeMessagingReaderTest::WriteData(const char* data, int length) {
ASSERT_EQ(length, written);
}
-TEST_F(NativeMessagingReaderTest, GoodMessage) {
+TEST_F(NativeMessagingReaderTest, ReaderDestroyedByClosingPipe) {
+ WriteMessage("{\"foo\": 42}");
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(on_error_signaled_);
+
+ // Close the write end of the pipe while the reader is waiting for more data.
+ write_file_.Close();
+ RunAndWaitForOperationComplete();
+ ASSERT_TRUE(on_error_signaled_);
+}
+
+#if defined(OS_WIN)
+// This scenario is only a problem on Windows as closing the write pipe there
+// does not trigger the parent process to close the read pipe.
+TEST_F(NativeMessagingReaderTest, ReaderDestroyedByOwner) {
+ WriteMessage("{\"foo\": 42}");
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(on_error_signaled_);
+
+ // Destroy the reader while it is waiting for more data.
+ reader_.reset();
+ ASSERT_FALSE(on_error_signaled_);
+}
+#endif // defined(OS_WIN)
+
+TEST_F(NativeMessagingReaderTest, SingleGoodMessage) {
WriteMessage("{\"foo\": 42}");
- Run();
- EXPECT_TRUE(message_);
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(on_error_signaled_);
+ ASSERT_TRUE(message_);
base::DictionaryValue* message_dict;
- EXPECT_TRUE(message_->GetAsDictionary(&message_dict));
+ ASSERT_TRUE(message_->GetAsDictionary(&message_dict));
int result;
- EXPECT_TRUE(message_dict->GetInteger("foo", &result));
- EXPECT_EQ(42, result);
+ ASSERT_TRUE(message_dict->GetInteger("foo", &result));
+ ASSERT_EQ(42, result);
+}
+
+TEST_F(NativeMessagingReaderTest, MultipleGoodMessages) {
+ WriteMessage("{}");
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(on_error_signaled_);
+ ASSERT_TRUE(message_);
+ base::DictionaryValue* message_dict;
+ ASSERT_TRUE(message_->GetAsDictionary(&message_dict));
+
+ int result;
+ WriteMessage("{\"foo\": 42}");
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(on_error_signaled_);
+ ASSERT_TRUE(message_);
+ ASSERT_TRUE(message_->GetAsDictionary(&message_dict));
+ ASSERT_TRUE(message_dict->GetInteger("foo", &result));
+ ASSERT_EQ(42, result);
+
+ WriteMessage("{\"bar\": 43}");
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(on_error_signaled_);
+ ASSERT_TRUE(message_);
+ ASSERT_TRUE(message_->GetAsDictionary(&message_dict));
+ ASSERT_TRUE(message_dict->GetInteger("bar", &result));
+ ASSERT_EQ(43, result);
+
+ WriteMessage("{\"baz\": 44}");
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(on_error_signaled_);
+ ASSERT_TRUE(message_);
+ ASSERT_TRUE(message_->GetAsDictionary(&message_dict));
+ ASSERT_TRUE(message_dict->GetInteger("baz", &result));
+ ASSERT_EQ(44, result);
}
TEST_F(NativeMessagingReaderTest, InvalidLength) {
uint32_t length = 0xffffffff;
WriteData(reinterpret_cast<char*>(&length), 4);
- Run();
- EXPECT_FALSE(message_);
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(message_);
+ ASSERT_TRUE(on_error_signaled_);
}
TEST_F(NativeMessagingReaderTest, EmptyFile) {
- Run();
- EXPECT_FALSE(message_);
+ write_file_.Close();
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(message_);
+ ASSERT_TRUE(on_error_signaled_);
}
TEST_F(NativeMessagingReaderTest, ShortHeader) {
// Write only 3 bytes - the message length header is supposed to be 4 bytes.
WriteData("xxx", 3);
- Run();
- EXPECT_FALSE(message_);
+ write_file_.Close();
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(message_);
+ ASSERT_TRUE(on_error_signaled_);
}
TEST_F(NativeMessagingReaderTest, EmptyBody) {
uint32_t length = 1;
WriteData(reinterpret_cast<char*>(&length), 4);
- Run();
- EXPECT_FALSE(message_);
+ write_file_.Close();
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(message_);
+ ASSERT_TRUE(on_error_signaled_);
}
TEST_F(NativeMessagingReaderTest, ShortBody) {
@@ -130,27 +207,19 @@ TEST_F(NativeMessagingReaderTest, ShortBody) {
// Only write 1 byte, where the header indicates there should be 2 bytes.
WriteData("x", 1);
- Run();
- EXPECT_FALSE(message_);
+ write_file_.Close();
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(message_);
+ ASSERT_TRUE(on_error_signaled_);
}
TEST_F(NativeMessagingReaderTest, InvalidJSON) {
std::string text = "{";
WriteMessage(text);
- Run();
- EXPECT_FALSE(message_);
-}
-
-TEST_F(NativeMessagingReaderTest, SecondMessage) {
- WriteMessage("{}");
- WriteMessage("{\"foo\": 42}");
- Run();
- EXPECT_TRUE(message_);
- base::DictionaryValue* message_dict;
- EXPECT_TRUE(message_->GetAsDictionary(&message_dict));
- int result;
- EXPECT_TRUE(message_dict->GetInteger("foo", &result));
- EXPECT_EQ(42, result);
+ write_file_.Close();
+ RunAndWaitForOperationComplete();
+ ASSERT_FALSE(message_);
+ ASSERT_TRUE(on_error_signaled_);
}
} // namespace remoting
« no previous file with comments | « remoting/host/native_messaging/native_messaging_reader.cc ('k') | remoting/host/setup/me2me_native_messaging_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698