LCOV - code coverage report
Current view: directory - src/trusted/desc - nacl_desc_quota_test.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 152 89 58.6 %
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                 : #include <stdio.h>
       8                 : #include <sys/types.h>
       9                 : #include <sys/stat.h>
      10                 : #include <fcntl.h>
      11                 : #include <errno.h>
      12                 : 
      13                 : #include "native_client/src/include/portability.h"
      14                 : #include "native_client/src/include/portability_string.h"
      15                 : #include "native_client/src/include/nacl_macros.h"
      16                 : 
      17                 : #include "native_client/src/shared/platform/nacl_check.h"
      18                 : #include "native_client/src/shared/platform/nacl_semaphore.h"
      19                 : 
      20                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      21                 : #include "native_client/src/shared/platform/nacl_log.h"
      22                 : #include "native_client/src/shared/platform/nacl_secure_random.h"
      23                 : #include "native_client/src/shared/platform/nacl_sync.h"
      24                 : #include "native_client/src/shared/platform/nacl_threads.h"
      25                 : #include "native_client/src/shared/platform/nacl_time.h"
      26                 : 
      27                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      28                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      29                 : #include "native_client/src/trusted/desc/nacl_desc_quota.h"
      30                 : #include "native_client/src/trusted/desc/nacl_desc_quota_interface.h"
      31                 : 
      32                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      33                 : 
      34                 : #if NACL_WINDOWS
      35                 : # define UNLINK(f)  _unlink(f)
      36                 : #else
      37                 : # define UNLINK(f)  unlink(f)
      38                 : #endif
      39                 : 
      40                 : char *gProgram = NULL;
      41                 : 
      42                 : uint64_t gNumBytes;
      43                 : 
      44                 : struct NaClDescFake {
      45                 :   struct NaClDesc base NACL_IS_REFCOUNT_SUBCLASS;
      46                 :   uint64_t bytes_written;
      47                 : };
      48                 : 
      49                 : /*
      50                 :  * A fake descriptor quota interface.
      51                 :  */
      52                 : 
      53               1 : static void FakeDtor(struct NaClRefCount *nrcp) {
      54               1 :   nrcp->vtbl = (struct NaClRefCountVtbl *)(&kNaClDescQuotaInterfaceVtbl);
      55               1 :   (*nrcp->vtbl->Dtor)(nrcp);
      56               1 : }
      57                 : 
      58                 : static int64_t FakeWriteRequest(struct NaClDescQuotaInterface *quota_interface,
      59                 :                                 uint8_t const                 *file_id,
      60                 :                                 int64_t                       offset,
      61               1 :                                 int64_t                       length) {
      62                 :   UNREFERENCED_PARAMETER(quota_interface);
      63                 :   UNREFERENCED_PARAMETER(file_id);
      64                 :   UNREFERENCED_PARAMETER(offset);
      65                 : 
      66                 :   NaClLog(1,
      67                 :           ("NaClSrpcPepperWriteRequest(dummy): requesting length %"NACL_PRId64
      68                 :            ", (0x%"NACL_PRIx64")\n"),
      69               1 :           length, length);
      70               1 :   if (length < 0) {
      71               0 :     NaClLog(LOG_FATAL, "Negative length: %"NACL_PRId64"\n", length);
      72                 :   }
      73               1 :   if ((uint64_t) length > gNumBytes) {
      74               1 :     NaClLog(1, "NaClSrpcPepperWriteRequest(dummy): clamping!\n");
      75               1 :     length = (int64_t) gNumBytes;
      76                 :   }
      77                 :   /* post: length <= gNumBytes */
      78                 :   NaClLog(1,
      79                 :           ("NaClSrpcPepperWriteRequest(dummy): allowing length %"NACL_PRId64
      80                 :            ", (0x%"NACL_PRIx64")\n"),
      81               1 :           length, length);
      82               1 :   gNumBytes -= length;
      83               1 :   return length;
      84               1 : }
      85                 : 
      86                 : static int64_t FakeFtruncateRequest(
      87                 :     struct NaClDescQuotaInterface *quota_interface,
      88                 :     uint8_t const                 *file_id,
      89               0 :     int64_t                       length) {
      90                 :   UNREFERENCED_PARAMETER(quota_interface);
      91                 :   UNREFERENCED_PARAMETER(file_id);
      92                 : 
      93               0 :   NaClLog(LOG_FATAL, "FtruncateRequest invoked!?!\n");
      94               0 :   return length;
      95               0 : }
      96                 : 
      97                 : struct NaClDescQuotaInterfaceVtbl const kFakeQuotaInterfaceVtbl = {
      98                 :   {
      99                 :     FakeDtor
     100                 :   },
     101                 :   FakeWriteRequest,
     102                 :   FakeFtruncateRequest
     103                 : };
     104                 : 
     105                 : struct FakeQuotaInterface {
     106                 :   struct NaClDescQuotaInterface base NACL_IS_REFCOUNT_SUBCLASS;
     107                 : };
     108                 : 
     109               1 : int FakeQuotaInterfaceCtor(struct FakeQuotaInterface *self) {
     110               1 :   struct NaClRefCount *nrcp = (struct NaClRefCount *) self;
     111               1 :   if (!NaClDescQuotaInterfaceCtor(&(self->base))) {
     112               0 :     return 0;
     113                 :   }
     114               1 :   nrcp->vtbl = (struct NaClRefCountVtbl *)(&kFakeQuotaInterfaceVtbl);
     115               1 :   return 1;
     116               1 : }
     117                 : 
     118                 : int ExerciseQuotaObject(struct NaClDescQuota  *test_obj,
     119                 :                         struct NaClSecureRng  *rngp,
     120                 :                         char                  *buffer,
     121                 :                         size_t                max_write_size,
     122               1 :                         uint64_t              num_bytes) {
     123                 :   nacl_off64_t file_size;
     124                 : 
     125               1 :   gNumBytes = num_bytes;
     126                 : 
     127                 :   NaClLog(LOG_INFO,
     128                 :           "ExerciseQuotaObject: allow total %"NACL_PRId64" bytes\n",
     129               1 :           num_bytes);
     130                 :   NaClLog(LOG_INFO,
     131                 :           "ExerciseQuotaObject: random write sizes, up to %"
     132                 :           NACL_PRIdS" bytes\n",
     133               1 :           max_write_size);
     134                 : 
     135               1 :   while (gNumBytes > 0) {
     136                 :     size_t    write_size;
     137                 :     uint32_t  limit;
     138                 :     ssize_t   result;
     139                 :     uint64_t  old_size;
     140                 : 
     141               1 :     NACL_COMPILE_TIME_ASSERT(sizeof(uint32_t) <= sizeof(size_t));
     142                 : 
     143                 :     /* following is always false on ILP32 */
     144               1 :     if (max_write_size > NACL_UMAX_VAL(uint32_t)) {
     145               0 :       limit = NACL_UMAX_VAL(uint32_t);
     146               0 :     } else {
     147               1 :       limit = (uint32_t) max_write_size;
     148                 :     }
     149                 : 
     150               1 :     write_size = (*rngp->base.vtbl->Uniform)(&rngp->base, limit);
     151                 : 
     152               1 :     NaClLog(LOG_INFO, "Random size: %"NACL_PRIdS"\n", write_size);
     153                 : 
     154               1 :     old_size = gNumBytes;
     155                 : 
     156                 :     result = (*NACL_VTBL(NaClDesc, test_obj)->
     157               1 :               Write)((struct NaClDesc *) test_obj, buffer, write_size);
     158                 : 
     159               1 :     if (result < 0) {
     160               0 :       NaClLog(LOG_INFO, "Write result %"NACL_PRIdS"\n", result);
     161               0 :       return 1;
     162                 :     }
     163                 :     /*
     164                 :      * OS short write?  Clamped write amount?
     165                 :      */
     166               1 :     if ((size_t) result < write_size && (uint64_t) result != gNumBytes) {
     167                 :       NaClLog(LOG_INFO,
     168                 :               ("Short write: asked for %"NACL_PRIdS" (0x%"NACL_PRIxS") bytes,"
     169                 :                " got %"NACL_PRIdS" (0x%"NACL_PRIxS") bytes.\n"),
     170                 :               write_size, write_size,
     171               1 :               result, result);
     172                 :     }
     173               1 :     if ((size_t) result > write_size) {
     174                 :       NaClLog(LOG_FATAL,
     175                 :               ("ERROR: LONG write: asked for %"NACL_PRIdS
     176                 :                " (0x%"NACL_PRIxS") bytes,"
     177                 :                " got %"NACL_PRIdS" (0x%"NACL_PRIxS") bytes.\n"),
     178                 :               write_size, write_size,
     179               0 :               result, result);
     180               0 :       return 1;
     181                 :     }
     182                 : 
     183               1 :     if (old_size - gNumBytes != (uint64_t) result) {
     184                 :       NaClLog(LOG_FATAL,
     185               0 :               "Write tracking failure.\n");
     186                 :     }
     187               1 :   }
     188                 : 
     189               1 :   NaClLog(LOG_INFO, "... checking file size\n");
     190                 : 
     191                 :   file_size = (*NACL_VTBL(NaClDesc, test_obj)->
     192                 :                Seek)((struct NaClDesc *) test_obj,
     193                 :                      0,
     194               1 :                      SEEK_END);
     195               1 :   CHECK((uint64_t) file_size == num_bytes);
     196                 : 
     197               1 :   NaClLog(LOG_INFO, "OK.\n");
     198                 : 
     199               1 :   return 0;
     200               1 : }
     201                 : 
     202               0 : void Usage(void) {
     203               0 :   fprintf(stderr, "Usage: %s -f file-to-write [-n num_bytes]\n", gProgram);
     204               0 : }
     205                 : 
     206               1 : int main(int ac, char **av) {
     207               1 :   int                        exit_status = 1;
     208               1 :   int                        num_errors = 0;
     209                 :   int                        opt;
     210               1 :   char                       *file_path = NULL;
     211                 :   char                       *buffer;
     212               1 :   size_t                     max_write_size = 5UL << 10;  /* > 1 page */
     213                 :   size_t                     ix;
     214               1 :   uint64_t                   num_bytes = 16UL << 20;
     215               1 :   struct NaClDescIoDesc      *ndip = NULL;
     216               1 :   struct NaClDescQuota       *object_under_test = NULL;
     217               1 :   struct FakeQuotaInterface  *fake_interface = NULL;
     218                 :   struct NaClSecureRng       rng;
     219                 :   static uint8_t             file_id0[NACL_DESC_QUOTA_FILE_ID_LEN];
     220                 :   static const char file_id0_cstr[NACL_DESC_QUOTA_FILE_ID_LEN] = "File ID 0";
     221                 : 
     222               1 :   NaClLogModuleInit();
     223               1 :   NaClTimeInit();
     224               1 :   NaClSecureRngModuleInit();
     225                 : 
     226               1 :   gProgram = strrchr(av[0], '/');
     227               1 :   if (NULL == gProgram) {
     228               1 :     gProgram = av[0];
     229               1 :   } else {
     230               0 :     ++gProgram;
     231                 :   }
     232                 : 
     233               1 :   memset(file_id0, 0, sizeof file_id0);
     234               1 :   memcpy(file_id0, file_id0_cstr, sizeof file_id0_cstr);
     235                 : 
     236               1 :   while (EOF != (opt = getopt(ac, av, "f:m:n:"))) {
     237               1 :     switch (opt) {
     238                 :       case 'f':
     239               1 :         file_path = optarg;
     240               1 :         break;
     241                 :       case 'm':
     242               0 :         max_write_size = (size_t) STRTOULL(optarg, (char **) NULL, 0);
     243                 :       case 'n':
     244               0 :         num_bytes = (uint64_t) STRTOULL(optarg, (char **) NULL, 0);
     245               0 :         break;
     246                 :       default:
     247               0 :         Usage();
     248               0 :         exit_status = 1;
     249               0 :         goto cleanup;
     250                 :     }
     251               1 :   }
     252               1 :   if (NULL == file_path) {
     253               0 :     fprintf(stderr, "Please provide a path name for a temporary file that\n");
     254               0 :     fprintf(stderr, "this test can create/overwrite.\n");
     255               0 :     Usage();
     256               0 :     exit_status = 2;
     257               0 :     goto cleanup;
     258                 :   }
     259                 : 
     260                 :   /*
     261                 :    * Invariant in cleanup code: ndip and object_under_test, if
     262                 :    * non-NULL, needs to be Dtor'd (via NaClDescSafeUnref).  So:
     263                 :    *
     264                 :    * 1) We never have a partially-constructed object.  (Our Ctors fail
     265                 :    *    atomically.)
     266                 :    *
     267                 :    * 2) If a Ctor takes ownership of another object, we immediately
     268                 :    *    replace our reference to that object with NULL, so that the
     269                 :    *    cleanup code would not try to Dtor the contained object
     270                 :    *    independently of the containing object.
     271                 :    */
     272                 :   if (NULL == (ndip = NaClDescIoDescOpen(file_path,
     273                 :                                          NACL_ABI_O_RDWR | NACL_ABI_O_CREAT,
     274               1 :                                          0777))) {
     275               0 :     fprintf(stderr, "%s could not open file %s\n", gProgram, file_path);
     276               0 :     exit_status = 3;
     277               0 :     goto cleanup_file;
     278                 :   }
     279               1 :   if (NULL == (fake_interface = malloc(sizeof *fake_interface))) {
     280               0 :     perror(gProgram);
     281               0 :     fprintf(stderr, "No memory for fake interface.\n");
     282               0 :     exit_status = 4;
     283               0 :     goto cleanup_file;
     284                 :   }
     285               1 :   if (!FakeQuotaInterfaceCtor(fake_interface)) {
     286               0 :     perror(gProgram);
     287               0 :     fprintf(stderr, "Ctor for fake quota interface failed.\n");
     288                 :     /*
     289                 :      * fake_interface is not constructed, so we must free it and
     290                 :      * NULL it out to prevent the cleanup code Dtors from firing.
     291                 :      */
     292               0 :     free(fake_interface);
     293               0 :     fake_interface = NULL;
     294               0 :     exit_status = 5;
     295               0 :     goto cleanup_file;
     296                 :   }
     297               1 :   if (NULL == (object_under_test = malloc(sizeof *object_under_test))) {
     298               0 :     perror(gProgram);
     299               0 :     fprintf(stderr, "No memory for object under test.\n");
     300               0 :     exit_status = 4;
     301               0 :     goto cleanup_file;
     302                 :   }
     303                 :   if (!NaClDescQuotaCtor(object_under_test,
     304                 :                          (struct NaClDesc *) ndip,
     305                 :                          file_id0,
     306               1 :                          (struct NaClDescQuotaInterface *) fake_interface)) {
     307               0 :     perror(gProgram);
     308               0 :     fprintf(stderr, "Ctor for quota object failed.\n");
     309                 :     /*
     310                 :      * object_under_test is not constructed, so we must free it and
     311                 :      * NULL it out to prevent the cleanup code Dtors from firing.
     312                 :      */
     313               0 :     free(object_under_test);
     314               0 :     object_under_test = NULL;
     315               0 :     exit_status = 5;
     316               0 :     goto cleanup_file;
     317                 :   }
     318                 : 
     319               1 :   ndip = NULL;  /* object_under_test has ownership */
     320                 : 
     321               1 :   if (!NaClSecureRngCtor(&rng)) {
     322               0 :     fprintf(stderr, "Ctor for SecureRng failed.\n");
     323               0 :     exit_status = 6;
     324               0 :     goto cleanup_file;
     325                 :   }
     326                 : 
     327               1 :   if (NULL == (buffer = malloc(max_write_size))) {
     328               0 :     fprintf(stderr, "No memory for write source buffer\n");
     329               0 :     exit_status = 7;
     330               0 :     goto cleanup_file;
     331                 :   }
     332                 : 
     333               1 :   for (ix = 0; ix < max_write_size; ++ix) {
     334               1 :     buffer[ix] = (char) ix;
     335               1 :   }
     336                 : 
     337                 :   num_errors += ExerciseQuotaObject(object_under_test,
     338                 :                                     &rng,
     339                 :                                     buffer,
     340                 :                                     max_write_size,
     341               1 :                                     num_bytes);
     342                 : 
     343               1 :   if (num_errors > 0) {
     344               0 :     printf("Total %d errors\n", num_errors);
     345               0 :     exit_status = 8;
     346               0 :   } else {
     347               1 :     printf("PASSED.\n");
     348               1 :     exit_status = 0;
     349                 :   }
     350                 : 
     351                 : cleanup_file:
     352                 :   NaClDescQuotaInterfaceSafeUnref(
     353               1 :       (struct NaClDescQuotaInterface *) fake_interface);
     354               1 :   NaClDescSafeUnref((struct NaClDesc *) ndip);
     355               1 :   NaClDescSafeUnref((struct NaClDesc *) object_under_test);
     356                 : 
     357               1 :   if (-1 == UNLINK(file_path)) {
     358               0 :     perror("nacl_desc_quota_test");
     359                 :     fprintf(stderr,
     360                 :             "unlink of a temporary file failed during test cleanup, errno %d\n",
     361               0 :             errno);
     362               0 :     exit_status = 9;
     363                 :   }
     364                 : 
     365                 : cleanup:
     366               1 :   return exit_status;
     367               1 : }

Generated by: LCOV version 1.7