Add binary data string difference reporting to PipeCapture tests (#777973)

Google Test string comparison asserts are only designed of C style
strings containing printable text of one or more lines with a
terminating NUL character.  GParted is crashing when PipeCapture is
reading the binary file names being reported by fsck.fat from a very
corrupted FAT file system.  Therefore need to be able to compare and
report differences of binary data stored in C++ std::string and
Glib::ustrings.  Write a specific assertion to handle this.

Now these sample tests:

    TEST_F( PipeCaptureTest, BinaryStringFailure )
    {
        inputstr = "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC";
        capturedstr = "AAAAAAAAAAAAAAAABBBBBBBBBBbbbb";
        EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
    }

    TEST_F( PipeCaptureTest, LeadingBinaryStringFailure )
    {
        inputstr = "The quick brown fox jumps over the lazy dog";
        capturedstr = "The quick brown fox\n";
        EXPECT_BINARYSTRINGEQ( inputstr.substr( 0, capturedstr.raw().length() ),
                               capturedstr.raw() );
    }

report failure like this:

    $ ./test_PipeCapture
    ...

    [ RUN      ] PipeCaptureTest.BinaryStringFailure
    test_PipeCapture.cc:270: Failure
          Expected: inputstr
         Of length: 48
    To be equal to: capturedstr.raw()
         Of length: 30
    With first binary difference:
    < 0x00000010  "BBBBBBBBBBBBBBBB"  42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42
    --
    > 0x00000010  "BBBBBBBBBBbbbb"    42 42 42 42 42 42 42 42 42 42 62 62 62 62
    [  FAILED  ] PipeCaptureTest.BinaryStringFailure (1 ms)
    [ RUN      ] PipeCaptureTest.LeadingBinaryStringFailure
    test_PipeCapture.cc:278: Failure
          Expected: inputstr.substr( 0, capturedstr.raw().length() )
         Of length: 20
    To be equal to: capturedstr.raw()
         Of length: 20
    With first binary difference:
    < 0x00000010  "fox "              66 6F 78 20
    --
    > 0x00000010  "fox."              66 6F 78 0A
    [  FAILED  ] PipeCaptureTest.LeadingBinaryStringFailure (0 ms)
    ...

Bug 777973 - Segmentation fault on bad disk
This commit is contained in:
Mike Fleetwood 2017-05-23 16:35:51 +01:00 committed by Curtis Gedak
parent eb2d571a6c
commit dc1c49ba62
1 changed files with 94 additions and 4 deletions

View File

@ -26,6 +26,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <sstream>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@ -46,6 +47,95 @@ static std::string repeat( const std::string & str, size_t count )
return result; return result;
} }
// Number of bytes of binary data to compare and report.
const size_t BinaryStringDiffSize = 16;
// Format up to 16 bytes of binary data ready for printing as:
// Hex offset ASCII text Hex bytes
// "0x000000000 \"ABCDEFGHabcdefgh\" 41 42 43 44 45 46 47 48 61 62 63 64 65 66 67 68"
std::string BinaryStringToPrint( size_t offset, const char * s, size_t len )
{
std::ostringstream result;
result << "0x";
result.fill( '0' );
result << std::setw( 8 ) << std::hex << std::uppercase << offset << " \"";
size_t i;
for ( i = 0 ; i < BinaryStringDiffSize && i < len ; i ++ )
result.put( ( isprint( s[i] ) ) ? s[i] : '.' );
result.put( '\"' );
if ( len > 0 )
{
for ( ; i < BinaryStringDiffSize ; i ++ )
result.put( ' ' );
result.put( ' ' );
for ( i = 0 ; i < BinaryStringDiffSize && i < len ; i ++ )
result << " "
<< std::setw( 2 ) << std::hex << std::uppercase
<< (unsigned int)(unsigned char)s[i];
}
return result.str();
}
// Helper to construct and return message for equality assertion of C++ strings containing
// binary data used in:
// EXPECT_BINARYSTRINGEQ( str1, str2 )
::testing::AssertionResult CompareHelperBinaryStringEQ( const char * lhs_expr, const char * rhs_expr,
const std::string & lhs, const std::string & rhs )
{
// Loop comparing binary data in 16 byte amounts, stopping and reporting the first
// difference encountered.
bool diff = false;
const char * p1 = lhs.data();
const char * p2 = rhs.data();
size_t len1 = lhs.length();
size_t len2 = rhs.length();
while ( len1 > 0 || len2 > 0 )
{
size_t cmp_span = BinaryStringDiffSize;
cmp_span = ( len1 < cmp_span ) ? len1 : cmp_span;
cmp_span = ( len2 < cmp_span ) ? len2 : cmp_span;
if ( cmp_span < BinaryStringDiffSize && len1 != len2 )
{
diff = true;
break;
}
if ( memcmp( p1, p2, cmp_span ) != 0 )
{
diff = true;
break;
}
p1 += cmp_span;
p2 += cmp_span;
len1 -= cmp_span;
len2 -= cmp_span;
}
if ( ! diff )
return ::testing::AssertionSuccess();
else
{
size_t offset = p1 - lhs.data();
return ::testing::AssertionFailure()
<< " Expected: " << lhs_expr << "\n"
<< " Of length: " << lhs.length() << "\n"
<< "To be equal to: " << rhs_expr << "\n"
<< " Of length: " << rhs.length() << "\n"
<< "With first binary difference:\n"
<< "< " << BinaryStringToPrint( offset, p1, len1 ) << "\n"
<< "--\n"
<< "> " << BinaryStringToPrint( offset, p2, len2 );
}
}
// Nonfatal assertion that binary data in C++ strings are equal.
#define EXPECT_BINARYSTRINGEQ(str1, str2) \
EXPECT_PRED_FORMAT2(CompareHelperBinaryStringEQ, str1, str2)
// Explicit test fixture class with common variables and methods used in each test. // Explicit test fixture class with common variables and methods used in each test.
// Reference: // Reference:
// Google Test, Primer, Test Fixtures: Using the Same Data Configuration for Multiple Tests // Google Test, Primer, Test Fixtures: Using the Same Data Configuration for Multiple Tests
@ -140,7 +230,7 @@ TEST_F( PipeCaptureTest, EmptyPipe )
PipeCapture pc( pipefds[ReaderFD], capturedstr ); PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.connect_signal(); pc.connect_signal();
run_writer_thread(); run_writer_thread();
EXPECT_STREQ( inputstr.c_str(), capturedstr.c_str() ); EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_FALSE( eof_signalled ); EXPECT_FALSE( eof_signalled );
} }
@ -152,7 +242,7 @@ TEST_F( PipeCaptureTest, EmptyPipeWithEOF )
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) ); pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal(); pc.connect_signal();
run_writer_thread(); run_writer_thread();
EXPECT_STREQ( inputstr.c_str(), capturedstr.c_str() ); EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled ); EXPECT_TRUE( eof_signalled );
} }
@ -164,7 +254,7 @@ TEST_F( PipeCaptureTest, ShortASCIIText )
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) ); pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal(); pc.connect_signal();
run_writer_thread(); run_writer_thread();
EXPECT_STREQ( inputstr.c_str(), capturedstr.c_str() ); EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled ); EXPECT_TRUE( eof_signalled );
} }
@ -176,7 +266,7 @@ TEST_F( PipeCaptureTest, LongASCIIText )
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) ); pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal(); pc.connect_signal();
run_writer_thread(); run_writer_thread();
EXPECT_STREQ( inputstr.c_str(), capturedstr.c_str() ); EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled ); EXPECT_TRUE( eof_signalled );
} }