示例#1
0
static int test_update(void)
{
   logbuffer_t logbuf = logbuffer_FREE;
   thread_t *  thread = 0;
   pipe_t      pipe   = pipe_FREE;
   uint8_t     buffer[1024];
   uint8_t     readbuffer[1024+1];

   // prepare
   TEST(0 == init_pipe(&pipe));
   logbuf = (logbuffer_t) logbuffer_INIT(sizeof(buffer), buffer, pipe.write);

   // TEST truncate_logbuffer
   for (unsigned i = 0; i < 32; ++i) {
      logbuf.logsize = 32;
      logbuf.addr[i] = 'a';
      truncate_logbuffer(&logbuf, i);
      TEST(logbuf.addr == buffer);
      TEST(logbuf.size == sizeof(buffer));
      TEST(logbuf.io   == pipe.write);
      TEST(logbuf.addr[i] == 0);
      TEST(logbuf.logsize == i);
   }

   // TEST truncate_logbuffer: parameter with bigger or equal size are ignored
   for (unsigned i = 0; i < 32; ++i) {
      logbuf.logsize = i;
      logbuf.addr[i]   = 'a';
      logbuf.addr[i+1] = 'a';
      truncate_logbuffer(&logbuf, i+1);
      truncate_logbuffer(&logbuf, i);
      TEST(logbuf.addr == buffer);
      TEST(logbuf.size == sizeof(buffer));
      TEST(logbuf.io   == pipe.write);
      TEST(logbuf.addr[i]   == 'a');
      TEST(logbuf.addr[i+1] == 'a');
      TEST(logbuf.logsize   == i);
   }

   // TEST write_logbuffer
   memset(readbuffer, 0, sizeof(readbuffer));
   for (unsigned i = 0; i < sizeof(buffer); ++i) {
      buffer[i] = (uint8_t)i;
   }
   logbuf.logsize = logbuf.size;
   // test
   TEST( 0 == write_logbuffer(&logbuf));
   // check logbuf
   TEST( logbuf.addr == buffer);
   TEST( logbuf.size == sizeof(buffer));
   TEST( logbuf.logsize == sizeof(buffer));
   TEST( logbuf.io   == pipe.write);
   // check content of pipe
   static_assert(sizeof(readbuffer) > sizeof(buffer), "check that only sizeof(buffer) are written");
   TEST(sizeof(buffer) == read(pipe.read, readbuffer, sizeof(readbuffer)));
   for (unsigned i = 0; i < sizeof(buffer); ++i) {
      TEST(buffer[i] == readbuffer[i]);
   }

   // TEST printheader_logbuffer
   logbuf.logsize = 0;
   log_header_t header = log_header_INIT("test_update", "file", 123456);
   printheader_logbuffer(&logbuf, &header);
   TEST(0 == compare_header(logbuf.logsize, logbuf.addr, "test_update", "file", 123456));
   for (size_t len = logbuf.logsize, i = 1; i < 10; ++i) {
      printheader_logbuffer(&logbuf, &header);
      TEST((i+1)*len == logbuf.logsize);
      TEST(0 == compare_header(len, logbuf.addr + i*len, "test_update", "file", 123456));
   }

   // TEST printheader_logbuffer: other thread
   TEST(0 == newgeneric_thread(&thread, &thread_printheader, &logbuf));
   TEST(0 == join_thread(thread));
   TEST(0 == returncode_thread(thread));
   TEST(0 == delete_thread(&thread));

   // TEST printheader_logbuffer: adds " ..." at end in case of truncated message
   logbuf.logsize = logbuf.size - 10;
   logbuf.addr[logbuf.logsize] = 0;
   printheader_logbuffer(&logbuf, &header);
   TEST(logbuf.logsize == logbuf.size - 1)
   TEST(0 == memcmp(logbuf.addr + logbuf.size - 10, "[", 1));
   TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5));

   // TEST vprintf_logbuffer: append on already stored content
   for (unsigned i = 0; i < sizeof(buffer)-100; ++i) {
      memset(buffer, 0, sizeof(buffer));
      memset(readbuffer, 0, sizeof(readbuffer));
      logbuf.logsize = i;
      printf_logbuffer(&logbuf, "%d : %s : %c;;", i, "OK!", '0');
      snprintf((char*)readbuffer + i, 100, "%d : %s : %c;;", i, "OK!", '0');
      TEST(0 == memcmp(buffer, readbuffer, sizeof(buffer)));
   }

   // TEST vprintf_logbuffer: different formats
   logbuf.logsize = 0;
   printf_logbuffer(&logbuf, "%%%s%%", "str" );
   printf_logbuffer(&logbuf, "%"PRIi8";", (int8_t)-1);
   printf_logbuffer(&logbuf, "%"PRIu8";", (uint8_t)1);
   printf_logbuffer(&logbuf, "%"PRIi16";", (int16_t)-256);
   printf_logbuffer(&logbuf, "%"PRIu16";", (uint16_t)256);
   printf_logbuffer(&logbuf, "%"PRIi32";", (int32_t)-65536);
   printf_logbuffer(&logbuf, "%"PRIu32";", (uint32_t)65536);
   printf_logbuffer(&logbuf, "%zd;", (ssize_t)-65536);
   printf_logbuffer(&logbuf, "%zu;", (size_t)65536);
   printf_logbuffer(&logbuf, "%g;", 2e100);
   printf_logbuffer(&logbuf, "%.0f;", (double)1234567);
   const char * result = "%str%-1;1;-256;256;-65536;65536;-65536;65536;2e+100;1234567;";
   TEST(strlen(result) == logbuf.logsize);
   TEST(0 == memcmp(logbuf.addr, result, logbuf.logsize));

   // TEST vprintf_logwriter: adds " ..." at end in case of truncated message
   char strtoobig[100];
   memset(strtoobig, '1', sizeof(strtoobig));
   logbuf.logsize = logbuf.size - sizeof(strtoobig);
   logbuf.addr[logbuf.logsize] = 0;
   printf_logbuffer(&logbuf, "%.100s", strtoobig);
   TEST(logbuf.logsize == logbuf.size - 1)
   TEST(0 == memcmp(logbuf.addr + logbuf.size - sizeof(strtoobig), strtoobig, sizeof(strtoobig)-5));
   TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5));

   // TEST vprintf_logbuffer: format == 0
   logbuf.logsize = 0;
   printf_logbuffer(&logbuf, 0);
   // nothing printed
   TEST(0 == logbuf.logsize);

   // TEST vprintf_logbuffer: sizefree_logbuffer() == 0
   logbuf.logsize = logbuf.size;
   memset(logbuf.addr, 255, logbuf.size);
   printf_logbuffer(&logbuf, "%d", 12345);
   // check logbuf not changed
   TEST(buffer == logbuf.addr);
   TEST(sizeof(buffer) == logbuf.size);
   TEST(sizeof(buffer) == logbuf.logsize);
   TEST(pipe.write     == logbuf.io);
   // check content of logbuf not changed except for " ..."
   for (size_t i = 0; i < logbuf.logsize - 5; ++i) {
      TEST(255 == logbuf.addr[i]);
   }
   TEST(0 == memcmp(logbuf.addr + logbuf.logsize - 5, " ...", 4));
   TEST(255 == logbuf.addr[logbuf.logsize-1]);

   // TEST vprintf_logbuffer: logbuffer_t.size <= 5
   for (size_t s = 5; s <= 5; --s) {
      TEST(sizeof(buffer) == logbuf.size);
      logbuf.size = s;
      logbuf.logsize = 0;
      memset(logbuf.addr, 255, s);
      printf_logbuffer(&logbuf, "%d", 12345);
      // check logbuf
      TEST(buffer == logbuf.addr);
      TEST(s      == logbuf.size);
      TEST((s?s-1:0)  == logbuf.logsize);
      TEST(pipe.write == logbuf.io);
      // check content of logbuf
      if (s == 5) {
         // " ..."
         TEST(0 == memcmp(logbuf.addr, " ...", 5));
      } else {
         // truncated 12345
         for (size_t i = 0; i < logbuf.logsize; ++i) {
            TEST(i+'1' == logbuf.addr[i]);
         }
         TEST(0 == (logbuf.size ? logbuf.addr[logbuf.size-1] : 0));
      }
      // reset
      logbuf.size = sizeof(buffer);
   }

   // unprepare
   TEST(-1 == read(pipe.read, readbuffer, sizeof(readbuffer)));
   TEST(0 == free_pipe(&pipe));

   return 0;
