LCOV - code coverage report
Current view: directory - src/shared/imc - sigpipe_test.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 521 318 61.0 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : // Test that SIGPIPE is not raised when using NaClSendDatagram or
       8                 : // NaClSendDatagramTo when the peer has been closed for various
       9                 : // flavors of sockets.
      10                 : 
      11                 : #include <stdio.h>
      12                 : #include <sys/types.h>
      13                 : #include <stdlib.h>
      14                 : #include <string.h>
      15                 : #include <errno.h>
      16                 : 
      17                 : #include <vector>
      18                 : 
      19                 : #include "native_client/src/include/checked_cast.h"
      20                 : #include "native_client/src/include/nacl_macros.h"
      21                 : #include "native_client/src/include/nacl_string.h"
      22                 : #include "native_client/src/include/portability.h"
      23                 : #include "native_client/src/include/portability_process.h"
      24                 : #include "native_client/src/shared/imc/nacl_imc_c.h"
      25                 : #include "native_client/src/shared/platform/nacl_log.h"
      26                 : #include "native_client/src/shared/platform/nacl_sync.h"
      27                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      28                 : #include "native_client/src/shared/platform/nacl_threads.h"
      29                 : 
      30                 : #if NACL_WINDOWS
      31                 : #define PRIHANDLE "p"
      32                 : #else
      33                 : #define PRIHANDLE "d"
      34                 : #endif
      35                 : 
      36                 : namespace {
      37                 : 
      38                 : const bool kPlatformUsesBoundSockets = NACL_WINDOWS;
      39                 : 
      40                 : bool gSleepBeforeReceive(false);
      41               2 : std::vector<int> gTestSequence;
      42                 : 
      43                 : /*
      44                 :  * PickRandomSocketAddress: choses a random socket address.
      45                 :  *
      46                 :  * NB: this uses rand() and thus is not thread-safe.  However, this is
      47                 :  * only used in the main thread.
      48                 :  */
      49                 : void PickRandomSocketAddress(NaClSocketAddress *addr) {
      50                 :   static const char alphabet[] =
      51                 :       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      52                 : #if !NACL_WINDOWS
      53                 :       "abcdefghijklmnopqrstuvwxyz"
      54                 : #endif
      55                 :       "0123456789";
      56                 :   static bool seeded = false;  // not thread safe
      57                 : 
      58                 :   if (!(sizeof alphabet - 1 == 36 ||
      59                 :         sizeof alphabet - 1 == 62)) {
      60                 :     printf("Alphabet size error\n");
      61                 :     abort();
      62                 :   }
      63                 :   if (!seeded) {
      64                 :     srand(GETPID());
      65                 :     seeded = 1;
      66                 :   }
      67                 :   for (int i = 0; i < NACL_PATH_MAX - 1; ++i) {
      68                 :     addr->path[i] = alphabet[rand() % (sizeof alphabet - 1)];
      69                 :   }
      70                 :   addr->path[NACL_PATH_MAX - 1] = '\0';
      71                 :   printf("PickRandomSocketAddress: returning %s\n", addr->path);
      72                 : }
      73                 : 
      74                 : 
      75               0 : void MyPerror(nacl::string s) {
      76               0 :   char error_msg[512];
      77               0 :   int err = errno;
      78               0 :   if (0 == NaClGetLastErrorString(error_msg, sizeof error_msg)) {
      79               0 :     printf("%s: %s\n", s.c_str(), error_msg);
      80               0 :   } else {
      81               0 :     printf("%s: errno %d\n", s.c_str(), err);
      82                 :   }
      83               0 :   errno = err;
      84               0 : }
      85                 : 
      86                 : 
      87               0 : void SplitString(std::vector<nacl::string> *result, nacl::string s, char sep) {
      88               0 :   nacl::string::size_type start;
      89               0 :   nacl::string::size_type sep_pos;
      90                 : 
      91               0 :   for (start = 0;
      92               0 :        nacl::string::npos != (sep_pos = s.find(sep, start));
      93               0 :        start = sep_pos + 1) {
      94               0 :     result->push_back(s.substr(start, sep_pos - start));
      95               0 :   }
      96               0 :   if (start < s.length()) {
      97               0 :     result->push_back(s.substr(start));
      98               0 :   }
      99               0 : }
     100                 : 
     101               0 : void ApplyInt(std::vector<int> *result, std::vector<nacl::string> const &vs) {
     102               0 :   for (std::vector<nacl::string>::const_iterator it = vs.begin();
     103               0 :        vs.end() != it;
     104               0 :        ++it) {
     105               0 :     result->push_back(strtol((*it).c_str(), static_cast<char **>(0), 0));
     106               0 :   }
     107               0 : }
     108                 : 
     109                 : struct TestState {
     110                 :   NaClSocketAddress cli_addr;
     111                 :   NaClSocketAddress srv_addr;
     112                 :   NaClHandle cli_sock;
     113                 :   NaClHandle srv_sock;
     114                 :   NaClHandle pair[2];
     115                 : 
     116                 :   bool new_sock_only;  // false to run only the single thread/socket
     117                 :                        // tests, true to do the complement
     118                 :   int repetitions;
     119                 :   int outer_rep;
     120                 : 
     121                 :   std::vector<int> *test_sequence;
     122                 : 
     123                 :   NaClMutex mu;
     124                 :   NaClCondVar cv;
     125                 :   int errors;
     126                 :   int cur_test;
     127                 : 
     128                 :   int msg_len;
     129                 :   char msg_buffer[512];
     130                 : 
     131                 :   TestState(std::vector<int> *, bool nso, int reps, int outer_rep);
     132                 :   int Init();
     133                 :   ~TestState();
     134                 : };
     135                 : 
     136             402 : TestState::TestState(std::vector<int> *seqp, bool nso, int reps,
     137             402 :                      int out_rep)
     138                 :     : cli_sock(NACL_INVALID_HANDLE),
     139                 :       srv_sock(NACL_INVALID_HANDLE),
     140                 :       new_sock_only(nso),
     141                 :       repetitions(reps),
     142                 :       outer_rep(out_rep),
     143                 :       test_sequence(seqp),
     144                 :       errors(-1),
     145             201 :       cur_test(-1) {
     146             201 :   pair[0] = NACL_INVALID_HANDLE;
     147             201 :   pair[1] = NACL_INVALID_HANDLE;
     148             201 :   NaClXMutexCtor(&mu);
     149             201 :   NaClXCondVarCtor(&cv);
     150             402 : }
     151                 : 
     152                 : int TestState::Init() {
     153                 :   if (kPlatformUsesBoundSockets) {
     154                 :     PickRandomSocketAddress(&cli_addr);
     155                 :     cli_sock = NaClBoundSocket(&cli_addr);
     156                 :     if (NACL_INVALID_HANDLE == cli_sock) {
     157                 :       MyPerror("BoundSocket");
     158                 :       printf("ERROR: No client socket\n");
     159                 :       return 1;
     160                 :     }
     161                 :     PickRandomSocketAddress(&srv_addr);
     162                 :     srv_sock = NaClBoundSocket(&srv_addr);
     163                 :     if (NACL_INVALID_HANDLE == srv_sock) {
     164                 :       MyPerror("BoundSocket");
     165                 :       printf("ERROR: No server socket\n");
     166                 :       return 1;
     167                 :     }
     168                 :   }
     169                 : 
     170             201 :   if (-1 == NaClSocketPair(pair)) {
     171               0 :     MyPerror("SocketPair");
     172               0 :     printf("ERROR: no socket pair\n");
     173               0 :     return 1;
     174                 :   }
     175                 : 
     176             201 :   strncpy(msg_buffer, "hello world\n", sizeof msg_buffer);
     177             201 :   msg_buffer[sizeof msg_buffer - 1] = '\0';
     178             201 :   msg_len = nacl::assert_cast<int>(strlen(msg_buffer));
     179                 : 
     180             201 :   printf("cli_sock %" PRIHANDLE ", srv_sock %" PRIHANDLE ","
     181                 :          "pair[0] %" PRIHANDLE ", pair[1] %" PRIHANDLE "\n",
     182                 :          cli_sock, srv_sock, pair[0], pair[1]);
     183                 : 
     184             201 :   return 0;
     185             201 : }
     186                 : 
     187                 : 
     188             201 : TestState::~TestState() {
     189             201 :   if (NACL_INVALID_HANDLE != cli_sock) {
     190               0 :     printf("NaClClose(%" PRIHANDLE ")\n", cli_sock);
     191               0 :     (void) NaClClose(cli_sock);
     192               0 :   }
     193             201 :   if (NACL_INVALID_HANDLE != srv_sock) {
     194               0 :     printf("NaClClose(%" PRIHANDLE ")\n", srv_sock);
     195               0 :     (void) NaClClose(srv_sock);
     196               0 :   }
     197            1206 :   for (int i = 0; i < 2; ++i) {
     198             402 :     if (NACL_INVALID_HANDLE != pair[i]) {
     199             401 :       printf("NaClClose(%" PRIHANDLE ")\n", pair[i]);
     200             401 :       (void) NaClClose(pair[i]);
     201             401 :     }
     202             402 :   }
     203             201 :   (void) NaClCondVarDtor(&cv);
     204             201 :   (void) NaClMutexDtor(&mu);
     205             402 : }
     206                 : 
     207                 : 
     208             200 : int SendDescriptor(TestState *tsp, int mode) {
     209             200 :   int errors(0);
     210             200 :   NaClMessageHeader hdr;
     211             200 :   NaClHandle xfer[2];
     212             200 :   hdr.iov = NULL;
     213             200 :   hdr.iov_length = 0;
     214             200 :   hdr.handle_count = 1;
     215             200 :   hdr.handles = xfer;
     216                 :       // &tsp->pair[0];   // bug w/ OSX, kernel oops
     217                 :       // &tsp->cli_sock;  // bug w/ bound sockets, eager NaClClose unlink
     218             200 :   if (-1 == NaClSocketPair(xfer)) {  // an otherwise unused NaClHandle.
     219               0 :     ++errors;
     220               0 :     printf("SendDescriptr: could not create (unused) NaClSocketPair\n");
     221               0 :     return errors;
     222                 :   }
     223             200 :   if (-1 == NaClClose(xfer[1])) {
     224               0 :     ++errors;
     225               0 :     printf("SendDescriptor: could not NaClClose the unused"
     226                 :            " end of SocketPair\n");
     227               0 :     return errors;
     228                 :   }
     229             200 :   hdr.flags = 0;
     230             200 :   printf("Sending a descriptor, mode %d\n", mode);
     231             200 :   int result(-1);
     232             200 :   nacl::string op;
     233             200 :   switch (mode) {
     234                 :     case 0: {
     235               0 :       op = "SendDatagramTo";
     236               0 :       result = NaClSendDatagramTo(&hdr, 0, &tsp->srv_addr);
     237               0 :       break;
     238                 :     }
     239                 :     case 1: {
     240             200 :       op = "SendDatagram";
     241             400 :       result = NaClSendDatagram(tsp->pair[1], &hdr, 0);
     242             200 :       break;
     243                 :     }
     244                 :     default: {
     245               0 :       printf("ERROR: illegal test mode\n");
     246               0 :       ++errors;
     247               0 :       break;
     248                 :     }
     249                 :   }
     250             200 :   if (-1 == result) {
     251               0 :     MyPerror("SendDescriptor, " + op);
     252               0 :     printf("ERROR: SendDescriptor: %s failed.\n", op.c_str());
     253               0 :     ++errors;
     254             200 :   } else if (0 != result) {
     255               0 :     printf("ERROR: SendDescriptor: %s returned %d, expected 0.\n",
     256               0 :            op.c_str(),
     257                 :            result);
     258               0 :     ++errors;
     259               0 :   } else {
     260             200 :     printf("SendDescriptor: OK\n");
     261                 :   }
     262             200 :   NaClClose(xfer[0]);
     263             200 :   return errors;
     264             400 : }
     265                 : 
     266                 : 
     267             200 : int ReceiveDescriptor(TestState *tsp, int mode) {
     268             200 :   int errors(0);
     269             200 :   NaClMessageHeader hdr;
     270             200 :   NaClIOVec vec;
     271             200 :   char buffer[512];
     272             200 :   NaClHandle handle[8];
     273             200 :   int nbytes(-1);
     274             200 :   printf("ReceiverThread: receive a handle, mode %d\n", mode);
     275             200 :   vec.base = buffer;
     276             200 :   vec.length = sizeof buffer;
     277             200 :   hdr.iov = &vec;
     278             200 :   hdr.iov_length = 1;
     279             200 :   hdr.handles = handle;
     280             200 :   hdr.handle_count = NACL_ARRAY_SIZE(handle);
     281             200 :   hdr.flags = 0;
     282             200 :   switch (mode) {
     283                 :     case 0: {
     284               0 :       nbytes = NaClReceiveDatagram(tsp->srv_sock, &hdr, 0);
     285               0 :       break;
     286                 :     }
     287                 :     case 1: {
     288             200 :       nbytes = NaClReceiveDatagram(tsp->pair[0], &hdr, 0);
     289             200 :       break;
     290                 :     }
     291                 :     default: {
     292               0 :       printf("ERROR: illegal test mode\n");
     293               0 :       ++errors;
     294               0 :       break;
     295                 :     }
     296                 :   }
     297             200 :   if (-1 == nbytes) {
     298               0 :     MyPerror("ReceiverThread, ReceiveDatagram");
     299               0 :     printf("ERROR: ReceiveDatagram failed, did not receive any handles.\n");
     300               0 :     ++errors;
     301               0 :   } else {
     302             200 :     if (0 != nbytes) {
     303               0 :       printf("ERROR: ReceiveDatagram should have received zero bytes"
     304                 :              " of data, got %d.\n", nbytes);
     305               0 :       printf("ERROR: received \"%.*s\"\n", nbytes, buffer);
     306               0 :       ++errors;
     307               0 :     }
     308             200 :     if (1 != hdr.handle_count) {
     309               0 :       printf("ERROR: Did not receive a single handle.\n");
     310               0 :       ++errors;
     311               0 :     }
     312                 : 
     313             200 :     if (NACL_ARRAY_SIZE(handle) < hdr.handle_count) {
     314               0 :       printf("ERROR: Too many handles: %" NACL_PRIu32, hdr.handle_count);
     315               0 :       return ++errors;
     316                 :     }
     317             800 :     for (size_t i = 0; i < hdr.handle_count; ++i) {
     318             200 :       if (hdr.handles[i] == tsp->srv_sock) {
     319               0 :         printf("ERROR: received handle is same as srv_sock!\n");
     320               0 :         ++errors;
     321               0 :         continue;
     322                 :       }
     323             200 :       if (hdr.handles[i] == tsp->cli_sock) {
     324               0 :         printf("ERROR: received handle is same as cli_sock!\n");
     325               0 :         ++errors;
     326               0 :         continue;
     327                 :       }
     328             200 :       if (hdr.handles[i] == tsp->pair[0]) {
     329               0 :         printf("ERROR: received handle is same as pair[0]!\n");
     330               0 :         ++errors;
     331               0 :         continue;
     332                 :       }
     333             200 :       if (hdr.handles[i] == tsp->pair[1]) {
     334               0 :         printf("ERROR: received handle is same as pair[1]!\n");
     335               0 :         ++errors;
     336               0 :         continue;
     337                 :       }
     338             200 :       printf("close(%" PRIHANDLE ")\n", hdr.handles[i]);
     339             200 :       if (-1 == NaClClose(hdr.handles[i])) {
     340               0 :         MyPerror("ReceiverThread, Close");
     341               0 :         printf("ERROR: Close on received handle failed\n");
     342               0 :         ++errors;
     343               0 :       }
     344             200 :     }
     345                 :   }
     346             200 :   if (0 == errors) {
     347             200 :     printf("ReceiverThread, receive handle: OK\n");
     348             200 :   } else {
     349               0 :     printf("ReceiverThread, receive handle: FAILED\n");
     350                 :   }
     351             200 :   return errors;
     352             200 : }
     353                 : 
     354                 : 
     355             200 : int SendData(TestState *tsp, int mode) {
     356             200 :   int errors(0);
     357             200 :   NaClMessageHeader hdr;
     358             200 :   NaClIOVec vec;
     359             200 :   int nbytes(-1);
     360             200 :   vec.base = tsp->msg_buffer;
     361             200 :   vec.length = tsp->msg_len;
     362             200 :   hdr.iov = &vec;
     363             200 :   hdr.iov_length = 1;
     364             200 :   hdr.handle_count = 0;
     365             200 :   hdr.flags = 0;
     366             200 :   nacl::string op;
     367                 : 
     368             200 :   printf("Sending data, mode %d\n", mode);
     369             200 :   switch (mode) {
     370                 :     case 0: {
     371               0 :       op = "SendDatagramTo";
     372               0 :       nbytes = NaClSendDatagramTo(&hdr, 0, &tsp->srv_addr);
     373               0 :       break;
     374                 :     }
     375                 :     case 1: {
     376             200 :       op = "SendDatagram";
     377             400 :       nbytes = NaClSendDatagram(tsp->pair[1], &hdr, 0);
     378             200 :     } break;
     379                 :     default: {
     380               0 :       printf("ERROR: Illegal test mode\n");
     381               0 :       ++errors;
     382               0 :       break;
     383                 :     }
     384                 :   }
     385             200 :   if (-1 == nbytes) {
     386               0 :     MyPerror("send thread " + op);
     387               0 :     printf("Send thread, %s failed\n", op.c_str());
     388               0 :   }
     389             200 :   if (nbytes != tsp->msg_len) {
     390               0 :     printf("ERROR: send thread, send data: %s did not send"
     391                 :            " all bytes.  Tried to send %d, but only %d actually sent.\n",
     392               0 :            op.c_str(), tsp->msg_len, nbytes);
     393               0 :     if (0 == mode) {
     394               0 :       printf("sock addr %s\n", tsp->srv_addr.path);
     395               0 :     }
     396               0 :     ++errors;
     397               0 :   } else {
     398             200 :     printf("Send thread, send data: OK\n");
     399                 :   }
     400             200 :   return errors;
     401             200 : }
     402                 : 
     403             200 : int ReceiveData(TestState *tsp, int mode) {
     404             200 :   int errors(0);
     405             200 :   NaClMessageHeader hdr;
     406             200 :   NaClIOVec vec;
     407             200 :   NaClHandle handle[8];
     408             200 :   int nbytes(-1);
     409             200 :   printf("ReceiverThread: receive data, mode %d\n", mode);
     410             200 :   char recv_buf[1024];
     411             200 :   memset(recv_buf, 0, sizeof recv_buf);
     412             200 :   vec.base = recv_buf;
     413             200 :   vec.length = sizeof recv_buf;
     414             200 :   hdr.iov = &vec;
     415             200 :   hdr.iov_length = 1;
     416             200 :   hdr.handles = handle;
     417             200 :   hdr.handle_count = NACL_ARRAY_SIZE(handle);
     418             200 :   hdr.flags = 0;
     419             200 :   switch (mode) {
     420                 :     case 0: {
     421               0 :       nbytes = NaClReceiveDatagram(tsp->srv_sock, &hdr, 0);
     422               0 :       break;
     423                 :     }
     424                 :     case 1: {
     425             200 :       nbytes = NaClReceiveDatagram(tsp->pair[0], &hdr, 0);
     426             200 :       break;
     427                 :     }
     428                 :     default: {
     429               0 :       printf("ERROR: illegal test mode\n");
     430               0 :       ++errors;
     431               0 :       break;
     432                 :     }
     433                 :   }
     434             200 :   if (-1 == nbytes) {
     435               0 :     MyPerror("ReceiverThread, ReceiveDatagram");
     436               0 :     printf("ERROR: ReceiveDatagram failed, did not receive anything.\n");
     437               0 :     ++errors;
     438               0 :   } else {
     439             200 :     if (nbytes != tsp->msg_len) {
     440               0 :       MyPerror("ReceiveDatagram");
     441               0 :       printf("ERROR: ReceiveDatagram did not receive all bytes."
     442                 :              "  Buffer %" NACL_PRIuS ", expected %d, got %d bytes.\n",
     443                 :              sizeof recv_buf, tsp->msg_len, nbytes);
     444               0 :       ++errors;
     445               0 :     }
     446             200 :     if (0 != strcmp(recv_buf, tsp->msg_buffer)) {
     447               0 :       printf("Received %s, sent %s\n", recv_buf, tsp->msg_buffer);
     448               0 :       ++errors;
     449               0 :     }
     450             200 :     if (0 != hdr.handle_count) {
     451               0 :       printf("ERROR: Did not receive zero handles.\n");
     452               0 :       ++errors;
     453               0 :     }
     454             200 :     if (NACL_ARRAY_SIZE(handle) < hdr.handle_count) {
     455               0 :       printf("Too many handles: %" NACL_PRIu32, hdr.handle_count);
     456               0 :       return ++errors;
     457                 :     }
     458             400 :     for (size_t i = 0; i < hdr.handle_count; ++i) {
     459               0 :       if (hdr.handles[i] == tsp->srv_sock) {
     460               0 :         printf("ERROR: received handle is same as srv_sock!\n");
     461               0 :         ++errors;
     462               0 :         continue;
     463                 :       }
     464               0 :       if (hdr.handles[i] == tsp->cli_sock) {
     465               0 :         printf("ERROR: received handle is same as cli_sock!\n");
     466               0 :         ++errors;
     467               0 :         continue;
     468                 :       }
     469               0 :       if (hdr.handles[i] == tsp->pair[0]) {
     470               0 :         printf("ERROR: received handle is same as pair[0]!\n");
     471               0 :         ++errors;
     472               0 :         continue;
     473                 :       }
     474               0 :       if (hdr.handles[i] == tsp->pair[1]) {
     475               0 :         printf("ERROR: received handle is same as pair[1]!\n");
     476               0 :         ++errors;
     477               0 :         continue;
     478                 :       }
     479               0 :       printf("close(%" PRIHANDLE ")\n", hdr.handles[i]);
     480               0 :       if (-1 == NaClClose(hdr.handles[i])) {
     481               0 :         MyPerror("ReceiverThread, Close");
     482               0 :         printf("ERROR: Close on received handle failed\n");
     483               0 :         ++errors;
     484               0 :       }
     485               0 :     }
     486                 :   }
     487             200 :   if (0 == errors) {
     488             200 :     printf("ReceiverThread, receive data: OK\n");
     489             200 :   } else {
     490               0 :     printf("ReceiverThread, receive data: FAILED\n");
     491                 :   }
     492             200 :   return errors;
     493             200 : }
     494                 : 
     495               1 : int SendDataNoPeer(TestState *tsp, int mode) {
     496               1 :   int errors(0);
     497               1 :   NaClMessageHeader hdr;
     498               1 :   NaClIOVec vec;
     499               1 :   int nbytes(-1);
     500               1 :   vec.base = tsp->msg_buffer;
     501               1 :   vec.length = tsp->msg_len;
     502               1 :   hdr.iov = &vec;
     503               1 :   hdr.iov_length = 1;
     504               1 :   hdr.handle_count = 0;
     505               1 :   hdr.flags = 0;
     506               1 :   nacl::string op;
     507               1 :   switch (mode) {
     508                 :     case 0: {
     509               0 :       op = "SendDatagramTo";
     510               0 :       nbytes = NaClSendDatagramTo(&hdr, 0, &tsp->srv_addr);
     511               0 :       break;
     512                 :     }
     513                 :     case 1: {
     514               1 :       op = "SendDatagram";
     515               2 :       nbytes = NaClSendDatagram(tsp->pair[1], &hdr, 0);
     516               1 :       break;
     517                 :     }
     518                 :     default: {
     519               0 :       printf("ERROR: illegal test mode\n");
     520               0 :       ++errors;
     521               0 :       break;
     522                 :     }
     523                 :   }
     524                 : 
     525                 : #if NACL_WINDOWS
     526                 :   if (-1 != nbytes
     527                 :       || (0 == mode && ERROR_FILE_NOT_FOUND != GetLastError())
     528                 :       || (1 == mode && ERROR_NO_DATA != GetLastError())) {
     529                 :     MyPerror(op);
     530                 :     printf("ERROR: no peer, nbytes %d, GetLastError => %d\n",
     531                 :            nbytes,
     532                 :            GetLastError());
     533                 :     ++errors;
     534                 :   } else {
     535                 :     printf("OK\n");
     536                 :   }
     537                 : #else
     538               2 :   if (-1 != nbytes
     539               1 :       || (0 == mode && ECONNREFUSED != errno)
     540               2 :       || (1 == mode && EPIPE != errno)) {
     541               0 :     MyPerror(op);
     542               0 :     printf("ERROR: no peer, nbytes %d, errno %d\n", nbytes, errno);
     543               0 :     ++errors;
     544               0 :   } else {
     545               1 :     printf("OK\n");
     546                 :   }
     547                 : #endif
     548               1 :   return errors;
     549               1 : }
     550                 : 
     551                 : struct TestFn {
     552                 :   char const *name;
     553                 :   int (*sender)(TestState *, int);
     554                 :   int (*receiver)(TestState *, int);
     555                 :   int mode;        // currently, only 0,1 for using bound socket and socketpair
     556                 :   bool new_socks;  // run test w/ per-test sockets
     557                 :   bool flakey;       // known-to-be-flakey test (known IMC implementation bug)
     558                 : } test_fn[] = { {
     559                 :     "Send one descriptor via bound socket, shared socket",
     560                 :     SendDescriptor,
     561                 :     ReceiveDescriptor,
     562                 :     0,
     563                 :     false,
     564                 :     false,
     565                 :   }, {
     566                 :     "Send some data via bound socket, shared socket",
     567                 :     SendData,
     568                 :     ReceiveData,
     569                 :     0,
     570                 :     false,
     571                 : #if NACL_WINDOWS
     572                 :     true,  // known not to be flakey
     573                 : #else
     574                 :     false,
     575                 : #endif
     576                 :   }, {
     577                 :     "Send one descriptor via socket pair, shared socket",
     578                 :     SendDescriptor,
     579                 :     ReceiveDescriptor,
     580                 :     1,
     581                 :     false,
     582                 :     false,
     583                 :   }, {
     584                 :     "Send some data via socket pair, shared socket",
     585                 :     SendData,
     586                 :     ReceiveData,
     587                 :     1,
     588                 :     false,
     589                 :     false,
     590                 :   }, {
     591                 :     "Send one descriptor via bound socket, per test socket",
     592                 :     SendDescriptor,
     593                 :     ReceiveDescriptor,
     594                 :     0,
     595                 :     true,
     596                 :     false,
     597                 :   }, {
     598                 :     "Send some data via bound socket, per test socket",
     599                 :     SendData,
     600                 :     ReceiveData,
     601                 :     0,
     602                 :     true,
     603                 : #if NACL_WINDOWS
     604                 :     true,  // known not to work: first msg must be a desc xfer
     605                 : #else
     606                 :     false,
     607                 : #endif
     608                 :   }, {
     609                 :     "Send one descriptor via socket pair, per test socket",
     610                 :     SendDescriptor,
     611                 :     ReceiveDescriptor,
     612                 :     1,
     613                 :     true,
     614                 :     false,
     615                 :   }, {
     616                 :     "Send some data via socket pair, per test socket",
     617                 :     SendData,
     618                 :     ReceiveData,
     619                 :     1,
     620                 :     true,
     621                 :     false,
     622                 :   },
     623                 :   // add more tests here
     624                 : };
     625                 : 
     626             201 : void WINAPI PeerThread(void *state) {
     627             201 :   int errors(0);
     628             201 :   TestState *tsp = reinterpret_cast<TestState *>(state);
     629                 : 
     630            1002 :   for (int i = 0; i < tsp->repetitions; ++i) {
     631             300 :     if (-1 == tsp->outer_rep)
     632             100 :       printf("\n======== PEER THREAD, REPETITION %d ========\n", i);
     633                 :     else
     634             200 :       printf("\n======== INDEPENDENT PEER THREAD, REPETITION %d ========\n",
     635                 :              tsp->outer_rep);
     636             300 :     for (std::vector<int>::const_iterator it = tsp->test_sequence->begin();
     637             900 :          tsp->test_sequence->end() != it;
     638             600 :          ++it) {
     639             600 :       int test = *it;
     640                 : 
     641             600 :       if (test_fn[test].new_socks != tsp->new_sock_only) {
     642             200 :         printf("PeerThread: new_socks mismatch, skipping\n");
     643             200 :         continue;
     644                 :       }
     645                 : 
     646             400 :       printf("PeerThread: Locking for test %d to start\n", test);
     647             400 :       NaClXMutexLock(&tsp->mu);
     648             999 :       while (tsp->cur_test != test) {
     649             199 :         printf("PeerThread: waiting for test %d to start\n", test);
     650             199 :         printf("tsp->cur_test %d\n", tsp->cur_test);
     651             199 :         NaClXCondVarWait(&tsp->cv, &tsp->mu);
     652             199 :       }
     653             400 :       NaClXMutexUnlock(&tsp->mu);
     654                 : 
     655             400 :       printf("PeerThread: START test %d, %s\n", test, test_fn[test].name);
     656             400 :       errors += test_fn[test].sender(tsp, test_fn[test].mode);
     657             400 :       printf("PeerThread: END test %d, %s\n", test, test_fn[test].name);
     658                 : 
     659             400 :       printf("PeerThread: Locking for test %d to end\n", test);
     660             400 :       NaClXMutexLock(&tsp->mu);
     661             400 :       tsp->cur_test = -1;
     662             400 :       NaClXCondVarSignal(&tsp->cv);
     663             400 :       NaClXMutexUnlock(&tsp->mu);
     664             400 :     }
     665             300 :   }
     666             201 :   if (-1 == tsp->outer_rep)
     667               1 :     printf("\n======== EXITING PEER THREAD ========\n");
     668                 :   else
     669             200 :     printf("\n======== EXITING INDEPENDENT PEER THREAD"
     670                 :            " ========\n");
     671                 : 
     672             201 :   printf("%sPEER THREAD EXITING, LOCKING\n",
     673                 :          (-1 == tsp->outer_rep) ? "" : "INDEPENDENT ");
     674             201 :   NaClXMutexLock(&tsp->mu);
     675             201 :   tsp->errors = errors;
     676             201 :   printf("%sPEER THREAD EXITING, SIGNALING\n",
     677                 :          (-1 == tsp->outer_rep) ? "" : "INDEPENDENT ");
     678             201 :   fflush(NULL);
     679             201 :   NaClXCondVarSignal(&tsp->cv);
     680             201 :   NaClXMutexUnlock(&tsp->mu);
     681             201 : }
     682                 : 
     683                 : 
     684               1 : int TestNaClSocket(int rep_count) {
     685               1 :   int errors = 0;
     686               1 :   TestState tstate(&gTestSequence, false, rep_count, -1);
     687                 : 
     688               2 :   errors += tstate.Init();
     689               1 :   if (0 != errors) return errors;
     690                 : 
     691                 :   // The Windows IMC implementation deadlocks if SendDatagramTo is
     692                 :   // invoked while nobody is doing a ReceiveDatagram.  Thus, we spawn
     693                 :   // a receiver thread.
     694                 : 
     695               1 :   printf("Starting receiver thread.\n");
     696               1 :   struct NaClThread thr;
     697               2 :   if (!NaClThreadCtor(&thr, PeerThread, static_cast<void *>(&tstate),
     698                 :                       128*1024)) {
     699               0 :     NaClLog(LOG_FATAL, "TestNaClSocket could not create receiver thread!\n");
     700               0 :   }
     701                 : 
     702             202 :   for (int rep = 0; rep < rep_count; ++rep) {
     703             100 :     printf("\n======== MAIN THREAD, START REPETITION %d ========\n", rep);
     704             300 :     for (std::vector<int>::const_iterator it = gTestSequence.begin();
     705            1500 :          gTestSequence.end() != it;
     706             800 :          ++it) {
     707             800 :       int test = *it;
     708             400 :       printf("MainThread: test %d, %s\n", test, test_fn[test].name);
     709             400 :       fflush(NULL);
     710                 : 
     711             400 :       if (gSleepBeforeReceive) {
     712               0 :         printf("Sleeping.\n");
     713               0 :         fflush(NULL);
     714                 : #if NACL_WINDOWS
     715                 :         Sleep(1000);
     716                 : #else
     717               0 :         sleep(1);
     718                 : #endif
     719               0 :       }
     720                 : 
     721             400 :       if (!test_fn[test].new_socks) {
     722             200 :         printf("Locking to start test %d\n", test);
     723             200 :         NaClXMutexLock(&tstate.mu);
     724             200 :         tstate.cur_test = test;
     725             200 :         NaClXCondVarSignal(&tstate.cv);
     726             200 :         NaClXMutexUnlock(&tstate.mu);
     727             200 :         printf("Signaled test %d start\n", test);
     728                 : 
     729             400 :         errors += test_fn[test].receiver(&tstate, test_fn[test].mode);
     730                 : 
     731             200 :         printf("Locking to wait for test %d end\n", test);
     732             200 :         NaClXMutexLock(&tstate.mu);
     733             401 :         while (-1 != tstate.cur_test) {
     734               1 :           printf("Waiting for test %d to be finished\n", test);
     735               1 :           printf("tstate.cur_test %d\n", tstate.cur_test);
     736               1 :           NaClXCondVarWait(&tstate.cv, &tstate.mu);
     737               1 :         }
     738             200 :         NaClXMutexUnlock(&tstate.mu);
     739             200 :       } else {
     740             200 :         printf("test %d requests independent socket/thread\n", test);
     741             400 :         std::vector<int> seq;
     742             200 :         seq.push_back(test);
     743             200 :         TestState private_sock(&seq, true, 1, rep);
     744             400 :         int private_errors(private_sock.Init());
     745             200 :         if (0 != private_errors) {
     746               0 :           printf("Could not create/initialize TestState.\n");
     747               0 :           errors += private_errors;
     748               0 :           continue;
     749                 :         }
     750             200 :         struct NaClThread private_thr;
     751             400 :         if (!NaClThreadCtor(&private_thr, PeerThread,
     752                 :                             static_cast<void *>(&private_sock), 128*1024)) {
     753               0 :           NaClLog(LOG_FATAL, "TestNaClSocket could not create PeerThread\n");
     754               0 :         }
     755                 : 
     756             200 :         printf("Locking to start test %d\n", test);
     757             200 :         NaClXMutexLock(&private_sock.mu);
     758             200 :         private_sock.cur_test = test;
     759             200 :         NaClXCondVarSignal(&private_sock.cv);
     760             200 :         NaClXMutexUnlock(&private_sock.mu);
     761             200 :         printf("Signaled test %d start\n", test);
     762                 : 
     763             400 :         errors += test_fn[test].receiver(&private_sock, test_fn[test].mode);
     764                 : 
     765             200 :         printf("Locking to wait for test %d end\n", test);
     766             200 :         NaClXMutexLock(&private_sock.mu);
     767             410 :         while (-1 != private_sock.cur_test) {
     768              10 :           printf("Waiting for test %d to be finished\n", test);
     769              10 :           printf("private_sock %d\n", private_sock.cur_test);
     770              10 :           NaClXCondVarWait(&private_sock.cv, &private_sock.mu);
     771              10 :         }
     772             200 :         NaClXMutexUnlock(&private_sock.mu);
     773                 : 
     774             200 :         fflush(NULL);
     775             200 :         NaClXMutexLock(&private_sock.mu);
     776             409 :         while (-1 == private_sock.errors) {
     777               9 :           NaClXCondVarWait(&private_sock.cv, &private_sock.mu);
     778               9 :         }
     779             200 :         NaClXMutexUnlock(&private_sock.mu);
     780             200 :         errors += private_sock.errors;
     781             200 :         if (private_sock.outer_rep != rep) {
     782               0 :           printf("Threads out of sync!?!\n");
     783               0 :           abort();
     784                 :         }
     785             600 :       }
     786             400 :     }
     787             100 :   }
     788                 : 
     789                 : 
     790               1 :   printf("MainThread: Waiting for receiver thread to exit.\n");
     791               1 :   fflush(NULL);
     792               1 :   NaClXMutexLock(&tstate.mu);
     793               2 :   while (-1 == tstate.errors) {
     794               0 :     NaClXCondVarWait(&tstate.cv, &tstate.mu);
     795               0 :   }
     796               1 :   NaClXMutexUnlock(&tstate.mu);
     797               1 :   NaClThreadDtor(&thr);
     798               1 :   errors += tstate.errors;
     799                 : 
     800                 :   // now close server side and attempt to send again.
     801               1 :   printf("NaClClose(%" PRIHANDLE ")\n", tstate.srv_sock);
     802               1 :   (void) NaClClose(tstate.srv_sock);
     803               1 :   tstate.srv_sock = NACL_INVALID_HANDLE;
     804               1 :   printf("NaClClose(%" PRIHANDLE ")\n", tstate.pair[0]);
     805               1 :   (void) NaClClose(tstate.pair[0]);
     806               1 :   tstate.pair[0] = NACL_INVALID_HANDLE;
     807                 : 
     808                 :   if (kPlatformUsesBoundSockets) {
     809                 :     printf("Sending a datagram to an address with closed bound socket.\n");
     810                 :     SendDataNoPeer(&tstate, 0);
     811                 :   }
     812               1 :   printf("Sending a datagram to a socketpair where peer was closed.\n");
     813               1 :   SendDataNoPeer(&tstate, 1);
     814                 : 
     815               1 :   return errors;
     816               1 : }
     817                 : 
     818                 : void ListTests() {
     819               0 :   for (size_t ix = 0; ix < NACL_ARRAY_SIZE(test_fn); ++ix) {
     820               0 :     printf("%3" NACL_PRIuS ": %s\n", ix, test_fn[ix].name);
     821               0 :     if (test_fn[ix].flakey) {
     822               0 :       printf(" NB: known to be flakey on this platform\n");
     823               0 :     }
     824               0 :   }
     825               0 : }
     826                 : 
     827                 : }  // anonymous namespace
     828                 : 
     829                 : 
     830               1 : int main(int ac,
     831               1 :          char **av) {
     832               1 :   int errors(0);
     833               1 :   int opt;
     834               1 :   int rep_count(100);
     835                 : 
     836               1 :   char obuf[BUFSIZ];
     837                 : 
     838               1 :   setvbuf(stdout, obuf, _IOLBF, sizeof obuf);
     839                 : 
     840               1 :   NaClLogModuleInit();
     841                 : 
     842               2 :   while (-1 != (opt = getopt(ac, av, "lr:st:"))) {
     843               0 :     switch (opt) {
     844                 :       case 'l': {
     845               0 :         ListTests();
     846               0 :         return 0;
     847                 :       }
     848                 :       case 'r': {
     849               0 :         rep_count = strtol(optarg, static_cast<char **>(NULL), 0);
     850               0 :         break;
     851                 :       }
     852                 :       case 's': {
     853               0 :         gSleepBeforeReceive = true;
     854               0 :         break;
     855                 :       }
     856                 :       case 't': {
     857               0 :         std::vector<nacl::string> vs;
     858               0 :         SplitString(&vs, optarg, ',');
     859               0 :         ApplyInt(&gTestSequence, vs);
     860                 :         break;
     861               0 :       }
     862                 :       default: {
     863               0 :         fprintf(stderr,
     864                 :                 "Usage: sigpipe_test [-l] [-r reps] [-s] [-t tests]\n"
     865                 :                 " -l list available tests\n"
     866                 :                 " -r run test sequence reps number of times\n"
     867                 :                 " -s sleep between receiving handle and data\n"
     868                 :                 " -t test sequence, a comma separated integers specifying\n"
     869                 :                 "    which tests to run and in what order\n");
     870               0 :         exit(1);
     871                 :       }
     872                 :     }
     873               0 :   }
     874               1 :   if (gTestSequence.empty()) {
     875              18 :     for (size_t i = 0; i < NACL_ARRAY_SIZE(test_fn); ++i) {
     876              16 :       if (!test_fn[i].flakey &&
     877                 :           (kPlatformUsesBoundSockets || test_fn[i].mode != 0)) {
     878               4 :         gTestSequence.push_back(nacl::assert_cast<int>(i));
     879               4 :       }
     880               8 :     }
     881               1 :   }
     882               1 :   printf("Test sequence:\n");
     883               1 :   for (std::vector<int>::const_iterator it = gTestSequence.begin();
     884               5 :        gTestSequence.end() != it;
     885               4 :        ++it) {
     886               4 :     if ((unsigned) *it >= NACL_ARRAY_SIZE(test_fn)) {
     887               0 :       fprintf(stderr, "No test %d\n", *it);
     888               0 :       ++errors;
     889               0 :     } else {
     890               4 :       printf(" %d: %s\n", *it, test_fn[*it].name);
     891                 :     }
     892               4 :   }
     893                 : 
     894               1 :   if (errors) {
     895               0 :     printf("Test specification error.\n");
     896               0 :     return errors;
     897                 :   }
     898                 : #if NACL_WINDOWS
     899                 :   if (0 != gTestSequence[0]) {
     900                 :     printf("WARNING: it is known that the Windows IMC implementation\n"
     901                 :            "fails if the first operation is not send descriptor\n");
     902                 :     fflush(NULL);
     903                 :   }
     904                 : #endif
     905                 : 
     906               1 :   errors += TestNaClSocket(rep_count);
     907                 : 
     908               3 :   printf("%s\n", (errors == 0) ? "PASSED" : "FAILED");
     909                 : 
     910               1 :   NaClLogModuleFini();
     911                 : 
     912               1 :   return errors;
     913               1 : }

Generated by: LCOV version 1.7