1/*
2 *
3 * Copyright 2018 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#import <XCTest/XCTest.h>
20
21#include "src/core/lib/iomgr/port.h"
22
23#ifdef GRPC_CFSTREAM
24
25#include <netinet/in.h>
26
27#include <grpc/impl/codegen/sync.h>
28#include <grpc/support/sync.h>
29
30#include "src/core/lib/iomgr/endpoint.h"
31#include "src/core/lib/iomgr/resolve_address.h"
32#include "src/core/lib/iomgr/tcp_client.h"
33#include "test/core/util/test_config.h"
34
35// static int g_connections_complete = 0;
36static gpr_mu g_mu;
37static int g_connections_complete = 0;
38static grpc_endpoint* g_connecting = nullptr;
39
40static void finish_connection() {
41  gpr_mu_lock(&g_mu);
42  g_connections_complete++;
43  gpr_mu_unlock(&g_mu);
44}
45
46static void must_succeed(void* arg, grpc_error* error) {
47  GPR_ASSERT(g_connecting != nullptr);
48  GPR_ASSERT(error == GRPC_ERROR_NONE);
49  grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called"));
50  grpc_endpoint_destroy(g_connecting);
51  g_connecting = nullptr;
52  finish_connection();
53}
54
55static void must_fail(void* arg, grpc_error* error) {
56  GPR_ASSERT(g_connecting == nullptr);
57  GPR_ASSERT(error != GRPC_ERROR_NONE);
58  const char* error_str = grpc_error_string(error);
59  NSLog(@"%s", error_str);
60  finish_connection();
61}
62
63@interface CFStreamClientTests : XCTestCase
64
65@end
66
67@implementation CFStreamClientTests
68
69+ (void)setUp {
70  grpc_init();
71  gpr_mu_init(&g_mu);
72}
73
74+ (void)tearDown {
75  grpc_shutdown();
76}
77
78- (void)testSucceeds {
79  grpc_resolved_address resolved_addr;
80  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
81  int svr_fd;
82  int r;
83  int connections_complete_before;
84  grpc_closure done;
85  grpc_core::ExecCtx exec_ctx;
86
87  gpr_log(GPR_DEBUG, "test_succeeds");
88
89  memset(&resolved_addr, 0, sizeof(resolved_addr));
90  resolved_addr.len = sizeof(struct sockaddr_in);
91  addr->sin_family = AF_INET;
92
93  /* create a dummy server */
94  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
95  GPR_ASSERT(svr_fd >= 0);
96  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len));
97  GPR_ASSERT(0 == listen(svr_fd, 1));
98
99  gpr_mu_lock(&g_mu);
100  connections_complete_before = g_connections_complete;
101  gpr_mu_unlock(&g_mu);
102
103  /* connect to it */
104  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr.len) == 0);
105  GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
106  grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr,
107                          GRPC_MILLIS_INF_FUTURE);
108
109  /* await the connection */
110  do {
111    resolved_addr.len = sizeof(addr);
112    r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
113               reinterpret_cast<socklen_t*>(&resolved_addr.len));
114  } while (r == -1 && errno == EINTR);
115  GPR_ASSERT(r >= 0);
116  close(r);
117
118  grpc_core::ExecCtx::Get()->Flush();
119
120  /* wait for the connection callback to finish */
121  gpr_mu_lock(&g_mu);
122  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
123  while (connections_complete_before == g_connections_complete) {
124    gpr_mu_unlock(&g_mu);
125    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
126    gpr_mu_lock(&g_mu);
127  }
128  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
129
130  gpr_mu_unlock(&g_mu);
131}
132
133- (void)testFails {
134  grpc_core::ExecCtx exec_ctx;
135
136  grpc_resolved_address resolved_addr;
137  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
138  int connections_complete_before;
139  grpc_closure done;
140  int svr_fd;
141
142  gpr_log(GPR_DEBUG, "test_fails");
143
144  memset(&resolved_addr, 0, sizeof(resolved_addr));
145  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
146  addr->sin_family = AF_INET;
147
148  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
149  GPR_ASSERT(svr_fd >= 0);
150  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len));
151  GPR_ASSERT(0 == listen(svr_fd, 1));
152  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr.len) == 0);
153  close(svr_fd);
154
155  gpr_mu_lock(&g_mu);
156  connections_complete_before = g_connections_complete;
157  gpr_mu_unlock(&g_mu);
158
159  /* connect to a broken address */
160  GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
161  grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr,
162                          GRPC_MILLIS_INF_FUTURE);
163
164  grpc_core::ExecCtx::Get()->Flush();
165
166  /* wait for the connection callback to finish */
167  gpr_mu_lock(&g_mu);
168  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
169  while (g_connections_complete == connections_complete_before) {
170    gpr_mu_unlock(&g_mu);
171    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
172    gpr_mu_lock(&g_mu);
173  }
174
175  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
176
177  gpr_mu_unlock(&g_mu);
178}
179
180@end
181
182#else  // GRPC_CFSTREAM
183
184// Dummy test suite
185@interface CFStreamClientTests : XCTestCase
186
187@end
188
189@implementation CFStreamClientTests
190
191- (void)setUp {
192  [super setUp];
193}
194
195- (void)tearDown {
196  [super tearDown];
197}
198
199@end
200
201#endif  // GRPC_CFSTREAM
202