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 "test/core/util/mock_endpoint.h"
26
27 #include <inttypes.h>
28
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/string_util.h>
31 #include "src/core/lib/iomgr/sockaddr.h"
32
33 typedef struct mock_endpoint {
34 grpc_endpoint base;
35 gpr_mu mu;
36 void (*on_write)(grpc_slice slice);
37 grpc_slice_buffer read_buffer;
38 grpc_slice_buffer* on_read_out;
39 grpc_closure* on_read;
40 grpc_resource_user* resource_user;
41 } mock_endpoint;
42
me_read(grpc_endpoint * ep,grpc_slice_buffer * slices,grpc_closure * cb)43 static void me_read(grpc_endpoint* ep, grpc_slice_buffer* slices,
44 grpc_closure* cb) {
45 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
46 gpr_mu_lock(&m->mu);
47 if (m->read_buffer.count > 0) {
48 grpc_slice_buffer_swap(&m->read_buffer, slices);
49 GRPC_CLOSURE_SCHED(cb, GRPC_ERROR_NONE);
50 } else {
51 m->on_read = cb;
52 m->on_read_out = slices;
53 }
54 gpr_mu_unlock(&m->mu);
55 }
56
me_write(grpc_endpoint * ep,grpc_slice_buffer * slices,grpc_closure * cb,void * arg)57 static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
58 grpc_closure* cb, void* arg) {
59 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
60 for (size_t i = 0; i < slices->count; i++) {
61 m->on_write(slices->slices[i]);
62 }
63 GRPC_CLOSURE_SCHED(cb, GRPC_ERROR_NONE);
64 }
65
me_add_to_pollset(grpc_endpoint * ep,grpc_pollset * pollset)66 static void me_add_to_pollset(grpc_endpoint* ep, grpc_pollset* pollset) {}
67
me_add_to_pollset_set(grpc_endpoint * ep,grpc_pollset_set * pollset)68 static void me_add_to_pollset_set(grpc_endpoint* ep,
69 grpc_pollset_set* pollset) {}
70
me_delete_from_pollset_set(grpc_endpoint * ep,grpc_pollset_set * pollset)71 static void me_delete_from_pollset_set(grpc_endpoint* ep,
72 grpc_pollset_set* pollset) {}
73
me_shutdown(grpc_endpoint * ep,grpc_error * why)74 static void me_shutdown(grpc_endpoint* ep, grpc_error* why) {
75 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
76 gpr_mu_lock(&m->mu);
77 if (m->on_read) {
78 GRPC_CLOSURE_SCHED(m->on_read,
79 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
80 "Endpoint Shutdown", &why, 1));
81 m->on_read = nullptr;
82 }
83 gpr_mu_unlock(&m->mu);
84 grpc_resource_user_shutdown(m->resource_user);
85 GRPC_ERROR_UNREF(why);
86 }
87
me_destroy(grpc_endpoint * ep)88 static void me_destroy(grpc_endpoint* ep) {
89 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
90 grpc_slice_buffer_destroy(&m->read_buffer);
91 grpc_resource_user_unref(m->resource_user);
92 gpr_free(m);
93 }
94
me_get_peer(grpc_endpoint * ep)95 static char* me_get_peer(grpc_endpoint* ep) {
96 return gpr_strdup("fake:mock_endpoint");
97 }
98
me_get_resource_user(grpc_endpoint * ep)99 static grpc_resource_user* me_get_resource_user(grpc_endpoint* ep) {
100 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
101 return m->resource_user;
102 }
103
me_get_fd(grpc_endpoint * ep)104 static int me_get_fd(grpc_endpoint* ep) { return -1; }
105
106 static const grpc_endpoint_vtable vtable = {
107 me_read,
108 me_write,
109 me_add_to_pollset,
110 me_add_to_pollset_set,
111 me_delete_from_pollset_set,
112 me_shutdown,
113 me_destroy,
114 me_get_resource_user,
115 me_get_peer,
116 me_get_fd,
117 };
118
grpc_mock_endpoint_create(void (* on_write)(grpc_slice slice),grpc_resource_quota * resource_quota)119 grpc_endpoint* grpc_mock_endpoint_create(void (*on_write)(grpc_slice slice),
120 grpc_resource_quota* resource_quota) {
121 mock_endpoint* m = static_cast<mock_endpoint*>(gpr_malloc(sizeof(*m)));
122 m->base.vtable = &vtable;
123 char* name;
124 gpr_asprintf(&name, "mock_endpoint_%" PRIxPTR, (intptr_t)m);
125 m->resource_user = grpc_resource_user_create(resource_quota, name);
126 gpr_free(name);
127 grpc_slice_buffer_init(&m->read_buffer);
128 gpr_mu_init(&m->mu);
129 m->on_write = on_write;
130 m->on_read = nullptr;
131 return &m->base;
132 }
133
grpc_mock_endpoint_put_read(grpc_endpoint * ep,grpc_slice slice)134 void grpc_mock_endpoint_put_read(grpc_endpoint* ep, grpc_slice slice) {
135 mock_endpoint* m = reinterpret_cast<mock_endpoint*>(ep);
136 gpr_mu_lock(&m->mu);
137 if (m->on_read != nullptr) {
138 grpc_slice_buffer_add(m->on_read_out, slice);
139 GRPC_CLOSURE_SCHED(m->on_read, GRPC_ERROR_NONE);
140 m->on_read = nullptr;
141 } else {
142 grpc_slice_buffer_add(&m->read_buffer, slice);
143 }
144 gpr_mu_unlock(&m->mu);
145 }
146