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 <grpc/grpc.h>
19 #include <grpc/support/log_windows.h>
20 #include <gtest/gtest.h>
21
22 #include "absl/status/status.h"
23 #include "absl/time/time.h"
24 #include "src/core/lib/event_engine/common_closures.h"
25 #include "src/core/lib/event_engine/thread_pool/thread_pool.h"
26 #include "src/core/lib/event_engine/windows/iocp.h"
27 #include "src/core/lib/event_engine/windows/win_socket.h"
28 #include "src/core/lib/iomgr/error.h"
29 #include "src/core/util/notification.h"
30 #include "test/core/event_engine/windows/create_sockpair.h"
31
32 namespace {
33 using ::grpc_event_engine::experimental::AnyInvocableClosure;
34 using ::grpc_event_engine::experimental::CreateSockpair;
35 using ::grpc_event_engine::experimental::IOCP;
36 using ::grpc_event_engine::experimental::ThreadPool;
37 using ::grpc_event_engine::experimental::WinSocket;
38 } // namespace
39
40 class WinSocketTest : public testing::Test {
41 public:
WinSocketTest()42 WinSocketTest()
43 : thread_pool_(grpc_event_engine::experimental::MakeThreadPool(8)) {
44 CreateSockpair(sockpair_, IOCP::GetDefaultSocketFlags());
45 wrapped_client_socket_ =
46 std::make_unique<WinSocket>(sockpair_[0], thread_pool_.get());
47 wrapped_server_socket_ =
48 std::make_unique<WinSocket>(sockpair_[1], thread_pool_.get());
49 }
50
~WinSocketTest()51 ~WinSocketTest() override {
52 wrapped_client_socket_->Shutdown();
53 wrapped_server_socket_->Shutdown();
54 thread_pool_->Quiesce();
55 }
56
57 protected:
58 std::shared_ptr<ThreadPool> thread_pool_;
59 SOCKET sockpair_[2];
60 std::unique_ptr<WinSocket> wrapped_client_socket_;
61 std::unique_ptr<WinSocket> wrapped_server_socket_;
62 };
63
TEST_F(WinSocketTest,ManualReadEventTriggeredWithoutIO)64 TEST_F(WinSocketTest, ManualReadEventTriggeredWithoutIO) {
65 grpc_core::Notification read_called;
66 AnyInvocableClosure on_read([&read_called]() { read_called.Notify(); });
67 wrapped_client_socket_->NotifyOnRead(&on_read);
68 AnyInvocableClosure on_write([] { FAIL() << "No Write expected"; });
69 wrapped_client_socket_->NotifyOnWrite(&on_write);
70 wrapped_client_socket_->read_info()->SetReady();
71 read_called.WaitForNotification();
72 }
73
TEST_F(WinSocketTest,NotificationCalledImmediatelyOnShutdownWinSocket)74 TEST_F(WinSocketTest, NotificationCalledImmediatelyOnShutdownWinSocket) {
75 wrapped_client_socket_->Shutdown();
76 grpc_core::Notification read_called;
77 AnyInvocableClosure closure([this, &read_called] {
78 ASSERT_EQ(wrapped_client_socket_->read_info()->result().bytes_transferred,
79 0u);
80 ASSERT_EQ(wrapped_client_socket_->read_info()->result().wsa_error,
81 WSAESHUTDOWN);
82 read_called.Notify();
83 });
84 wrapped_client_socket_->NotifyOnRead(&closure);
85 read_called.WaitForNotification();
86 }
87
TEST_F(WinSocketTest,UnsetNotificationWorks)88 TEST_F(WinSocketTest, UnsetNotificationWorks) {
89 AnyInvocableClosure read_closure{
90 []() { grpc_core::Crash("read callback called"); }};
91 wrapped_client_socket_->NotifyOnRead(&read_closure);
92 AnyInvocableClosure write_closure{
93 []() { grpc_core::Crash("write callback called"); }};
94 wrapped_client_socket_->NotifyOnWrite(&write_closure);
95 wrapped_client_socket_->UnregisterReadCallback();
96 wrapped_client_socket_->UnregisterWriteCallback();
97 // Give this time to fail.
98 absl::SleepFor(absl::Seconds(1));
99 }
100
TEST_F(WinSocketTest,UnsetNotificationCanBeDoneRepeatedly)101 TEST_F(WinSocketTest, UnsetNotificationCanBeDoneRepeatedly) {
102 // This should crash if a callback is already registered.
103 AnyInvocableClosure closure{
104 []() { grpc_core::Crash("read callback 1 called"); }};
105 wrapped_client_socket_->NotifyOnRead(&closure);
106 wrapped_client_socket_->UnregisterReadCallback();
107 wrapped_client_socket_->NotifyOnRead(&closure);
108 wrapped_client_socket_->UnregisterReadCallback();
109 wrapped_client_socket_->NotifyOnRead(&closure);
110 wrapped_client_socket_->UnregisterReadCallback();
111 // Give this time to fail.
112 absl::SleepFor(absl::Seconds(1));
113 }
114
main(int argc,char ** argv)115 int main(int argc, char** argv) {
116 ::testing::InitGoogleTest(&argc, argv);
117 grpc_init();
118 int status = RUN_ALL_TESTS();
119 grpc_shutdown();
120 return status;
121 }
122
123 #else // not GPR_WINDOWS
main(int,char **)124 int main(int /* argc */, char** /* argv */) { return 0; }
125 #endif
126