Differential Testing of GNUs Coreutils 'fmt' Utility
Question: I am exploring various testing strategies (differential, regression, unit,
etc...), and have been assigned the task of testing GNUs `Coreutils`
_[`fmt`](http://www.gnu.org/software/coreutils/manual/html_node/fmt-
invocation.html#fmt-invocation)_ utility. I am trying to apply randomized
differential testing and create an oracle, so as to assert the described
postconditions of the utility are met.

* * *

What I would like to do is create a Python utility that generates a randomized
string, applies text wrapping to the string (up to a given line width) to
generate an expected output, and then invoke the fmt utility on the generated
string and assert that the output matches the expected output. To do this, I
am trying to leverage the
[`textwrap`](https://docs.python.org/2/library/textwrap.html#module-textwrap)
Python module. However, I have not found a way to ensure that indentation is
maintained. Consider a file (file.txt) with contents

    
    
    \s\s\s\sLorem ipsum dolor sit amet, consectetuer-adipiscing elit. Curabitur dignissim venenatis pede. Quisque dui dui, ultricies ut, facilisis non, pulvinar non.
    

as input to the fmt utility. Invoking the command `fmt -w 50 file.txt` leads
to the output:

    
    
     \s\s\s\sLorem ipsum dolor sit amet,
     \s\s\s\sconsectetuer-adipiscing elit. Curabitur
     \s\s\s\sdignissim venenatis pede. Quisque dui dui,
     \s\s\s\sultricies ut, facilisis non, pulvinar non.
    

* * *

According to the fmt utilities documentation,

> By default, blank lines, spaces between words, and indentation are preserved
> in the output; successive input lines with different indentation are not
> joined; tabs are expanded on input and introduced on output.
>
> fmt prefers breaking lines at the end of a sentence, and tries to avoid line
> breaks after the first word of a sentence or before the last word of a
> sentence. A sentence break is defined as either the end of a paragraph or a
> word ending in any of ‘.?!’, followed by two spaces or end of line, ignoring
> any intervening parentheses or quotes.

In my attempt to mimic the same output behavior as the fmt utility, I decided
to use the textwrap modules
_[`fill`](https://docs.python.org/2/library/textwrap.html#textwrap.fill)_
function as follows:

    
    
    textwrap.fill(in_str, width=50, expand_tabs=True, drop_whitespace=False, fix_sentence_endings=True, break_on_hyphens=False)
    

Which, according to the Python documentation, should do the following:

  1. The maximum length of the wrapped lines will be equal to the width parameter (50).
  2. All tab characters in the input will be expanded to spaces.
  3. Whitespace at the beginning and ending of every line (after wrapping but before indenting) will **not** be dropped.
  4. Assume that a sentence ending consists of a lowercase letter followed by one of '.', '!', or '?', possibly followed by one of '"' or "'", followed by a space.
  5. Only white spaces will be considered as potentially good places for line breaks.

However, the output of the textwrap.fill function on the same input returns:

    
    
    \s\s\s\sLorem ipsum dolor sit amet, 
    consectetuer-adipiscing elit.  Curabitur dignissim
     venenatis pede.  Quisque dui dui, ultricies ut, 
    facilisis non, pulvinar non.  Duis quis arcu a 
    purus volutpat iaculis.  Morbi id dui in diam 
    ornare dictum.  Praesent consectetuer vehicula 
    ipsum.  Praesent tortor massa, congue et, ornare 
    in, posuere eget, pede.
    

As you can see, the indentation level is not maintained.

* * *

What tool and/or differential testing strategy could I best utilize to test
the fmt utility most effectively? Any suggestions are much appreciated!


Answer: Try to run this snippet with `py.test`:

    
    
    #!/usr/bin/env python2.7
    from textwrap import TextWrapper
    
    input_tx = """\s\s\s\sLorem ipsum dolor sit amet, consectetuer-adipiscing elit. Curabitur dignissim venenatis pede. Quisque dui dui, ultricies ut, facilisis non, pulvinar non."""
    output_tx1 = """\s\s\s\sLorem ipsum dolor sit amet, consectetuer-
    \s\s\s\sadipiscing elit. Curabitur dignissim
    \s\s\s\svenenatis pede. Quisque dui dui, ultricies
    \s\s\s\sut, facilisis non, pulvinar non."""
    output_tx2 = """\s\s\s\sLorem ipsum dolor sit amet,
    \s\s\s\sconsectetuer-adipiscing elit. Curabitur
    \s\s\s\sdignissim venenatis pede. Quisque dui dui,
    \s\s\s\sultricies ut, facilisis non, pulvinar non."""
    
    class Test_TextWrapper:
        def test_stackoverflow_q32753000_1(self):
            sut = TextWrapper(width=50, subsequent_indent="\s\s\s\s")
            assert sut.fill(input_tx) == output_tx1
    
        def test_stackoverflow_q32753000_2(self):
            sut = TextWrapper(width=50, subsequent_indent="\s\s\s\s",
                              fix_sentence_endings=False,
                              break_on_hyphens=False)
            assert sut.fill(input_tx) == output_tx2
    

It should show you something like this:

    
    
    > py.test -v -k Test_TextWrapper 
    ============================================== test session starts ===============================================
    platform linux2 -- Python 2.7.11, pytest-2.9.0, py-1.4.31, pluggy-0.3.1 -- /usr/bin/python
    cachedir: .cache
    ...
    plugins: cov-2.2.1
    collected 6 items 
    
    test_fmt.py::Test_TextWrapper::test_stackoverflow_q32753000_1 PASSED
    test_fmt.py::Test_TextWrapper::test_stackoverflow_q32753000_2 PASSED
    
    =================================== 4 tests deselected by '-kTest_TextWrapper' ===================================
    ===================================== 2 passed, 4 deselected in 0.03 seconds =====================================
    

As you can see, my second test case produces the same output as shown in the
example of your question.

I'm currently writing a small Python wrapper class for Python standard library
`textwrap.TextWrapper` class. This derived class will provide a new `prefix`
keyword argument combining the effects of the `initial_indent` and the
`subsequent_indent` parameters with a removal of the prefix from the input
text. (Similar to what the `-p` option of the `fmt` utility program does)
While looking for prior art and inspiration I found your question here.

