test_util.cpp

Go to the documentation of this file.
00001 /*
00002 This file is part of hugin.
00003 
00004 hugin is free software: you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation, either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 hugin is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with hugin.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00017 
00025 #include <iostream>
00026 #include <stdexcept>
00027 #include <sstream>
00028 #include <cstdio>
00029 #include <sys/wait.h>
00030 #include <iomanip>
00031 #include "Makefile.h"
00032 #include "test_util.h"
00033 
00034 #include <boost/iostreams/stream.hpp>
00035 #include <boost/iostreams/device/file_descriptor.hpp>
00036 #include <boost/iostreams/code_converter.hpp>
00037 
00038 using namespace makefile;
00039 namespace fs = boost::filesystem;
00040 namespace io = boost::iostreams;
00041 
00042 namespace makefile { namespace tester {
00050 int exec_make(std::stringbuf& makeoutbuf, std::stringbuf& makeerrbuf)
00051 {
00052         // store 2 fd per pipe {read, write}
00053         int fdmakein[2];
00054         int fdmakeout[2];
00055         int fdmakeerr[2];
00056         if(pipe(fdmakein) || pipe(fdmakeout) || pipe(fdmakeerr))
00057         {
00058                 std::cerr << "pipe() failed." << std::endl;
00059                 return false;
00060         }
00061 
00062 
00063         if(fork())
00064         { // parent
00065                 close(fdmakein[0]);
00066                 close(fdmakeout[1]);
00067                 close(fdmakeerr[1]);
00068 
00069                 // boost gives us a way to use those pipes in C++ style.
00070                 // the code_converter allows wchar mode Makefile to be written to a char-pipe
00071 #ifdef USE_WCHAR
00072                 io::stream< io::code_converter<io::file_descriptor_sink> > makein(fdmakein[1]);
00073 #else
00074                 io::stream<io::file_descriptor_sink> makein(fdmakein[1]);
00075 #endif
00076                 io::stream<io::file_descriptor_source> makeout(fdmakeout[0]);
00077                 io::stream<io::file_descriptor_source> makeerr(fdmakeerr[0]);
00078 
00079                 // Write the makefile to make's stdin
00080                 Makefile::getSingleton().writeMakefile(makein);
00081                 Makefile::getSingleton().clean();
00082                 makein.close();
00083 
00084                 makeout.get(makeoutbuf, '\0');  // delimiter \0 should read until eof.
00085                 makeerr.get(makeerrbuf, '\0');
00086 
00087                 int status;
00088                 wait(&status);                  // status contains return value an some other flags
00089                 if(WIFEXITED(status))   // that can be evaluated by these macros (man wait)
00090                 {
00091                         return WEXITSTATUS(status);
00092                 }
00093                 // If WIFEXITED is false, something complicated happened (signal etc..).
00094                 std::cerr << "Command terminated abnormally. status=" << std::hex << status << std::endl;
00095                 return status;
00096 
00097 
00098         } else { // child
00099                 close(fdmakein[1]);
00100                 close(fdmakeout[0]);
00101                 close(fdmakeerr[0]);
00102                 // replace stdin and stdout
00103                 if(dup2(fdmakein[0], 0) == -1 || dup2(fdmakeout[1], 1) == -1 || dup2(fdmakeerr[1], 2) == -1)
00104                 {
00105                         std::cerr << "Failed to switch std stream" << std::endl;
00106                         exit(-1);
00107                 }
00108 
00109                 // execvp takes a NULL-terminated array of null-terminated strings. cool ;)
00110                 const char* const argv[] = {"make", "-f-", (char*) NULL};
00111                 execvp(argv[0], (char* const*)argv);
00112                 return -1;              // exec should never return
00113         }
00114 }
00115 
00116 bool Test::run()
00117 {
00118         int status = exec_make(makeoutbuf, makeerrbuf);
00119 
00120         std::cout << std::setw(30) << std::left <<  name;
00121         if(eval())
00122         {
00123                 std::cout << "PASS" << std::endl;
00124                 return true;
00125         }
00126         std::cout << "FAIL" << std::endl;
00127         std::cout << "ret: " << status << std::endl;
00128         std::cout << "out: " << makeoutbuf.str() << std::endl;
00129         std::cout << "cmp: " << goodout << std::endl;
00130         std::cout << "err: " << makeerrbuf.str() << std::endl;
00131         return false;
00132 }
00133 }}

Generated on 22 Oct 2014 for Hugintrunk by  doxygen 1.4.7