tags:

views:

66

answers:

2

Hey all, the following is a snippet of code taken from the unix ptx utility. I'm attempting to maximize code coverage on this utility, but I am unable to reach the indicated portion of code. Admittedly, I'm not as strong in my C skills as I used to be. The portion of code is indicated with comments, but it is towards the bottom of the block.

if (used_length == allocated_length)
{
     allocated_length += (1 << SWALLOW_REALLOC_LOG);
     block->start
    = (char *) xrealloc (block->start, allocated_length);
}

Any help interpreting the indicated portion in order to cover that block would be greatly appreciated.

/* Reallocation step when swallowing non regular files.  The value is not
   the actual reallocation step, but its base two logarithm.  */
#define SWALLOW_REALLOC_LOG 12

static void swallow_file_in_memory (const char *file_name, BLOCK *block)
{
  int file_handle;      /* file descriptor number */
  struct stat stat_block;   /* stat block for file */
  size_t allocated_length;  /* allocated length of memory buffer */
  size_t used_length;       /* used length in memory buffer */
  int read_length;      /* number of character gotten on last read */

  /* As special cases, a file name which is NULL or "-" indicates standard
     input, which is already opened.  In all other cases, open the file from
     its name.  */
  bool using_stdin = !file_name || !*file_name || strcmp (file_name, "-") == 0;
  if (using_stdin)
    file_handle = STDIN_FILENO;
  else
    if ((file_handle = open (file_name, O_RDONLY)) < 0)
      error (EXIT_FAILURE, errno, "%s", file_name);

  /* If the file is a plain, regular file, allocate the memory buffer all at
     once and swallow the file in one blow.  In other cases, read the file
     repeatedly in smaller chunks until we have it all, reallocating memory
     once in a while, as we go.  */

  if (fstat (file_handle, &stat_block) < 0)
    error (EXIT_FAILURE, errno, "%s", file_name);

  if (S_ISREG (stat_block.st_mode))
    {
      size_t in_memory_size;

      block->start = (char *) xmalloc ((size_t) stat_block.st_size);

      if ((in_memory_size = read (file_handle,
                  block->start, (size_t) stat_block.st_size))
      != stat_block.st_size)
    {
        error (EXIT_FAILURE, errno, "%s", file_name);
    }
      block->end = block->start + in_memory_size;
    }
  else
    {
      block->start = (char *) xmalloc ((size_t) 1 << SWALLOW_REALLOC_LOG);
      used_length = 0;
      allocated_length = (1 << SWALLOW_REALLOC_LOG);

      while (read_length = read (file_handle,
                 block->start + used_length,
                 allocated_length - used_length),
         read_length > 0)
    {
      used_length += read_length;
      /* Cannot cover from this point...*/
      if (used_length == allocated_length)
        {
          allocated_length += (1 << SWALLOW_REALLOC_LOG);
          block->start
        = (char *) xrealloc (block->start, allocated_length);
        }
      /* ...to this point. */
    }

      if (read_length < 0)
    error (EXIT_FAILURE, errno, "%s", file_name);

      block->end = block->start + used_length;
    }

  /* Close the file, but only if it was not the standard input.  */

  if (! using_stdin && close (file_handle) != 0)
    error (EXIT_FAILURE, errno, "%s", file_name);
}
+1  A: 

To maximize code coverage you need to hit 100% coverage.

Firstly the 100% aim is generally a waste of time. By all means use code coverage tools to aid you, but don't get obsessed by the number. It's more important to test specific areas of your code well and deliberately miss out other parts instead of spreading your effort over the entire codebase, regardless of its importance.

Having said that, in order to get the coverage in this specific case you will have to mock the read method so that you can control what it does. You need to use dependency injection to achieve this. Another technique could be to assign a buffer of only one byte, forcing that branch to be taken.

Mark Byers
+1  A: 

Based on the code, it sounds like your input is smaller than 4096 (1 << SWALLOW_REALLOC_LOG) bytes long. Give it an input larger (and make sure you are providing this larger input not as a plain file, but via a pipe) and you should hit that code.

R Samuel Klatchko
Thank you sir. That was the problem. I appreciate it.