diff options
Diffstat (limited to 'test/cctest/test_inspector_socket.cc')
-rw-r--r-- | test/cctest/test_inspector_socket.cc | 601 |
1 files changed, 246 insertions, 355 deletions
diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc index d1f5b4a98a..943109b8a5 100644 --- a/test/cctest/test_inspector_socket.cc +++ b/test/cctest/test_inspector_socket.cc @@ -1,57 +1,17 @@ #include "inspector_socket.h" #include "gtest/gtest.h" +#include <queue> + #define PORT 9444 namespace { using node::inspector::InspectorSocket; -using node::inspector::inspector_from_stream; -using node::inspector::inspector_handshake_event; -using node::inspector::kInspectorHandshakeFailed; -using node::inspector::kInspectorHandshakeHttpGet; -using node::inspector::kInspectorHandshakeUpgraded; -using node::inspector::kInspectorHandshakeUpgrading; static const int MAX_LOOP_ITERATIONS = 10000; -#define SPIN_WHILE(condition) \ - { \ - Timeout timeout(&loop); \ - while ((condition) && !timeout.timed_out) { \ - uv_run(&loop, UV_RUN_NOWAIT); \ - } \ - ASSERT_FALSE((condition)); \ - } - -static bool connected = false; -static bool inspector_ready = false; -static int handshake_events = 0; -static enum inspector_handshake_event last_event = kInspectorHandshakeHttpGet; static uv_loop_t loop; -static uv_tcp_t server, client_socket; -static InspectorSocket inspector; -static std::string last_path; // NOLINT(runtime/string) -static void (*handshake_delegate)(enum inspector_handshake_event state, - const std::string& path, - bool* should_continue); -static const char SERVER_CLOSE_FRAME[] = {'\x88', '\x00'}; - - -struct read_expects { - const char* expected; - size_t expected_len; - size_t pos; - bool read_expected; - bool callback_called; -}; - -static const char HANDSHAKE_REQ[] = "GET /ws/path HTTP/1.1\r\n" - "Host: localhost:9222\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key: aaa==\r\n" - "Sec-WebSocket-Version: 13\r\n\r\n"; class Timeout { public: @@ -86,16 +46,176 @@ class Timeout { uv_timer_t timer_; }; -static void stop_if_stop_path(enum inspector_handshake_event state, - const std::string& path, bool* cont) { - *cont = path.empty() || path != "/close"; +#define SPIN_WHILE(condition) \ + { \ + Timeout timeout(&loop); \ + while ((condition) && !timeout.timed_out) { \ + uv_run(&loop, UV_RUN_NOWAIT); \ + } \ + ASSERT_FALSE((condition)); \ + } + +enum inspector_handshake_event { + kInspectorHandshakeHttpGet, + kInspectorHandshakeUpgraded, + kInspectorHandshakeNoEvents +}; + +struct expectations { + std::string actual_data; + size_t actual_offset; + size_t actual_end; + int err_code; +}; + +static bool waiting_to_close = true; + +void handle_closed(uv_handle_t* handle) { + waiting_to_close = false; } -static bool connected_cb(InspectorSocket* socket, - enum inspector_handshake_event state, - const std::string& path) { - inspector_ready = state == kInspectorHandshakeUpgraded; - last_event = state; +static void really_close(uv_handle_t* handle) { + waiting_to_close = true; + if (!uv_is_closing(handle)) { + uv_close(handle, handle_closed); + SPIN_WHILE(waiting_to_close); + } +} + +static void buffer_alloc_cb(uv_handle_t* stream, size_t len, uv_buf_t* buf) { + buf->base = new char[len]; + buf->len = len; +} + +class TestInspectorDelegate; + +static TestInspectorDelegate* delegate = nullptr; + +// Gtest asserts can't be used in dtor directly. +static void assert_is_delegate(TestInspectorDelegate* d) { + GTEST_ASSERT_EQ(delegate, d); +} + +class TestInspectorDelegate : public InspectorSocket::Delegate { + public: + using delegate_fn = void(*)(inspector_handshake_event, const std::string&, + bool* should_continue); + + TestInspectorDelegate() : inspector_ready(false), + last_event(kInspectorHandshakeNoEvents), + handshake_events(0), + handshake_delegate_(stop_if_stop_path), + fail_on_ws_frame_(false) { } + + ~TestInspectorDelegate() { + assert_is_delegate(this); + delegate = nullptr; + } + + void OnHttpGet(const std::string& path) override { + process(kInspectorHandshakeHttpGet, path); + } + + void OnSocketUpgrade(const std::string& path, + const std::string& ws_key) override { + ws_key_ = ws_key; + process(kInspectorHandshakeUpgraded, path); + } + + void OnWsFrame(const std::vector<char>& buffer) override { + ASSERT_FALSE(fail_on_ws_frame_); + frames.push(buffer); + } + + void SetDelegate(delegate_fn d) { + handshake_delegate_ = d; + } + + void SetInspector(InspectorSocket::Pointer inspector) { + socket_ = std::move(inspector); + } + + void Write(const char* buf, size_t len) { + socket_->Write(buf, len); + } + + void ExpectReadError() { + SPIN_WHILE(frames.empty() || !frames.back().empty()); + } + + void ExpectData(const char* data, size_t len) { + const char* cur = data; + const char* end = data + len; + while (cur < end) { + SPIN_WHILE(frames.empty()); + const std::vector<char>& frame = frames.front(); + EXPECT_FALSE(frame.empty()); + auto c = frame.begin(); + for (; c < frame.end() && cur < end; c++) { + GTEST_ASSERT_EQ(*cur, *c) << "Character #" << cur - data; + cur = cur + 1; + } + EXPECT_EQ(c, frame.end()); + frames.pop(); + } + } + + void FailOnWsFrame() { + fail_on_ws_frame_ = true; + } + + void WaitForDispose() { + SPIN_WHILE(delegate != nullptr); + } + + void Close() { + socket_.reset(); + } + + bool inspector_ready; + std::string last_path; // NOLINT(runtime/string) + inspector_handshake_event last_event; + int handshake_events; + std::queue<std::vector<char>> frames; + + private: + static void stop_if_stop_path(enum inspector_handshake_event state, + const std::string& path, bool* cont) { + *cont = path.empty() || path != "/close"; + } + + void process(inspector_handshake_event event, const std::string& path); + + bool disposed_ = false; + delegate_fn handshake_delegate_; + InspectorSocket::Pointer socket_; + std::string ws_key_; + bool fail_on_ws_frame_; +}; + +static bool connected = false; +static uv_tcp_t server, client_socket; +static const char SERVER_CLOSE_FRAME[] = {'\x88', '\x00'}; + +struct read_expects { + const char* expected; + size_t expected_len; + size_t pos; + bool read_expected; + bool callback_called; +}; + +static const char HANDSHAKE_REQ[] = "GET /ws/path HTTP/1.1\r\n" + "Host: localhost:9222\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: aaa==\r\n" + "Sec-WebSocket-Version: 13\r\n\r\n"; + +void TestInspectorDelegate::process(inspector_handshake_event event, + const std::string& path) { + inspector_ready = event == kInspectorHandshakeUpgraded; + last_event = event; if (path.empty()) { last_path = "@@@ Nothing received @@@"; } else { @@ -103,15 +223,23 @@ static bool connected_cb(InspectorSocket* socket, } handshake_events++; bool should_continue = true; - handshake_delegate(state, path, &should_continue); - return should_continue; + handshake_delegate_(event, path, &should_continue); + if (should_continue) { + if (inspector_ready) + socket_->AcceptUpgrade(ws_key_); + } else { + socket_->CancelHandshake(); + } } static void on_new_connection(uv_stream_t* server, int status) { GTEST_ASSERT_EQ(0, status); connected = true; - inspector_accept(server, static_cast<InspectorSocket*>(server->data), - connected_cb); + delegate = new TestInspectorDelegate(); + delegate->SetInspector( + InspectorSocket::Accept(server, + InspectorSocket::DelegatePointer(delegate))); + GTEST_ASSERT_NE(nullptr, delegate); } void write_done(uv_write_t* req, int status) { req->data = nullptr; } @@ -129,11 +257,6 @@ static void do_write(const char* data, int len) { SPIN_WHILE(req.data); } -static void buffer_alloc_cb(uv_handle_t* stream, size_t len, uv_buf_t* buf) { - buf->base = new char[len]; - buf->len = len; -} - static void check_data_cb(read_expects* expectation, ssize_t nread, const uv_buf_t* buf, bool* retval) { *retval = false; @@ -207,102 +330,6 @@ static void expect_on_client(const char* data, size_t len) { SPIN_WHILE(!expectation.read_expected); } -struct expectations { - std::string actual_data; - size_t actual_offset; - size_t actual_end; - int err_code; -}; - -static void grow_expects_buffer(uv_handle_t* stream, size_t size, uv_buf_t* b) { - expectations* expects = static_cast<expectations*>( - inspector_from_stream(stream)->data); - size_t end = expects->actual_end; - // Grow the buffer in chunks of 64k. - size_t new_length = (end + size + 65535) & ~((size_t) 0xFFFF); - expects->actual_data.resize(new_length); - *b = uv_buf_init(&expects->actual_data[end], new_length - end); -} - -// static void dump_hex(const char* buf, size_t len) { -// const char* ptr = buf; -// const char* end = ptr + len; -// const char* cptr; -// char c; -// int i; - -// while (ptr < end) { -// cptr = ptr; -// for (i = 0; i < 16 && ptr < end; i++) { -// printf("%2.2X ", *(ptr++)); -// } -// for (i = 72 - (i * 4); i > 0; i--) { -// printf(" "); -// } -// for (i = 0; i < 16 && cptr < end; i++) { -// c = *(cptr++); -// printf("%c", (c > 0x19) ? c : '.'); -// } -// printf("\n"); -// } -// printf("\n\n"); -// } - -static void save_read_data(uv_stream_t* stream, ssize_t nread, - const uv_buf_t* buf) { - expectations* expects = static_cast<expectations*>( - inspector_from_stream(stream)->data); - expects->err_code = nread < 0 ? nread : 0; - if (nread > 0) { - expects->actual_end += nread; - } -} - -static void setup_inspector_expecting() { - if (inspector.data) { - return; - } - expectations* expects = new expectations(); - inspector.data = expects; - inspector_read_start(&inspector, grow_expects_buffer, save_read_data); -} - -static void expect_on_server(const char* data, size_t len) { - setup_inspector_expecting(); - expectations* expects = static_cast<expectations*>(inspector.data); - for (size_t i = 0; i < len;) { - SPIN_WHILE(expects->actual_offset == expects->actual_end); - for (; i < len && expects->actual_offset < expects->actual_end; i++) { - char actual = expects->actual_data[expects->actual_offset++]; - char expected = data[i]; - if (expected != actual) { - fprintf(stderr, "Character %zu:\n", i); - GTEST_ASSERT_EQ(expected, actual); - } - } - } - expects->actual_end -= expects->actual_offset; - if (!expects->actual_end) { - memmove(&expects->actual_data[0], - &expects->actual_data[expects->actual_offset], - expects->actual_end); - } - expects->actual_offset = 0; -} - -static void inspector_record_error_code(uv_stream_t* stream, ssize_t nread, - const uv_buf_t* buf) { - InspectorSocket *inspector = inspector_from_stream(stream); - // Increment instead of assign is to ensure the function is only called once - *(static_cast<int*>(inspector->data)) += nread; -} - -static void expect_server_read_error() { - setup_inspector_expecting(); - expectations* expects = static_cast<expectations*>(inspector.data); - SPIN_WHILE(expects->err_code != UV_EPROTO); -} - static void expect_handshake() { const char UPGRADE_RESPONSE[] = "HTTP/1.1 101 Switching Protocols\r\n" @@ -320,35 +347,6 @@ static void expect_handshake_failure() { expect_on_client(UPGRADE_RESPONSE, sizeof(UPGRADE_RESPONSE) - 1); } -static bool waiting_to_close = true; - -void handle_closed(uv_handle_t* handle) { waiting_to_close = false; } - -static void really_close(uv_handle_t* handle) { - waiting_to_close = true; - if (!uv_is_closing(handle)) { - uv_close(handle, handle_closed); - SPIN_WHILE(waiting_to_close); - } -} - -// Called when the test leaves inspector socket in active state -static void manual_inspector_socket_cleanup() { - EXPECT_EQ(0, uv_is_active( - reinterpret_cast<uv_handle_t*>(&inspector.tcp))); - really_close(reinterpret_cast<uv_handle_t*>(&inspector.tcp)); - delete inspector.ws_state; - inspector.ws_state = nullptr; - delete inspector.http_parsing_state; - inspector.http_parsing_state = nullptr; - inspector.buffer.clear(); -} - -static void assert_both_sockets_closed() { - SPIN_WHILE(uv_is_active(reinterpret_cast<uv_handle_t*>(&client_socket))); - SPIN_WHILE(uv_is_active(reinterpret_cast<uv_handle_t*>(&inspector.tcp))); -} - static void on_connection(uv_connect_t* connect, int status) { GTEST_ASSERT_EQ(0, status); connect->data = connect; @@ -357,16 +355,10 @@ static void on_connection(uv_connect_t* connect, int status) { class InspectorSocketTest : public ::testing::Test { protected: virtual void SetUp() { - inspector.reinit(); - handshake_delegate = stop_if_stop_path; - handshake_events = 0; connected = false; - inspector_ready = false; - last_event = kInspectorHandshakeHttpGet; GTEST_ASSERT_EQ(0, uv_loop_init(&loop)); server = uv_tcp_t(); client_socket = uv_tcp_t(); - server.data = &inspector; sockaddr_in addr; uv_tcp_init(&loop, &server); uv_tcp_init(&loop, &client_socket); @@ -386,13 +378,7 @@ class InspectorSocketTest : public ::testing::Test { virtual void TearDown() { really_close(reinterpret_cast<uv_handle_t*>(&client_socket)); - EXPECT_TRUE(inspector.buffer.empty()); - expectations* expects = static_cast<expectations*>(inspector.data); - if (expects != nullptr) { - GTEST_ASSERT_EQ(expects->actual_end, expects->actual_offset); - delete expects; - inspector.data = nullptr; - } + SPIN_WHILE(delegate != nullptr); const int err = uv_loop_close(&loop); if (err != 0) { uv_print_all_handles(&loop, stderr); @@ -403,22 +389,22 @@ class InspectorSocketTest : public ::testing::Test { TEST_F(InspectorSocketTest, ReadsAndWritesInspectorMessage) { ASSERT_TRUE(connected); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); - SPIN_WHILE(!inspector_ready); + SPIN_WHILE(!delegate->inspector_ready); expect_handshake(); // 2. Brief exchange const char SERVER_MESSAGE[] = "abcd"; const char CLIENT_FRAME[] = {'\x81', '\x04', 'a', 'b', 'c', 'd'}; - inspector_write(&inspector, SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); + delegate->Write(SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); expect_on_client(CLIENT_FRAME, sizeof(CLIENT_FRAME)); const char SERVER_FRAME[] = {'\x81', '\x84', '\x7F', '\xC2', '\x66', '\x31', '\x4E', '\xF0', '\x55', '\x05'}; const char CLIENT_MESSAGE[] = "1234"; do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); - expect_on_server(CLIENT_MESSAGE, sizeof(CLIENT_MESSAGE) - 1); + delegate->ExpectData(CLIENT_MESSAGE, sizeof(CLIENT_MESSAGE) - 1); // 3. Close const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', @@ -487,53 +473,34 @@ TEST_F(InspectorSocketTest, BufferEdgeCases) { "{\"id\":17,\"method\":\"Network.canEmulateNetworkConditions\"}"}; do_write(MULTIPLE_REQUESTS, sizeof(MULTIPLE_REQUESTS)); - expect_on_server(EXPECT, sizeof(EXPECT) - 1); - inspector_read_stop(&inspector); - manual_inspector_socket_cleanup(); + delegate->ExpectData(EXPECT, sizeof(EXPECT) - 1); } TEST_F(InspectorSocketTest, AcceptsRequestInSeveralWrites) { ASSERT_TRUE(connected); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); // Specifically, break up the request in the "Sec-WebSocket-Key" header name // and value const int write1 = 95; const int write2 = 5; const int write3 = sizeof(HANDSHAKE_REQ) - write1 - write2 - 1; do_write(const_cast<char*>(HANDSHAKE_REQ), write1); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); do_write(const_cast<char*>(HANDSHAKE_REQ) + write1, write2); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); do_write(const_cast<char*>(HANDSHAKE_REQ) + write1 + write2, write3); - SPIN_WHILE(!inspector_ready); + SPIN_WHILE(!delegate->inspector_ready); expect_handshake(); - inspector_read_stop(&inspector); GTEST_ASSERT_EQ(uv_is_active(reinterpret_cast<uv_handle_t*>(&client_socket)), 0); - manual_inspector_socket_cleanup(); } TEST_F(InspectorSocketTest, ExtraTextBeforeRequest) { - last_event = kInspectorHandshakeUpgraded; - char UNCOOL_BRO[] = "Uncool, bro: Text before the first req\r\n"; - do_write(const_cast<char*>(UNCOOL_BRO), sizeof(UNCOOL_BRO) - 1); - - ASSERT_FALSE(inspector_ready); - do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); - SPIN_WHILE(last_event != kInspectorHandshakeFailed); - expect_handshake_failure(); - assert_both_sockets_closed(); -} - -TEST_F(InspectorSocketTest, ExtraLettersBeforeRequest) { - char UNCOOL_BRO[] = "Uncool!!"; + delegate->last_event = kInspectorHandshakeUpgraded; + char UNCOOL_BRO[] = "Text before the first req, shouldn't be her\r\n"; do_write(const_cast<char*>(UNCOOL_BRO), sizeof(UNCOOL_BRO) - 1); - - ASSERT_FALSE(inspector_ready); - do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); - SPIN_WHILE(last_event != kInspectorHandshakeFailed); expect_handshake_failure(); - assert_both_sockets_closed(); + GTEST_ASSERT_EQ(nullptr, delegate); } TEST_F(InspectorSocketTest, RequestWithoutKey) { @@ -544,87 +511,65 @@ TEST_F(InspectorSocketTest, RequestWithoutKey) { "Sec-WebSocket-Version: 13\r\n\r\n"; do_write(const_cast<char*>(BROKEN_REQUEST), sizeof(BROKEN_REQUEST) - 1); - SPIN_WHILE(last_event != kInspectorHandshakeFailed); expect_handshake_failure(); - assert_both_sockets_closed(); } TEST_F(InspectorSocketTest, KillsConnectionOnProtocolViolation) { ASSERT_TRUE(connected); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); - SPIN_WHILE(!inspector_ready); - ASSERT_TRUE(inspector_ready); + SPIN_WHILE(!delegate->inspector_ready); + ASSERT_TRUE(delegate->inspector_ready); expect_handshake(); const char SERVER_FRAME[] = "I'm not a good WS frame. Nope!"; do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); - expect_server_read_error(); + SPIN_WHILE(delegate != nullptr); GTEST_ASSERT_EQ(uv_is_active(reinterpret_cast<uv_handle_t*>(&client_socket)), 0); } TEST_F(InspectorSocketTest, CanStopReadingFromInspector) { ASSERT_TRUE(connected); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake(); - ASSERT_TRUE(inspector_ready); + ASSERT_TRUE(delegate->inspector_ready); // 2. Brief exchange const char SERVER_FRAME[] = {'\x81', '\x84', '\x7F', '\xC2', '\x66', '\x31', '\x4E', '\xF0', '\x55', '\x05'}; const char CLIENT_MESSAGE[] = "1234"; do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); - expect_on_server(CLIENT_MESSAGE, sizeof(CLIENT_MESSAGE) - 1); + delegate->ExpectData(CLIENT_MESSAGE, sizeof(CLIENT_MESSAGE) - 1); - inspector_read_stop(&inspector); do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); GTEST_ASSERT_EQ(uv_is_active( reinterpret_cast<uv_handle_t*>(&client_socket)), 0); - manual_inspector_socket_cleanup(); -} - -static int inspector_closed = 0; - -void inspector_closed_cb(InspectorSocket *inspector, int code) { - inspector_closed++; } TEST_F(InspectorSocketTest, CloseDoesNotNotifyReadCallback) { - inspector_closed = 0; do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake(); - int error_code = 0; - inspector.data = &error_code; - inspector_read_start(&inspector, buffer_alloc_cb, - inspector_record_error_code); - inspector_close(&inspector, inspector_closed_cb); + delegate->Close(); char CLOSE_FRAME[] = {'\x88', '\x00'}; expect_on_client(CLOSE_FRAME, sizeof(CLOSE_FRAME)); - EXPECT_EQ(0, inspector_closed); const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', '\x0E', '\x1E', '\xFA'}; + delegate->FailOnWsFrame(); do_write(CLIENT_CLOSE_FRAME, sizeof(CLIENT_CLOSE_FRAME)); - EXPECT_NE(UV_EOF, error_code); - SPIN_WHILE(inspector_closed == 0); - EXPECT_EQ(1, inspector_closed); - inspector.data = nullptr; + SPIN_WHILE(delegate != nullptr); } TEST_F(InspectorSocketTest, CloseWorksWithoutReadEnabled) { - inspector_closed = 0; do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake(); - inspector_close(&inspector, inspector_closed_cb); + delegate->Close(); char CLOSE_FRAME[] = {'\x88', '\x00'}; expect_on_client(CLOSE_FRAME, sizeof(CLOSE_FRAME)); - EXPECT_EQ(0, inspector_closed); const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', '\x0E', '\x1E', '\xFA'}; do_write(CLIENT_CLOSE_FRAME, sizeof(CLIENT_CLOSE_FRAME)); - SPIN_WHILE(inspector_closed == 0); - EXPECT_EQ(1, inspector_closed); } // Make sure buffering works @@ -641,26 +586,24 @@ static void send_in_chunks(const char* data, size_t len) { } static const char TEST_SUCCESS[] = "Test Success\n\n"; +static int ReportsHttpGet_eventsCount = 0; static void ReportsHttpGet_handshake(enum inspector_handshake_event state, const std::string& path, bool* cont) { *cont = true; enum inspector_handshake_event expected_state = kInspectorHandshakeHttpGet; std::string expected_path; - switch (handshake_events) { + switch (delegate->handshake_events) { case 1: expected_path = "/some/path"; break; case 2: expected_path = "/respond/withtext"; - inspector_write(&inspector, TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); + delegate->Write(TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); break; case 3: expected_path = "/some/path2"; break; - case 5: - expected_state = kInspectorHandshakeFailed; - break; case 4: expected_path = "/close"; *cont = false; @@ -670,10 +613,11 @@ static void ReportsHttpGet_handshake(enum inspector_handshake_event state, } EXPECT_EQ(expected_state, state); EXPECT_EQ(expected_path, path); + ReportsHttpGet_eventsCount = delegate->handshake_events; } TEST_F(InspectorSocketTest, ReportsHttpGet) { - handshake_delegate = ReportsHttpGet_handshake; + delegate->SetDelegate(ReportsHttpGet_handshake); const char GET_REQ[] = "GET /some/path HTTP/1.1\r\n" "Host: localhost:9222\r\n" @@ -688,7 +632,6 @@ TEST_F(InspectorSocketTest, ReportsHttpGet) { send_in_chunks(WRITE_REQUEST, sizeof(WRITE_REQUEST) - 1); expect_on_client(TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); - const char GET_REQS[] = "GET /some/path2 HTTP/1.1\r\n" "Host: localhost:9222\r\n" "Sec-WebSocket-Key: aaa==\r\n" @@ -698,53 +641,50 @@ TEST_F(InspectorSocketTest, ReportsHttpGet) { "Sec-WebSocket-Key: aaa==\r\n" "Sec-WebSocket-Version: 13\r\n\r\n"; send_in_chunks(GET_REQS, sizeof(GET_REQS) - 1); - expect_handshake_failure(); - EXPECT_EQ(5, handshake_events); + EXPECT_EQ(4, ReportsHttpGet_eventsCount); + EXPECT_EQ(nullptr, delegate); } -static void -HandshakeCanBeCanceled_handshake(enum inspector_handshake_event state, - const std::string& path, bool* cont) { - switch (handshake_events - 1) { +static int HandshakeCanBeCanceled_eventCount = 0; + +static +void HandshakeCanBeCanceled_handshake(enum inspector_handshake_event state, + const std::string& path, bool* cont) { + switch (delegate->handshake_events - 1) { case 0: - EXPECT_EQ(kInspectorHandshakeUpgrading, state); + EXPECT_EQ(kInspectorHandshakeUpgraded, state); EXPECT_EQ("/ws/path", path); break; - case 1: - EXPECT_EQ(kInspectorHandshakeFailed, state); - EXPECT_TRUE(path.empty()); - break; default: EXPECT_TRUE(false); break; } *cont = false; + HandshakeCanBeCanceled_eventCount = delegate->handshake_events; } TEST_F(InspectorSocketTest, HandshakeCanBeCanceled) { - handshake_delegate = HandshakeCanBeCanceled_handshake; + delegate->SetDelegate(HandshakeCanBeCanceled_handshake); do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake_failure(); - EXPECT_EQ(2, handshake_events); + EXPECT_EQ(1, HandshakeCanBeCanceled_eventCount); + EXPECT_EQ(nullptr, delegate); } static void GetThenHandshake_handshake(enum inspector_handshake_event state, const std::string& path, bool* cont) { *cont = true; std::string expected_path = "/ws/path"; - switch (handshake_events - 1) { + switch (delegate->handshake_events - 1) { case 0: EXPECT_EQ(kInspectorHandshakeHttpGet, state); expected_path = "/respond/withtext"; - inspector_write(&inspector, TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); + delegate->Write(TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); break; case 1: - EXPECT_EQ(kInspectorHandshakeUpgrading, state); - break; - case 2: EXPECT_EQ(kInspectorHandshakeUpgraded, state); break; default: @@ -755,7 +695,7 @@ static void GetThenHandshake_handshake(enum inspector_handshake_event state, } TEST_F(InspectorSocketTest, GetThenHandshake) { - handshake_delegate = GetThenHandshake_handshake; + delegate->SetDelegate(GetThenHandshake_handshake); const char WRITE_REQUEST[] = "GET /respond/withtext HTTP/1.1\r\n" "Host: localhost:9222\r\n\r\n"; send_in_chunks(WRITE_REQUEST, sizeof(WRITE_REQUEST) - 1); @@ -764,15 +704,7 @@ TEST_F(InspectorSocketTest, GetThenHandshake) { do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake(); - EXPECT_EQ(3, handshake_events); - manual_inspector_socket_cleanup(); -} - -static void WriteBeforeHandshake_inspector_delegate(inspector_handshake_event e, - const std::string& path, - bool* cont) { - if (e == kInspectorHandshakeFailed) - inspector_closed = 1; + EXPECT_EQ(2, delegate->handshake_events); } TEST_F(InspectorSocketTest, WriteBeforeHandshake) { @@ -780,51 +712,31 @@ TEST_F(InspectorSocketTest, WriteBeforeHandshake) { const char MESSAGE2[] = "Message 2"; const char EXPECTED[] = "Message 1Message 2"; - inspector_write(&inspector, MESSAGE1, sizeof(MESSAGE1) - 1); - inspector_write(&inspector, MESSAGE2, sizeof(MESSAGE2) - 1); + delegate->Write(MESSAGE1, sizeof(MESSAGE1) - 1); + delegate->Write(MESSAGE2, sizeof(MESSAGE2) - 1); expect_on_client(EXPECTED, sizeof(EXPECTED) - 1); - inspector_closed = 0; - handshake_delegate = WriteBeforeHandshake_inspector_delegate; really_close(reinterpret_cast<uv_handle_t*>(&client_socket)); - SPIN_WHILE(inspector_closed == 0); -} - -static void CleanupSocketAfterEOF_close_cb(InspectorSocket* inspector, - int status) { - *(static_cast<bool*>(inspector->data)) = true; -} - -static void CleanupSocketAfterEOF_read_cb(uv_stream_t* stream, ssize_t nread, - const uv_buf_t* buf) { - EXPECT_EQ(UV_EOF, nread); - InspectorSocket* insp = inspector_from_stream(stream); - inspector_close(insp, CleanupSocketAfterEOF_close_cb); + SPIN_WHILE(delegate != nullptr); } TEST_F(InspectorSocketTest, CleanupSocketAfterEOF) { do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake(); - inspector_read_start(&inspector, buffer_alloc_cb, - CleanupSocketAfterEOF_read_cb); - for (int i = 0; i < MAX_LOOP_ITERATIONS; ++i) { uv_run(&loop, UV_RUN_NOWAIT); } uv_close(reinterpret_cast<uv_handle_t*>(&client_socket), nullptr); - bool flag = false; - inspector.data = &flag; - SPIN_WHILE(!flag); - inspector.data = nullptr; + SPIN_WHILE(delegate != nullptr); } TEST_F(InspectorSocketTest, EOFBeforeHandshake) { const char MESSAGE[] = "We'll send EOF afterwards"; - inspector_write(&inspector, MESSAGE, sizeof(MESSAGE) - 1); + delegate->Write(MESSAGE, sizeof(MESSAGE) - 1); expect_on_client(MESSAGE, sizeof(MESSAGE) - 1); uv_close(reinterpret_cast<uv_handle_t*>(&client_socket), nullptr); - SPIN_WHILE(last_event != kInspectorHandshakeFailed); + SPIN_WHILE(delegate != nullptr); } static void fill_message(std::string* buffer) { @@ -843,9 +755,9 @@ static void mask_message(const std::string& message, TEST_F(InspectorSocketTest, Send1Mb) { ASSERT_TRUE(connected); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); - SPIN_WHILE(!inspector_ready); + SPIN_WHILE(!delegate->inspector_ready); expect_handshake(); // 2. Brief exchange @@ -860,7 +772,7 @@ TEST_F(InspectorSocketTest, Send1Mb) { std::string expected(EXPECTED_FRAME_HEADER, sizeof(EXPECTED_FRAME_HEADER)); expected.append(message); - inspector_write(&inspector, &message[0], message.size()); + delegate->Write(&message[0], message.size()); expect_on_client(&expected[0], expected.size()); char MASK[4] = {'W', 'h', 'O', 'a'}; @@ -874,9 +786,8 @@ TEST_F(InspectorSocketTest, Send1Mb) { outgoing.resize(outgoing.size() + message.size()); mask_message(message, &outgoing[sizeof(FRAME_TO_SERVER_HEADER)], MASK); - setup_inspector_expecting(); // Buffer on the client side. do_write(&outgoing[0], outgoing.size()); - expect_on_server(&message[0], message.size()); + delegate->ExpectData(&message[0], message.size()); // 3. Close const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', @@ -887,53 +798,33 @@ TEST_F(InspectorSocketTest, Send1Mb) { reinterpret_cast<uv_handle_t*>(&client_socket))); } -static ssize_t err; - -void ErrorCleansUpTheSocket_cb(uv_stream_t* stream, ssize_t read, - const uv_buf_t* buf) { - err = read; -} - TEST_F(InspectorSocketTest, ErrorCleansUpTheSocket) { - inspector_closed = 0; do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake(); const char NOT_A_GOOD_FRAME[] = {'H', 'e', 'l', 'l', 'o'}; - err = 42; - inspector_read_start(&inspector, buffer_alloc_cb, - ErrorCleansUpTheSocket_cb); do_write(NOT_A_GOOD_FRAME, sizeof(NOT_A_GOOD_FRAME)); - SPIN_WHILE(err > 0); - EXPECT_EQ(UV_EPROTO, err); -} - -static void ServerClosedByClient_cb(InspectorSocket* socket, int code) { - *static_cast<bool*>(socket->data) = true; + SPIN_WHILE(delegate != nullptr); } -TEST_F(InspectorSocketTest, NoCloseResponseFromClinet) { +TEST_F(InspectorSocketTest, NoCloseResponseFromClient) { ASSERT_TRUE(connected); - ASSERT_FALSE(inspector_ready); + ASSERT_FALSE(delegate->inspector_ready); do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); - SPIN_WHILE(!inspector_ready); + SPIN_WHILE(!delegate->inspector_ready); expect_handshake(); // 2. Brief exchange const char SERVER_MESSAGE[] = "abcd"; const char CLIENT_FRAME[] = {'\x81', '\x04', 'a', 'b', 'c', 'd'}; - inspector_write(&inspector, SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); + delegate->Write(SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); expect_on_client(CLIENT_FRAME, sizeof(CLIENT_FRAME)); - bool closed = false; - - inspector.data = &closed; - inspector_close(&inspector, ServerClosedByClient_cb); + delegate->Close(); expect_on_client(SERVER_CLOSE_FRAME, sizeof(SERVER_CLOSE_FRAME)); uv_close(reinterpret_cast<uv_handle_t*>(&client_socket), nullptr); - SPIN_WHILE(!closed); - inspector.data = nullptr; GTEST_ASSERT_EQ(0, uv_is_active( - reinterpret_cast<uv_handle_t*>(&client_socket))); + reinterpret_cast<uv_handle_t*>(&client_socket))); + delegate->WaitForDispose(); } } // anonymous namespace |