ONERR:
   delete_thread(&thread);
   free_pipe(&pipe);
   return EINVAL;
}
示例#2
0
static int test_logininfo(void)
{
   syslogin_info_t* info = 0;
   thread_t* thr = 0;
   uid_t   uid;
   gid_t   gid;
   int     fd[2] = { -1, -1 };
   uint8_t buffer[16];

   // prepare
   TEST(0 == pipe2(fd, O_CLOEXEC|O_NONBLOCK));

   // == lifetime ==

   for (unsigned entrypos = 0; true; ++entrypos) {
      setpwent();
      for (unsigned i = 0; i < entrypos; ++i) {
         TEST(0 != getpwent());
      }
      struct passwd* pwd = getpwent();
      if (pwd == 0) {
         TEST(entrypos > 2); // tested at least 2 entries
         break;
      }
      uid = pwd->pw_uid;
      gid = pwd->pw_gid;

      // TEST new_syslogininfo: read entries
      TEST(0 == new_syslogininfo(&info, uid));
      TEST(0 != info);
      TEST(0 <  info->size);
      TEST(uid == info->uid);
      TEST(1 <= info->nrgroups);
      TEST(info->nrgroups > info->gmain);
      TEST(gid == info->gid[info->gmain]);
      // check memory addr
      TEST(info->gname == (const char**)(&info[1]));
      TEST(info->gid   == (sys_groupid_t*)((uint8_t*)info->gname + info->nrgroups * sizeof(char*)));
      TEST(info->uname == (const char*)((uint8_t*)info->gid + info->nrgroups * sizeof(sys_groupid_t)));
      TEST(info->gname[0] == info->uname + strlen(info->uname) + 1);
      TEST((uint8_t*)info + info->size  == (const uint8_t*)info->gname[info->nrgroups-1] + strlen(info->gname[info->nrgroups-1]) + 1);
      for (size_t i = 1; i < info->nrgroups; ++i) {
         TEST(info->gname[i-1] + strlen(info->gname[i-1]) + 1 == info->gname[i]);
      }
      // DEBUG printf("user %s(%d) groups ", info->uname, info->uid);
      // DEBUG for (size_t i = 0; i < info->nrgroups; ++i) {
      // DEBUG    if (i == info->gmain) printf("*");
      // DEBUG    printf("%s(%d),", info->gname[i], info->gid[i]);
      // DEBUG }
      // DEBUG printf("\n");

      // TEST delete_syslogininfo
      TEST(0 != info);
      TEST(0 == delete_syslogininfo(&info));
      TEST(0 == info);
      TEST(0 == delete_syslogininfo(&info));
      TEST(0 == info);
   }

   // TEST new_syslogininfo: lock
   TEST(0 == new_thread(&thr, &thread_initinfo, (void*)(intptr_t)fd[1]));
   TEST(0 == lock_mutex(&s_syslogininfo_lock));
   struct pollfd pfd = { .fd = fd[0], .events = POLLIN };
   TEST(1 == poll(&pfd, 1, 10000));
   TEST(1 == read(fd[0], buffer, sizeof(buffer)));
   TEST(EBUSY == tryjoin_thread(thr));
   TEST(-1 == read(fd[0], buffer, sizeof(buffer)));
   TEST(EAGAIN == errno);
   TEST(0 == unlock_mutex(&s_syslogininfo_lock));
   TEST(0 == join_thread(thr));
   TEST(0 == returncode_thread(thr));
   TEST(0 == delete_thread(&thr));

   // TEST new_syslogininfo: ENOENT
   info = (void*)1;
   TEST(ENOENT == new_syslogininfo(&info, (uid_t)-2));
   TEST((void*)1 == info);
   info = 0;

   // == query ==

   // TEST username_syslogininfo
   syslogin_info_t info2;
   info2.uname = 0;
   TEST(0 == username_syslogininfo(&info2));
   for (uintptr_t i = 1; i; i <<= 1) {
      info2.uname = (const char*)i;
      TEST((const char*)i == username_syslogininfo(&info2));
   }

   // unprepare
   TEST(0 == close(fd[0]));
   TEST(0 == close(fd[1]));

   return 0;
ONERR:
   if (info != (void*)1) {
      delete_syslogininfo(&info);
   }
   close(fd[0]);
   close(fd[1]);
   return EINVAL;
}