1 /*
2 Copyright (c) 2013 Insollo Entertainment, LLC. All rights reserved.
3 Copyright 2016 Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
4 Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
5 Copyright 2018 Capitar IT Group BV <info@capitar.com>
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 DEALINGS IN THE SOFTWARE.
24 */
25
26 // Note: This file started life in nanomsg. We have copied it, and adjusted
27 // it for validating the compatibility features of nanomsg. As much as
28 // possible we want to run tests from the nanomsg test suite unmodified.
29
30 #include <assert.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <nng/compat/nanomsg/nn.h>
36 #include "compat_testutil.h"
37
38 int test_socket_impl(char *file, int line, int family, int protocol);
39 int test_connect_impl(char *file, int line, int sock, char *address);
40 int test_bind_impl(char *file, int line, int sock, char *address);
41 void test_close_impl(char *file, int line, int sock);
42 void test_send_impl(char *file, int line, int sock, char *data);
43 void test_recv_impl(char *file, int line, int sock, char *data);
44 void test_drop_impl(char *file, int line, int sock, int err);
45 int test_setsockopt_impl(char *file, int line, int sock, int level, int option,
46 const void *optval, size_t optlen);
47
48 int
test_socket_impl(char * file,int line,int family,int protocol)49 test_socket_impl(char *file, int line, int family, int protocol)
50 {
51 int sock;
52
53 sock = nn_socket(family, protocol);
54 if (sock == -1) {
55 fprintf(stderr, "Failed create socket: %s [%d] (%s:%d)\n",
56 nn_err_strerror(errno), (int) errno, file, line);
57 nn_err_abort();
58 }
59
60 return (sock);
61 }
62
63 int
test_connect_impl(char * file,int line,int sock,char * address)64 test_connect_impl(char *file, int line, int sock, char *address)
65 {
66 int rc;
67
68 rc = nn_connect(sock, address);
69 if (rc < 0) {
70 fprintf(stderr, "Failed connect to \"%s\": %s [%d] (%s:%d)\n",
71 address, nn_err_strerror(errno), (int) errno, file, line);
72 nn_err_abort();
73 }
74 return (rc);
75 }
76
77 int
test_bind_impl(char * file,int line,int sock,char * address)78 test_bind_impl(char *file, int line, int sock, char *address)
79 {
80 int rc;
81
82 rc = nn_bind(sock, address);
83 if (rc < 0) {
84 fprintf(stderr, "Failed bind to \"%s\": %s [%d] (%s:%d)\n",
85 address, nn_err_strerror(errno), (int) errno, file, line);
86 nn_err_abort();
87 }
88 return (rc);
89 }
90
91 int
test_setsockopt_impl(char * file,int line,int sock,int level,int option,const void * optval,size_t optlen)92 test_setsockopt_impl(char *file, int line, int sock, int level, int option,
93 const void *optval, size_t optlen)
94 {
95 int rc;
96
97 rc = nn_setsockopt(sock, level, option, optval, optlen);
98 if (rc < 0) {
99 fprintf(stderr, "Failed set option \"%d\": %s [%d] (%s:%d)\n",
100 option, nn_err_strerror(errno), (int) errno, file, line);
101 nn_err_abort();
102 }
103 return rc;
104 }
105
106 void
test_close_impl(char * file,int line,int sock)107 test_close_impl(char *file, int line, int sock)
108 {
109 int rc;
110
111 rc = nn_close(sock);
112 if ((rc != 0) && (errno != EBADF && errno != ETERM)) {
113 fprintf(stderr, "Failed to close socket: %s [%d] (%s:%d)\n",
114 nn_err_strerror(errno), (int) errno, file, line);
115 nn_err_abort();
116 }
117 }
118
119 void
test_send_impl(char * file,int line,int sock,char * data)120 test_send_impl(char *file, int line, int sock, char *data)
121 {
122 size_t data_len;
123 int rc;
124
125 data_len = strlen(data);
126
127 rc = nn_send(sock, data, data_len, 0);
128 if (rc < 0) {
129 fprintf(stderr, "Failed to send: %s [%d] (%s:%d)\n",
130 nn_err_strerror(errno), (int) errno, file, line);
131 nn_err_abort();
132 }
133 if (rc != (int) data_len) {
134 fprintf(stderr,
135 "Data to send is truncated: %d != %d (%s:%d)\n", rc,
136 (int) data_len, file, line);
137 nn_err_abort();
138 }
139 }
140
141 void
test_recv_impl(char * file,int line,int sock,char * data)142 test_recv_impl(char *file, int line, int sock, char *data)
143 {
144 size_t data_len;
145 int rc;
146 char * buf;
147
148 data_len = strlen(data);
149 /* We allocate plus one byte so that we are sure that message received
150 has correct length and not truncated */
151 buf = malloc(data_len + 1);
152 alloc_assert(buf);
153
154 rc = nn_recv(sock, buf, data_len + 1, 0);
155 if (rc < 0) {
156 fprintf(stderr, "Failed to recv: %s [%d] (%s:%d)\n",
157 nn_err_strerror(errno), (int) errno, file, line);
158 nn_err_abort();
159 }
160 if (rc != (int) data_len) {
161 fprintf(stderr,
162 "Received data has wrong length: %d != %d (%s:%d)\n", rc,
163 (int) data_len, file, line);
164 nn_err_abort();
165 }
166 if (memcmp(data, buf, data_len) != 0) {
167 /* We don't print the data as it may have binary garbage */
168 fprintf(
169 stderr, "Received data is wrong (%s:%d)\n", file, line);
170 nn_err_abort();
171 }
172
173 free(buf);
174 }
175
176 void
test_drop_impl(char * file,int line,int sock,int err)177 test_drop_impl(char *file, int line, int sock, int err)
178 {
179 int rc;
180 char buf[1024];
181
182 rc = nn_recv(sock, buf, sizeof(buf), 0);
183 if (rc < 0 && err != errno) {
184 fprintf(stderr,
185 "Got wrong err to recv: %s [%d != %d] (%s:%d)\n",
186 nn_err_strerror(errno), (int) errno, err, file, line);
187 nn_err_abort();
188 } else if (rc >= 0) {
189 fprintf(stderr, "Did not drop message: [%d bytes] (%s:%d)\n",
190 rc, file, line);
191 nn_err_abort();
192 }
193 }
194
195 int
get_test_port(int argc,const char * argv[])196 get_test_port(int argc, const char *argv[])
197 {
198 return (atoi(argc < 2 ? "5555" : argv[1]));
199 }
200
201 void
test_addr_from(char * out,const char * proto,const char * ip,int port)202 test_addr_from(char *out, const char *proto, const char *ip, int port)
203 {
204 sprintf(out, "%s://%s:%d", proto, ip, port);
205 }
206
207 extern int nng_thread_create(void **, void (*)(void *), void *);
208
209 int
nn_thread_init(struct nn_thread * thr,void (* func)(void *),void * arg)210 nn_thread_init(struct nn_thread *thr, void (*func)(void *), void *arg)
211 {
212 return (nng_thread_create(&thr->thr, func, arg));
213 }
214
215 extern void nng_thread_destroy(void *);
216
217 void
nn_thread_term(struct nn_thread * thr)218 nn_thread_term(struct nn_thread *thr)
219 {
220 nng_thread_destroy(thr->thr);
221 }
222
223 extern void nng_msleep(int32_t);
224
225 void
nn_sleep(int ms)226 nn_sleep(int ms)
227 {
228 nng_msleep(ms);
229 }
230