From 7df0822d3ed58ee73918cac576c0b07363e84425 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Mon, 23 Jan 2017 22:49:57 -0800 Subject: Added a bunch more compatibility stuff. I implemented the reqrep compatibility test, which uncovered a few semantic issues I had in the REQ/REP protocol, which I've fixed. There are still missing things. and at least one portion of the req/rep test suite cannot be enabled until I add tuning of the reconnect timeout, which is currently way too long (1 sec) for the test suite to work. --- tests/compat_reqrep.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 tests/compat_reqrep.c (limited to 'tests/compat_reqrep.c') diff --git a/tests/compat_reqrep.c b/tests/compat_reqrep.c new file mode 100644 index 00000000..a418b8d9 --- /dev/null +++ b/tests/compat_reqrep.c @@ -0,0 +1,194 @@ +/* + Copyright (c) 2012 Martin Sustrik All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom + the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +#include "nng_compat.h" + +#include "compat_testutil.h" + +#define SOCKET_ADDRESS "inproc://test" + +extern void nng_usleep(uint64_t); + +int main () +{ + int rc; + int rep1; + int rep2; + int req1; + int req2; + int resend_ivl; + char buf [7]; + int timeo; + + /* Test req/rep with full socket types. */ + rep1 = test_socket (AF_SP, NN_REP); + test_bind (rep1, SOCKET_ADDRESS); + req1 = test_socket (AF_SP, NN_REQ); + test_connect (req1, SOCKET_ADDRESS); + req2 = test_socket (AF_SP, NN_REQ); + test_connect (req2, SOCKET_ADDRESS); + + /* Check invalid sequence of sends and recvs. */ + rc = nn_send (rep1, "ABC", 3, 0); + nn_assert (rc == -1 && nn_errno () == EFSM); + rc = nn_recv (req1, buf, sizeof (buf), 0); + nn_assert (rc == -1 && nn_errno () == EFSM); + + /* Check fair queueing the requests. */ + test_send (req2, "ABC"); + test_recv (rep1, "ABC"); + test_send (rep1, "ABC"); + test_recv (req2, "ABC"); + + test_send (req1, "ABC"); + test_recv (rep1, "ABC"); + test_send (rep1, "ABC"); + test_recv (req1, "ABC"); + + test_close (rep1); + test_close (req1); + test_close (req2); + + /* Check load-balancing of requests. */ + req1 = test_socket (AF_SP, NN_REQ); + test_bind (req1, SOCKET_ADDRESS); + + rep1 = test_socket (AF_SP, NN_REP); + test_connect (rep1, SOCKET_ADDRESS); + + nng_usleep(10000); // ensure rep1 binds before rep2 + + rep2 = test_socket (AF_SP, NN_REP); + test_connect (rep2, SOCKET_ADDRESS); + + timeo = 500; + test_setsockopt (req1, NN_SOL_SOCKET, NN_RCVTIMEO, &timeo, sizeof (timeo)); + test_setsockopt (rep1, NN_SOL_SOCKET, NN_RCVTIMEO, &timeo, sizeof (timeo)); + test_setsockopt (rep2, NN_SOL_SOCKET, NN_RCVTIMEO, &timeo, sizeof (timeo)); + + // Give time for connections to settle -- required for LB stuff. + nng_usleep(100000); + + test_send (req1, "ABC"); + test_recv (rep1, "ABC"); + test_send (rep1, "ABC"); + test_recv (req1, "ABC"); + + test_send (req1, "ABC"); + test_recv (rep2, "ABC"); + test_send (rep2, "ABC"); + test_recv (req1, "ABC"); + + test_close (rep2); + test_close (rep1); + test_close (req1); + + /* Test re-sending of the request. */ + rep1 = test_socket (AF_SP, NN_REP); + test_bind (rep1, SOCKET_ADDRESS); + req1 = test_socket (AF_SP, NN_REQ); + test_connect (req1, SOCKET_ADDRESS); + resend_ivl = 100; + rc = nn_setsockopt (req1, NN_REQ, NN_REQ_RESEND_IVL, + &resend_ivl, sizeof (resend_ivl)); + errno_assert (rc == 0); + + test_send (req1, "ABC"); + test_recv (rep1, "ABC"); + /* The following waits for request to be resent */ + test_recv (rep1, "ABC"); + + test_close (req1); + test_close (rep1); + + +#if 0 // The default reconnect interval is waaay to large for this to pass. + /* Check sending a request when the peer is not available. (It should + be sent immediatelly when the peer comes online rather than relying + on the resend algorithm. */ + req1 = test_socket (AF_SP, NN_REQ); + timeo = 10; + rc = nn_setsockopt (req1, NN_SOL_SOCKET, NN_RECONNECT_IVL, + &timeo, sizeof (timeo)); + test_send (req1, "ABC"); + test_connect (req1, SOCKET_ADDRESS); + + rep1 = test_socket (AF_SP, NN_REP); + test_bind (rep1, SOCKET_ADDRESS); + timeo = 500; + rc = nn_setsockopt (rep1, NN_SOL_SOCKET, NN_RCVTIMEO, + &timeo, sizeof (timeo)); + printf("RC = %d errno %d (%s)\n", rc, errno, strerror(errno)); + errno_assert (rc == 0); + test_recv (rep1, "ABC"); + + test_close (req1); + test_close (rep1); +#endif + + /* Check removing socket request sent to (It should + be sent immediatelly to other peer rather than relying + on the resend algorithm). */ + req1 = test_socket (AF_SP, NN_REQ); + test_bind (req1, SOCKET_ADDRESS); + rep1 = test_socket (AF_SP, NN_REP); + test_connect (rep1, SOCKET_ADDRESS); + rep2 = test_socket (AF_SP, NN_REP); + nng_usleep(10000); // give time for rep1 to connect + test_connect (rep2, SOCKET_ADDRESS); + + timeo = 500; // Was 200, but Windows occasionally fails at that rate. + test_setsockopt (rep1, NN_SOL_SOCKET, NN_RCVTIMEO, &timeo, sizeof (timeo)); + test_setsockopt (rep2, NN_SOL_SOCKET, NN_RCVTIMEO, &timeo, sizeof (timeo)); + + test_send (req1, "ABC"); + /* We got request through rep1 */ + test_recv (rep1, "ABC"); + /* But instead replying we simulate crash */ + test_close (rep1); + /* The rep2 should get request immediately */ + test_recv (rep2, "ABC"); + /* Let's check it's delivered well */ + test_send (rep2, "REPLY"); + test_recv (req1, "REPLY"); + + test_close (req1); + test_close (rep2); + + /* Test cancelling delayed request */ + + req1 = test_socket (AF_SP, NN_REQ); + test_connect (req1, SOCKET_ADDRESS); + test_send (req1, "ABC"); + test_send (req1, "DEF"); + + rep1 = test_socket (AF_SP, NN_REP); + test_bind (rep1, SOCKET_ADDRESS); + timeo = 100; + test_recv (rep1, "DEF"); + + test_close (req1); + test_close (rep1); + + return 0; +} + -- cgit v1.2.3-70-g09d2