1 /*
2 *
3 * Copyright 2016 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 /* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
20 using that endpoint. Because of various transitive includes in uv.h,
21 including windows.h on Windows, uv.h must be included before other system
22 headers. Therefore, sockaddr.h must always be included first */
23 #include "src/core/lib/iomgr/sockaddr.h"
24
25 #include <inttypes.h>
26
27 #include <string>
28
29 #include "absl/strings/str_format.h"
30
31 #include "test/core/util/mock_endpoint.h"
32
33 #include <grpc/support/alloc.h>
34 #include <grpc/support/string_util.h>
35 #include "src/core/lib/iomgr/sockaddr.h"
36
37 typedef struct mock_endpoint {
38 grpc_endpoint base;
39 gpr_mu mu;
40 void (*on_write)(grpc_slice slice);
41 grpc_slice_buffer read_buffer;
42 grpc_slice_buffer* on_read_out;
43 grpc_closure* on_read;
44 grpc_resource_user* resource_user;
45 } mock_endpoint;
46
me_read(grpc_endpoint * ep,grpc_slice_buffer * slices,grpc_closure * cb,bool)47 static void me_read(grpc_endpoint* ep, grpc_slice_buffer* slices,
48 grpc_closure* cb, bool /*urgent*/) {
49 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
50 gpr_mu_lock(&m->mu);
51 if (m->read_buffer.count > 0) {
52 grpc_slice_buffer_swap(&m->read_buffer, slices);
53 grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, GRPC_ERROR_NONE);
54 } else {
55 m->on_read = cb;
56 m->on_read_out = slices;
57 }
58 gpr_mu_unlock(&m->mu);
59 }
60
me_write(grpc_endpoint * ep,grpc_slice_buffer * slices,grpc_closure * cb,void *)61 static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
62 grpc_closure* cb, void* /*arg*/) {
63 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
64 for (size_t i = 0; i < slices->count; i++) {
65 m->on_write(slices->slices[i]);
66 }
67 grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, GRPC_ERROR_NONE);
68 }
69
me_add_to_pollset(grpc_endpoint *,grpc_pollset *)70 static void me_add_to_pollset(grpc_endpoint* /*ep*/,
71 grpc_pollset* /*pollset*/) {}
72
me_add_to_pollset_set(grpc_endpoint *,grpc_pollset_set *)73 static void me_add_to_pollset_set(grpc_endpoint* /*ep*/,
74 grpc_pollset_set* /*pollset*/) {}
75
me_delete_from_pollset_set(grpc_endpoint *,grpc_pollset_set *)76 static void me_delete_from_pollset_set(grpc_endpoint* /*ep*/,
77 grpc_pollset_set* /*pollset*/) {}
78
me_shutdown(grpc_endpoint * ep,grpc_error * why)79 static void me_shutdown(grpc_endpoint* ep, grpc_error* why) {
80 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
81 gpr_mu_lock(&m->mu);
82 if (m->on_read) {
83 grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->on_read,
84 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
85 "Endpoint Shutdown", &why, 1));
86 m->on_read = nullptr;
87 }
88 gpr_mu_unlock(&m->mu);
89 grpc_resource_user_shutdown(m->resource_user);
90 GRPC_ERROR_UNREF(why);
91 }
92
me_destroy(grpc_endpoint * ep)93 static void me_destroy(grpc_endpoint* ep) {
94 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
95 grpc_slice_buffer_destroy(&m->read_buffer);
96 grpc_resource_user_unref(m->resource_user);
97 gpr_mu_destroy(&m->mu);
98 gpr_free(m);
99 }
100
me_get_peer(grpc_endpoint *)101 static char* me_get_peer(grpc_endpoint* /*ep*/) {
102 return gpr_strdup("fake:mock_endpoint");
103 }
104
me_get_resource_user(grpc_endpoint * ep)105 static grpc_resource_user* me_get_resource_user(grpc_endpoint* ep) {
106 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
107 return m->resource_user;
108 }
109
me_get_fd(grpc_endpoint *)110 static int me_get_fd(grpc_endpoint* /*ep*/) { return -1; }
111
me_can_track_err(grpc_endpoint *)112 static bool me_can_track_err(grpc_endpoint* /*ep*/) { return false; }
113
114 static const grpc_endpoint_vtable vtable = {me_read,
115 me_write,
116 me_add_to_pollset,
117 me_add_to_pollset_set,
118 me_delete_from_pollset_set,
119 me_shutdown,
120 me_destroy,
121 me_get_resource_user,
122 me_get_peer,
123 me_get_fd,
124 me_can_track_err};
125
grpc_mock_endpoint_create(void (* on_write)(grpc_slice slice),grpc_resource_quota * resource_quota)126 grpc_endpoint* grpc_mock_endpoint_create(void (*on_write)(grpc_slice slice),
127 grpc_resource_quota* resource_quota) {
128 mock_endpoint* m = static_cast<mock_endpoint*>(gpr_malloc(sizeof(*m)));
129 m->base.vtable = &vtable;
130 std::string name = absl::StrFormat("mock_endpoint_%" PRIxPTR, (intptr_t)m);
131 m->resource_user = grpc_resource_user_create(resource_quota, name.c_str());
132 grpc_slice_buffer_init(&m->read_buffer);
133 gpr_mu_init(&m->mu);
134 m->on_write = on_write;
135 m->on_read = nullptr;
136 return &m->base;
137 }
138
grpc_mock_endpoint_put_read(grpc_endpoint * ep,grpc_slice slice)139 void grpc_mock_endpoint_put_read(grpc_endpoint* ep, grpc_slice slice) {
140 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
141 gpr_mu_lock(&m->mu);
142 if (m->on_read != nullptr) {
143 grpc_slice_buffer_add(m->on_read_out, slice);
144 grpc_core::ExecCtx::Run(DEBUG_LOCATION, m->on_read, GRPC_ERROR_NONE);
145 m->on_read = nullptr;
146 } else {
147 grpc_slice_buffer_add(&m->read_buffer, slice);
148 }
149 gpr_mu_unlock(&m->mu);
150 }
151