Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / test / core / iomgr / socket_utils_test.cc
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include "src/core/lib/iomgr/port.h"
20
21 // This test won't work except with posix sockets enabled
22 #ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
23
24 #include <errno.h>
25 #include <netinet/in.h>
26 #include <netinet/ip.h>
27 #include <string.h>
28
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
31 #include <grpc/support/sync.h>
32
33 #include "src/core/lib/gpr/useful.h"
34 #include "src/core/lib/iomgr/socket_mutator.h"
35 #include "src/core/lib/iomgr/socket_utils_posix.h"
36 #include "test/core/util/test_config.h"
37
38 struct test_socket_mutator {
39   grpc_socket_mutator base;
40   int option_value;
41 };
42
43 static bool mutate_fd(int fd, grpc_socket_mutator* mutator) {
44   int newval;
45   socklen_t intlen = sizeof(newval);
46   struct test_socket_mutator* m =
47       reinterpret_cast<struct test_socket_mutator*>(mutator);
48
49   if (0 != setsockopt(fd, IPPROTO_IP, IP_TOS, &m->option_value,
50                       sizeof(m->option_value))) {
51     return false;
52   }
53   if (0 != getsockopt(fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) {
54     return false;
55   }
56   if (newval != m->option_value) {
57     return false;
58   }
59   return true;
60 }
61
62 static bool mutate_fd_2(const grpc_mutate_socket_info* info,
63                         grpc_socket_mutator* mutator) {
64   int newval;
65   socklen_t intlen = sizeof(newval);
66   struct test_socket_mutator* m =
67       reinterpret_cast<struct test_socket_mutator*>(mutator);
68
69   if (0 != setsockopt(info->fd, IPPROTO_IP, IP_TOS, &m->option_value,
70                       sizeof(m->option_value))) {
71     return false;
72   }
73   if (0 != getsockopt(info->fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) {
74     return false;
75   }
76   if (newval != m->option_value) {
77     return false;
78   }
79   return true;
80 }
81
82 static void destroy_test_mutator(grpc_socket_mutator* mutator) {
83   struct test_socket_mutator* m =
84       reinterpret_cast<struct test_socket_mutator*>(mutator);
85   gpr_free(m);
86 }
87
88 static int compare_test_mutator(grpc_socket_mutator* a,
89                                 grpc_socket_mutator* b) {
90   struct test_socket_mutator* ma =
91       reinterpret_cast<struct test_socket_mutator*>(a);
92   struct test_socket_mutator* mb =
93       reinterpret_cast<struct test_socket_mutator*>(b);
94   return GPR_ICMP(ma->option_value, mb->option_value);
95 }
96
97 static const grpc_socket_mutator_vtable mutator_vtable = {
98     mutate_fd, compare_test_mutator, destroy_test_mutator, nullptr};
99
100 static const grpc_socket_mutator_vtable mutator_vtable2 = {
101     nullptr, compare_test_mutator, destroy_test_mutator, mutate_fd_2};
102
103 static void test_with_vtable(const grpc_socket_mutator_vtable* vtable) {
104   int sock = socket(PF_INET, SOCK_STREAM, 0);
105   GPR_ASSERT(sock > 0);
106
107   struct test_socket_mutator mutator;
108   grpc_socket_mutator_init(&mutator.base, vtable);
109
110   mutator.option_value = IPTOS_LOWDELAY;
111   GPR_ASSERT(GRPC_LOG_IF_ERROR(
112       "set_socket_with_mutator",
113       grpc_set_socket_with_mutator(sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
114                                    (grpc_socket_mutator*)&mutator)));
115
116   mutator.option_value = IPTOS_THROUGHPUT;
117   GPR_ASSERT(GRPC_LOG_IF_ERROR(
118       "set_socket_with_mutator",
119       grpc_set_socket_with_mutator(sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
120                                    (grpc_socket_mutator*)&mutator)));
121
122   mutator.option_value = IPTOS_RELIABILITY;
123   GPR_ASSERT(GRPC_LOG_IF_ERROR(
124       "set_socket_with_mutator",
125       grpc_set_socket_with_mutator(sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
126                                    (grpc_socket_mutator*)&mutator)));
127
128   mutator.option_value = -1;
129   auto err = grpc_set_socket_with_mutator(
130       sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
131       reinterpret_cast<grpc_socket_mutator*>(&mutator));
132   GPR_ASSERT(err != GRPC_ERROR_NONE);
133   GRPC_ERROR_UNREF(err);
134 }
135
136 int main(int argc, char** argv) {
137   int sock;
138   grpc::testing::TestEnvironment env(argc, argv);
139
140   sock = socket(PF_INET, SOCK_STREAM, 0);
141   GPR_ASSERT(sock > 0);
142
143   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking",
144                                grpc_set_socket_nonblocking(sock, 1)));
145   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking",
146                                grpc_set_socket_nonblocking(sock, 0)));
147   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec",
148                                grpc_set_socket_cloexec(sock, 1)));
149   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec",
150                                grpc_set_socket_cloexec(sock, 0)));
151   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr",
152                                grpc_set_socket_reuse_addr(sock, 1)));
153   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr",
154                                grpc_set_socket_reuse_addr(sock, 0)));
155   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency",
156                                grpc_set_socket_low_latency(sock, 1)));
157   GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency",
158                                grpc_set_socket_low_latency(sock, 0)));
159
160   test_with_vtable(&mutator_vtable);
161   test_with_vtable(&mutator_vtable2);
162
163   close(sock);
164
165   return 0;
166 }
167
168 #else /* GRPC_POSIX_SOCKET_UTILS_COMMON */
169
170 int main(int argc, char** argv) { return 1; }
171
172 #endif /* GRPC_POSIX_SOCKET_UTILS_COMMON */