gparted/tests/test_PipeCapture.cc

382 lines
13 KiB
C++
Raw Normal View History

/* Copyright (C) 2017 Mike Fleetwood
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* Test PipeCapture
*
* All the tests work by creating a pipe(3) and using a separate thread to write data into
* the pipe with PipeCapture running in the initial thread. Captured data is then checked
* that it either matches the input or different expected output depending on the features
* being tested.
*/
Move duplicated test code into shared modules (#220) Move common testing code which doesn't need linking with GParted objects into the common module. Move the remaining common code used to print GParted objects using the insertion operator (operator<<) into the insertion_operators module. Split the common code like this so that the operator<<(std::ostream&, const OperationDetail&) function is not included in test_PipeCapture and it is not forced to link with all the non-UI related GParted objects. The Automake manual provides guidance that when a header belongs to a single program it is recommended to be listed in the program's _SOURCES variable and for a directory only containing header files listing them in the noinst_HEADERS variable is the right variable to use [1]. However the guidance doesn't cover this case for common.h and insertion_operators.h; header files in a directory with other files and used by multiple programs. So just because we have gparted_core_OBJECTS (normal Makefile, not Automake special variable) listing objects to link with, choose to use noinst_HEADERS Automake variable to list needed headers. [1] GNU Automake manual, 9.2 Header files https://www.gnu.org/software/automake/manual/html_node/Headers.html "Usually, only header files that accompany installed libraries need to be installed. Headers used by programs or convenience libraries are not installed. The noinst_HEADERS variable can be used for such headers. However, when the header belongs to a single convenience library or program, we recommend listing it in the program's or library's _SOURCES variable (see Defining program sources) instead of in noinst_HEADERS. This is clearer for the Makefile.am reader. noinst_HEADERS would be the right variable to use in a directory containing only headers and no associated library or program. All header files must be listed somewhere; in a _SOURCES variable or in a _HEADERS variable. Missing ones will not appear in the distribution. " Closes #220 - Format to Cleared not clearing "pdc" ataraid signature
2023-02-05 04:16:43 -07:00
#include "common.h"
#include "PipeCapture.h"
#include "gtest/gtest.h"
#include <stddef.h>
#include <stdio.h>
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
2017-05-23 09:35:51 -06:00
#include <sstream>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <string>
#include <sigc++/sigc++.h>
#include <glib.h>
#include <glibmm.h>
namespace GParted
{
// Repeat a C++ string count times, where count >= 0.
static std::string repeat( const std::string & str, size_t count )
{
std::string result = "";
while ( count -- > 0 )
result += str;
return result;
}
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
2017-05-23 09:35:51 -06:00
// 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 )
{
Move duplicated test code into shared modules (#220) Move common testing code which doesn't need linking with GParted objects into the common module. Move the remaining common code used to print GParted objects using the insertion operator (operator<<) into the insertion_operators module. Split the common code like this so that the operator<<(std::ostream&, const OperationDetail&) function is not included in test_PipeCapture and it is not forced to link with all the non-UI related GParted objects. The Automake manual provides guidance that when a header belongs to a single program it is recommended to be listed in the program's _SOURCES variable and for a directory only containing header files listing them in the noinst_HEADERS variable is the right variable to use [1]. However the guidance doesn't cover this case for common.h and insertion_operators.h; header files in a directory with other files and used by multiple programs. So just because we have gparted_core_OBJECTS (normal Makefile, not Automake special variable) listing objects to link with, choose to use noinst_HEADERS Automake variable to list needed headers. [1] GNU Automake manual, 9.2 Header files https://www.gnu.org/software/automake/manual/html_node/Headers.html "Usually, only header files that accompany installed libraries need to be installed. Headers used by programs or convenience libraries are not installed. The noinst_HEADERS variable can be used for such headers. However, when the header belongs to a single convenience library or program, we recommend listing it in the program's or library's _SOURCES variable (see Defining program sources) instead of in noinst_HEADERS. This is clearer for the Makefile.am reader. noinst_HEADERS would be the right variable to use in a directory containing only headers and no associated library or program. All header files must be listed somewhere; in a _SOURCES variable or in a _HEADERS variable. Missing ones will not appear in the distribution. " Closes #220 - Format to Cleared not clearing "pdc" ataraid signature
2023-02-05 04:16:43 -07:00
size_t cmp_span = BinaryStringChunkSize;
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
2017-05-23 09:35:51 -06:00
cmp_span = ( len1 < cmp_span ) ? len1 : cmp_span;
cmp_span = ( len2 < cmp_span ) ? len2 : cmp_span;
Move duplicated test code into shared modules (#220) Move common testing code which doesn't need linking with GParted objects into the common module. Move the remaining common code used to print GParted objects using the insertion operator (operator<<) into the insertion_operators module. Split the common code like this so that the operator<<(std::ostream&, const OperationDetail&) function is not included in test_PipeCapture and it is not forced to link with all the non-UI related GParted objects. The Automake manual provides guidance that when a header belongs to a single program it is recommended to be listed in the program's _SOURCES variable and for a directory only containing header files listing them in the noinst_HEADERS variable is the right variable to use [1]. However the guidance doesn't cover this case for common.h and insertion_operators.h; header files in a directory with other files and used by multiple programs. So just because we have gparted_core_OBJECTS (normal Makefile, not Automake special variable) listing objects to link with, choose to use noinst_HEADERS Automake variable to list needed headers. [1] GNU Automake manual, 9.2 Header files https://www.gnu.org/software/automake/manual/html_node/Headers.html "Usually, only header files that accompany installed libraries need to be installed. Headers used by programs or convenience libraries are not installed. The noinst_HEADERS variable can be used for such headers. However, when the header belongs to a single convenience library or program, we recommend listing it in the program's or library's _SOURCES variable (see Defining program sources) instead of in noinst_HEADERS. This is clearer for the Makefile.am reader. noinst_HEADERS would be the right variable to use in a directory containing only headers and no associated library or program. All header files must be listed somewhere; in a _SOURCES variable or in a _HEADERS variable. Missing ones will not appear in the distribution. " Closes #220 - Format to Cleared not clearing "pdc" ataraid signature
2023-02-05 04:16:43 -07:00
if (cmp_span < BinaryStringChunkSize && len1 != len2)
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
2017-05-23 09:35:51 -06:00
{
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"
Move duplicated test code into shared modules (#220) Move common testing code which doesn't need linking with GParted objects into the common module. Move the remaining common code used to print GParted objects using the insertion operator (operator<<) into the insertion_operators module. Split the common code like this so that the operator<<(std::ostream&, const OperationDetail&) function is not included in test_PipeCapture and it is not forced to link with all the non-UI related GParted objects. The Automake manual provides guidance that when a header belongs to a single program it is recommended to be listed in the program's _SOURCES variable and for a directory only containing header files listing them in the noinst_HEADERS variable is the right variable to use [1]. However the guidance doesn't cover this case for common.h and insertion_operators.h; header files in a directory with other files and used by multiple programs. So just because we have gparted_core_OBJECTS (normal Makefile, not Automake special variable) listing objects to link with, choose to use noinst_HEADERS Automake variable to list needed headers. [1] GNU Automake manual, 9.2 Header files https://www.gnu.org/software/automake/manual/html_node/Headers.html "Usually, only header files that accompany installed libraries need to be installed. Headers used by programs or convenience libraries are not installed. The noinst_HEADERS variable can be used for such headers. However, when the header belongs to a single convenience library or program, we recommend listing it in the program's or library's _SOURCES variable (see Defining program sources) instead of in noinst_HEADERS. This is clearer for the Makefile.am reader. noinst_HEADERS would be the right variable to use in a directory containing only headers and no associated library or program. All header files must be listed somewhere; in a _SOURCES variable or in a _HEADERS variable. Missing ones will not appear in the distribution. " Closes #220 - Format to Cleared not clearing "pdc" ataraid signature
2023-02-05 04:16:43 -07:00
<< "< " << binary_string_to_print(offset, p1, len1) << "\n"
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
2017-05-23 09:35:51 -06:00
<< "--\n"
Move duplicated test code into shared modules (#220) Move common testing code which doesn't need linking with GParted objects into the common module. Move the remaining common code used to print GParted objects using the insertion operator (operator<<) into the insertion_operators module. Split the common code like this so that the operator<<(std::ostream&, const OperationDetail&) function is not included in test_PipeCapture and it is not forced to link with all the non-UI related GParted objects. The Automake manual provides guidance that when a header belongs to a single program it is recommended to be listed in the program's _SOURCES variable and for a directory only containing header files listing them in the noinst_HEADERS variable is the right variable to use [1]. However the guidance doesn't cover this case for common.h and insertion_operators.h; header files in a directory with other files and used by multiple programs. So just because we have gparted_core_OBJECTS (normal Makefile, not Automake special variable) listing objects to link with, choose to use noinst_HEADERS Automake variable to list needed headers. [1] GNU Automake manual, 9.2 Header files https://www.gnu.org/software/automake/manual/html_node/Headers.html "Usually, only header files that accompany installed libraries need to be installed. Headers used by programs or convenience libraries are not installed. The noinst_HEADERS variable can be used for such headers. However, when the header belongs to a single convenience library or program, we recommend listing it in the program's or library's _SOURCES variable (see Defining program sources) instead of in noinst_HEADERS. This is clearer for the Makefile.am reader. noinst_HEADERS would be the right variable to use in a directory containing only headers and no associated library or program. All header files must be listed somewhere; in a _SOURCES variable or in a _HEADERS variable. Missing ones will not appear in the distribution. " Closes #220 - Format to Cleared not clearing "pdc" ataraid signature
2023-02-05 04:16:43 -07:00
<< "> " << binary_string_to_print(offset, p2, len2);
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
2017-05-23 09:35:51 -06:00
}
}
// 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.
// Reference:
// Google Test, Primer, Test Fixtures: Using the Same Data Configuration for Multiple Tests
class PipeCaptureTest : public ::testing::Test
{
protected:
PipeCaptureTest() : capturedstr( "text to be replaced" ),
eof_signalled( false ), update_signalled( 0U ) {};
virtual void SetUp();
virtual void TearDown();
static gboolean main_loop_quit( gpointer data );
void writer_thread( const std::string & str );
void run_writer_thread();
static const size_t ReaderFD = 0;
static const size_t WriterFD = 1;
std::string inputstr;
std::string expectedstr;
Glib::ustring capturedstr;
bool eof_signalled;
unsigned update_signalled;
int pipefds[2];
Glib::RefPtr<Glib::MainLoop> glib_main_loop;
public:
void eof_callback() { eof_signalled = true; };
void update_callback_leading_match();
};
// Further setup PipeCaptureTest fixture before running each test. Create pipe and Glib
// main loop object.
void PipeCaptureTest::SetUp()
{
ASSERT_TRUE( pipe( pipefds ) == 0 ) << "Failed to create pipe. errno="
<< errno << "," << strerror( errno );
glib_main_loop = Glib::MainLoop::create();
}
// Tear down fixture after running each test. Close reading end of the pipe. Also
// re-closed the writing end of the pipe, just in case something went wrong in the test.
void PipeCaptureTest::TearDown()
{
ASSERT_TRUE( close( pipefds[ReaderFD] ) == 0 ) << "Failed to close reading end of pipe. errno="
<< errno << "," << strerror( errno );
close( pipefds[WriterFD] );
}
// Callback used to end the currently running Glib main loop.
gboolean PipeCaptureTest::main_loop_quit( gpointer data )
{
static_cast<PipeCaptureTest *>( data )->glib_main_loop->quit();
return false; // One shot g_idle_add() callback
}
// Write the string into the pipe and close the pipe for writing. Registers callback to
// end the currently running Glib main loop.
void PipeCaptureTest::writer_thread( const std::string & str )
{
const size_t BlockSize = 4096;
const char * writebuf = str.data();
size_t remaining_size = str.length();
while ( remaining_size > 0 )
{
size_t write_size = ( remaining_size > BlockSize ) ? BlockSize : remaining_size;
ssize_t written = write( pipefds[WriterFD], writebuf, write_size );
if ( written <= 0 )
{
ADD_FAILURE() << __func__ << "(): Failed to write to pipe. errno="
<< errno << "," << strerror( errno );
break;
}
remaining_size -= written;
writebuf += written;
}
ASSERT_TRUE( close( pipefds[WriterFD] ) == 0 ) << "Failed to close writing end of pipe. errno="
<< errno << "," << strerror( errno );
g_idle_add( main_loop_quit, this );
}
// Create writer thread and run the Glib main loop.
void PipeCaptureTest::run_writer_thread()
{
Glib::Thread::create( sigc::bind( sigc::mem_fun( *this, &PipeCaptureTest::writer_thread ),
inputstr ),
false );
glib_main_loop->run();
}
// Callback fired from CapturePipe counting calls and ensuring captured string matches
// leading portion of input string.
void PipeCaptureTest::update_callback_leading_match()
{
update_signalled ++;
EXPECT_BINARYSTRINGEQ( inputstr.substr( 0, capturedstr.raw().length() ),
capturedstr.raw() );
if ( HasFailure() )
// No point trying to PipeCapture the rest of the input and report
// hundreds of further failures in the same test, so end the currently
// running Glib main loop immediately.
// References:
// * Google Test, AdvancedGuide, Propagating Fatal Failures
// * Google Test, AdvancedGuide, Checking for Failures in the Current Test
glib_main_loop->quit();
}
TEST_F( PipeCaptureTest, EmptyPipe )
{
// Test capturing 0 bytes with no on EOF callback registered.
inputstr = "";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.connect_signal();
run_writer_thread();
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
2017-05-23 09:35:51 -06:00
EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_FALSE( eof_signalled );
}
TEST_F( PipeCaptureTest, EmptyPipeWithEOF )
{
// Test capturing 0 bytes and registered on EOF callback occurs.
inputstr = "";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal();
run_writer_thread();
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
2017-05-23 09:35:51 -06:00
EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled );
}
TEST_F( PipeCaptureTest, ShortASCIIText )
{
// Test capturing small amount of ASCII text.
inputstr = "The quick brown fox jumps over the lazy dog";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal();
run_writer_thread();
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
2017-05-23 09:35:51 -06:00
EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled );
}
TEST_F( PipeCaptureTest, LongASCIIText )
{
// Test capturing 1 MiB of ASCII text (requiring multiple reads in PipeCapture).
inputstr = repeat( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_\n", 16384 );
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal();
run_writer_thread();
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
2017-05-23 09:35:51 -06:00
EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled );
}
TEST_F( PipeCaptureTest, LongASCIITextWithUpdate )
{
// Test capturing 1 MiB of ASCII text, that registered update callback occurs and
// intermediate captured string is a leading match for the input string.
inputstr = repeat( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_\n", 16384 );
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.signal_update.connect( sigc::mem_fun( *this, &PipeCaptureTest::update_callback_leading_match ) );
pc.connect_signal();
run_writer_thread();
EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_GT( update_signalled, 0U );
EXPECT_TRUE( eof_signalled );
}
Add test for bug with PipeCapture crashing reading binary data (#777973) A user had a very corrupt FAT file system and fsck.fat was reporting binary data in file names with errors. GParted crashed reading this output. Boiled down the problematic fsck.fat output to a sample 27 bytes which still triggers a crash and created a test for it. The test crashes test_PipeCapture program too. $ ./test_PipeCapture ... [ RUN ] PipeCaptureTest.MinimalBinaryCrash777973 Segmentation fault (core dumped) $ echo $? 139 However it still produces a non-zero exit status and the autotools test runner detects this so 'make check' still reports failure. $ make check ... make[2]: Entering directory `/home/centos/programming/c/gparted/tests' PASS: test_dummy PASS: test_BlockSpecial ../test-driver: line 95: 16152 Segmentation fault "$@" > $log_file 2>&1 FAIL: test_PipeCapture ... ============================================================================ Testsuite summary for gparted 0.28.1-git ============================================================================ # TOTAL: 3 # PASS: 2 # SKIP: 0 # XFAIL: 0 # FAIL: 1 # XPASS: 0 # ERROR: 0 ============================================================================ See tests/test-suite.log Please report to https://bugzilla.gnome.org/enter_bug.cgi?product=gparted ============================================================================ make[2]: *** [test-suite.log] Error 1 make[2]: Leaving directory `/home/centos/programming/c/gparted/tests' make[1]: *** [check-TESTS] Error 2 make[1]: Leaving directory `/home/centos/programming/c/gparted/tests' make: *** [check-am] Error 2 $ echo $? 2 Bug 777973 - Segmentation fault on bad disk
2017-05-24 06:35:44 -06:00
TEST_F( PipeCaptureTest, MinimalBinaryCrash777973 )
{
// Test for bug #777973. Minimal test case of binary data returned by fsck.fat
// as file names from a very corrupt FAT, leading to GParted crashing from a
// segmentation fault.
inputstr = "/LOST.DIR/!\xE2\x95\x9F\xE2\x88\xA9\xC2\xA0!\xE2\x95\x9F\xE2\x88\xA9\xC2";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal();
run_writer_thread();
// Final \xC2 byte is part of an incomplete UTF-8 character so will be skipped by
// PipeCapture.
expectedstr = "/LOST.DIR/!\xE2\x95\x9F\xE2\x88\xA9\xC2\xA0!\xE2\x95\x9F\xE2\x88\xA9";
EXPECT_BINARYSTRINGEQ( expectedstr, capturedstr.raw() );
Add test for bug with PipeCapture crashing reading binary data (#777973) A user had a very corrupt FAT file system and fsck.fat was reporting binary data in file names with errors. GParted crashed reading this output. Boiled down the problematic fsck.fat output to a sample 27 bytes which still triggers a crash and created a test for it. The test crashes test_PipeCapture program too. $ ./test_PipeCapture ... [ RUN ] PipeCaptureTest.MinimalBinaryCrash777973 Segmentation fault (core dumped) $ echo $? 139 However it still produces a non-zero exit status and the autotools test runner detects this so 'make check' still reports failure. $ make check ... make[2]: Entering directory `/home/centos/programming/c/gparted/tests' PASS: test_dummy PASS: test_BlockSpecial ../test-driver: line 95: 16152 Segmentation fault "$@" > $log_file 2>&1 FAIL: test_PipeCapture ... ============================================================================ Testsuite summary for gparted 0.28.1-git ============================================================================ # TOTAL: 3 # PASS: 2 # SKIP: 0 # XFAIL: 0 # FAIL: 1 # XPASS: 0 # ERROR: 0 ============================================================================ See tests/test-suite.log Please report to https://bugzilla.gnome.org/enter_bug.cgi?product=gparted ============================================================================ make[2]: *** [test-suite.log] Error 1 make[2]: Leaving directory `/home/centos/programming/c/gparted/tests' make[1]: *** [check-TESTS] Error 2 make[1]: Leaving directory `/home/centos/programming/c/gparted/tests' make: *** [check-am] Error 2 $ echo $? 2 Bug 777973 - Segmentation fault on bad disk
2017-05-24 06:35:44 -06:00
EXPECT_TRUE( eof_signalled );
}
TEST_F( PipeCaptureTest, ReadEmbeddedNULCharacter )
{
// Test embedded NUL character in the middle of the input is read correctly.
const char * buf = "ABC\0EF";
inputstr = std::string( buf, 6 );
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal();
run_writer_thread();
EXPECT_BINARYSTRINGEQ( inputstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled );
}
TEST_F( PipeCaptureTest, ReadNULByteInMiddleOfMultiByteUTF8Character )
{
// Test NUL byte in the middle of reading a multi-byte UTF-8 character.
const char * buf = "\xC0\x00_45678";
inputstr = std::string( buf, 8 );
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.signal_eof.connect( sigc::mem_fun( *this, &PipeCaptureTest::eof_callback ) );
pc.connect_signal();
run_writer_thread();
// Initial \xC0 byte is part of an incomplete UTF-8 characters so will be skipped
// by PipeCapture.
buf = "\x00_45678";
expectedstr = std::string( buf, 7 );
EXPECT_BINARYSTRINGEQ( expectedstr, capturedstr.raw() );
EXPECT_TRUE( eof_signalled );
}
TEST_F( PipeCaptureTest, LineDisciplineCarriageReturn )
{
// Test PipeCapture line discipline processes carriage return character.
inputstr = "1111\n2222\r33";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.connect_signal();
run_writer_thread();
expectedstr = "1111\n3322";
EXPECT_BINARYSTRINGEQ( expectedstr, capturedstr.raw() );
}
TEST_F( PipeCaptureTest, LineDisciplineCarriageReturn2 )
{
// Test PipeCapture line discipline processes multiple carriage return characters.
inputstr = "1111\n2222\r33\r\r4";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.connect_signal();
run_writer_thread();
expectedstr = "1111\n4322";
EXPECT_BINARYSTRINGEQ( expectedstr, capturedstr.raw() );
}
TEST_F( PipeCaptureTest, LineDisciplineBackspace )
{
// Test PipeCapture line discipline processes backspace character.
inputstr = "1111\n2222\b33";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.connect_signal();
run_writer_thread();
expectedstr = "1111\n22233";
EXPECT_BINARYSTRINGEQ( expectedstr, capturedstr.raw() );
}
TEST_F( PipeCaptureTest, LineDisciplineBackspace2 )
{
// Test PipeCapture line discipline processes too many backspace characters moving
// the cursor back only to the beginning of the current line.
inputstr = "1111\n2222\b\b\b\b\b\b33\b4";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.connect_signal();
run_writer_thread();
expectedstr = "1111\n3422";
EXPECT_BINARYSTRINGEQ( expectedstr, capturedstr.raw() );
}
TEST_F( PipeCaptureTest, LineDisciplineSkipCtrlAB )
{
// Test PipeCapture line discipline skips Ctrl-A and Ctrl-B.
inputstr = "ij\x01kl\x02mn";
PipeCapture pc( pipefds[ReaderFD], capturedstr );
pc.connect_signal();
run_writer_thread();
expectedstr = "ijklmn";
EXPECT_BINARYSTRINGEQ( expectedstr, capturedstr.raw() );
}
} // namespace GParted