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

Generated by: LCOV version 1.7