1 // Copyright 2022 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <grpc/support/port_platform.h>
16
17 #ifdef GPR_WINDOWS
18 #include <gtest/gtest.h>
19
20 #include "absl/status/status.h"
21 #include "absl/time/time.h"
22
23 #include <grpc/grpc.h>
24 #include <grpc/support/log_windows.h>
25
26 #include "src/core/lib/event_engine/common_closures.h"
27 #include "src/core/lib/event_engine/thread_pool/thread_pool.h"
28 #include "src/core/lib/event_engine/windows/iocp.h"
29 #include "src/core/lib/event_engine/windows/win_socket.h"
30 #include "src/core/lib/gprpp/notification.h"
31 #include "src/core/lib/iomgr/error.h"
32 #include "test/core/event_engine/windows/create_sockpair.h"
33
34 namespace {
35 using ::grpc_event_engine::experimental::AnyInvocableClosure;
36 using ::grpc_event_engine::experimental::CreateSockpair;
37 using ::grpc_event_engine::experimental::IOCP;
38 using ::grpc_event_engine::experimental::ThreadPool;
39 using ::grpc_event_engine::experimental::WinSocket;
40 } // namespace
41
42 class WinSocketTest : public testing::Test {
43 public:
WinSocketTest()44 WinSocketTest()
45 : thread_pool_(grpc_event_engine::experimental::MakeThreadPool(8)) {
46 CreateSockpair(sockpair_, IOCP::GetDefaultSocketFlags());
47 wrapped_client_socket_ =
48 std::make_unique<WinSocket>(sockpair_[0], thread_pool_.get());
49 wrapped_server_socket_ =
50 std::make_unique<WinSocket>(sockpair_[1], thread_pool_.get());
51 }
52
~WinSocketTest()53 ~WinSocketTest() override {
54 wrapped_client_socket_->Shutdown();
55 wrapped_server_socket_->Shutdown();
56 thread_pool_->Quiesce();
57 }
58
59 protected:
60 std::shared_ptr<ThreadPool> thread_pool_;
61 SOCKET sockpair_[2];
62 std::unique_ptr<WinSocket> wrapped_client_socket_;
63 std::unique_ptr<WinSocket> wrapped_server_socket_;
64 };
65
TEST_F(WinSocketTest,ManualReadEventTriggeredWithoutIO)66 TEST_F(WinSocketTest, ManualReadEventTriggeredWithoutIO) {
67 grpc_core::Notification read_called;
68 AnyInvocableClosure on_read([&read_called]() { read_called.Notify(); });
69 wrapped_client_socket_->NotifyOnRead(&on_read);
70 AnyInvocableClosure on_write([] { FAIL() << "No Write expected"; });
71 wrapped_client_socket_->NotifyOnWrite(&on_write);
72 wrapped_client_socket_->read_info()->SetReady();
73 read_called.WaitForNotification();
74 }
75
TEST_F(WinSocketTest,NotificationCalledImmediatelyOnShutdownWinSocket)76 TEST_F(WinSocketTest, NotificationCalledImmediatelyOnShutdownWinSocket) {
77 wrapped_client_socket_->Shutdown();
78 grpc_core::Notification read_called;
79 AnyInvocableClosure closure([this, &read_called] {
80 ASSERT_EQ(wrapped_client_socket_->read_info()->result().bytes_transferred,
81 0u);
82 ASSERT_EQ(wrapped_client_socket_->read_info()->result().wsa_error,
83 WSAESHUTDOWN);
84 read_called.Notify();
85 });
86 wrapped_client_socket_->NotifyOnRead(&closure);
87 read_called.WaitForNotification();
88 }
89
TEST_F(WinSocketTest,UnsetNotificationWorks)90 TEST_F(WinSocketTest, UnsetNotificationWorks) {
91 AnyInvocableClosure read_closure{
92 []() { grpc_core::Crash("read callback called"); }};
93 wrapped_client_socket_->NotifyOnRead(&read_closure);
94 AnyInvocableClosure write_closure{
95 []() { grpc_core::Crash("write callback called"); }};
96 wrapped_client_socket_->NotifyOnWrite(&write_closure);
97 wrapped_client_socket_->UnregisterReadCallback();
98 wrapped_client_socket_->UnregisterWriteCallback();
99 // Give this time to fail.
100 absl::SleepFor(absl::Seconds(1));
101 }
102
TEST_F(WinSocketTest,UnsetNotificationCanBeDoneRepeatedly)103 TEST_F(WinSocketTest, UnsetNotificationCanBeDoneRepeatedly) {
104 // This should crash if a callback is already registered.
105 AnyInvocableClosure closure{
106 []() { grpc_core::Crash("read callback 1 called"); }};
107 wrapped_client_socket_->NotifyOnRead(&closure);
108 wrapped_client_socket_->UnregisterReadCallback();
109 wrapped_client_socket_->NotifyOnRead(&closure);
110 wrapped_client_socket_->UnregisterReadCallback();
111 wrapped_client_socket_->NotifyOnRead(&closure);
112 wrapped_client_socket_->UnregisterReadCallback();
113 // Give this time to fail.
114 absl::SleepFor(absl::Seconds(1));
115 }
116
main(int argc,char ** argv)117 int main(int argc, char** argv) {
118 ::testing::InitGoogleTest(&argc, argv);
119 grpc_init();
120 int status = RUN_ALL_TESTS();
121 grpc_shutdown();
122 return status;
123 }
124
125 #else // not GPR_WINDOWS
main(int,char **)126 int main(int /* argc */, char** /* argv */) { return 0; }
127 #endif
128