[gparted] Add initial unit tests for PipeCapture (#777973)



commit b21ee06230adf8b9f4090eef7b46c179f8e26d42
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Fri May 12 22:00:08 2017 +0100

    Add initial unit tests for PipeCapture (#777973)
    
    So far just tests sending 0 bytes and a few ASCII bytes into a pipe and
    that they are read correctly by the PipeCapture class.
    
    Bug 777973 - Segmentation fault on bad disk

 .gitignore                |    1 +
 tests/Makefile.am         |    4 +-
 tests/test_PipeCapture.cc |  161 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 165 insertions(+), 1 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 0b30ece..a8e339b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,5 +50,6 @@ tests/*.log
 tests/*.trs
 tests/test-suite.log
 tests/test_BlockSpecial
+tests/test_PipeCapture
 tests/test_dummy
 xmldocs.make
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 07b0199..8fb91f3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -12,10 +12,12 @@ LDADD =  \
 # Programs to be built by "make check"
 check_PROGRAMS =  \
        test_dummy         \
-       test_BlockSpecial
+       test_BlockSpecial  \
+       test_PipeCapture
 
 # Test cases to be run by "make check"
 TESTS = $(check_PROGRAMS)
 
 test_dummy_SOURCES        = test_dummy.cc
 test_BlockSpecial_SOURCES = test_BlockSpecial.cc ../src/BlockSpecial.cc
+test_PipeCapture_SOURCES  = test_PipeCapture.cc ../src/PipeCapture.cc
diff --git a/tests/test_PipeCapture.cc b/tests/test_PipeCapture.cc
new file mode 100644
index 0000000..b77369c
--- /dev/null
+++ b/tests/test_PipeCapture.cc
@@ -0,0 +1,161 @@
+/* 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 matches the input.
+ */
+
+#include "PipeCapture.h"
+#include "gtest/gtest.h"
+
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <string>
+#include <sigc++/sigc++.h>
+#include <glib.h>
+#include <glibmm.h>
+
+namespace GParted
+{
+
+// 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() : eof_signalled( false )  {};
+
+       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;
+       Glib::ustring capturedstr;
+       bool eof_signalled;
+       int pipefds[2];
+       Glib::RefPtr<Glib::MainLoop> glib_main_loop;
+
+public:
+       void eof_callback()  { eof_signalled = true; };
+};
+
+// 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();
+}
+
+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();
+       EXPECT_STREQ( inputstr.c_str(), capturedstr.c_str() );
+       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();
+       EXPECT_STREQ( inputstr.c_str(), capturedstr.c_str() );
+       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();
+       EXPECT_STREQ( inputstr.c_str(), capturedstr.c_str() );
+       EXPECT_TRUE( eof_signalled );
+}
+
+}  // namespace GParted


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]