/* This file is part of hugin. hugin 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. hugin 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 hugin. If not, see . */ /** * @file test_filenames.cpp * @brief Tester that tries to feed a lot of possible characters * as filenames into the makefilelib, make, and the filesystem. * * Created on: Jul 16, 2010 * @author Florian Achleitner */ #include "char_type.h" #include "Comment.h" #include "Variable.h" #include "VariableDef.h" #include "VariableRef.h" #include "MakefileItem.h" #include "Makefile.h" #include "AutoVariable.h" #include "Newline.h" #include "Rule.h" #include "Conditional.h" #include "StringAdapter.h" #include "test_util.h" #include #include using namespace makefile; using namespace makefile::tester; namespace fs = boost::filesystem; #ifdef USE_WCHAR ostream& cout = std::wcout; ostream& cerr = std::wcerr; #else ostream& cout = std::cout; ostream& cerr = std::cerr; #endif #define START 0x20 /** * Prints the tested characters. * @param out * @param limit */ void printchars(ostream& out, wchar_t limit) { char_type c; for(c = 0x20; c < limit; c++) { out << c; } } /** * Tries to create files with names from 0x20 to limit using boost::filesystem. * @param dir * @param limit Upper limit for filenames * @return Filenames that couldn't be found after creation. */ std::vector createfiles_direct(const path dir, uchar_type limit) { std::vector miss; char_type c[] = cstr("X.1"); for(*c = START; static_cast(*c) < limit; (*c)++) { path filename(c); ofstream file(dir / filename); file.close(); if(!fs::exists(dir / filename)) { miss.push_back(filename); } } return miss; } /** * Tries to create files with names from 0x20 to limit by calling make. * It first writes a makefile of this structure: @verbatim FILENAME=X.1 all : @touch $(FILENAME) @endverbatim * Afterwards make is called with system() and creates the file by executing touch. * * @param dir * @param limit Upper limit for filenames * @return Filenames that couldn't be found after creation. */ std::vector createfiles_make(const path dir, uchar_type limit) { const path makefile(cstr("makefile")); std::vector miss; char_type c[] = cstr("X.1"); for(*c = START; static_cast(*c) < limit; (*c)++) { path filename(c); // If the filename cannot be stored in a Variable, theres no chance to bring it through. try { makefile::Variable mffilename(cstr("FILENAME"), (dir / filename).string(), makefile::Makefile::SHELL); makefile::Rule touch; touch.addTarget(cstr("all")); touch.addCommand(cstr("@touch ") + mffilename.getRef().toString()); mffilename.getDef().add(); touch.add(); string dirstring = dir.string(); std::stringbuf makeout, makeerr; int ret = exec_make(makeout, makeerr); if(ret) { std::cerr << "make returned " << ret << std::endl; std::cout << makeout.str(); std::cerr << makeerr.str(); } } catch(std::exception& e) { std::cerr << "Variable exception: " << e.what() << std::endl; } if(!fs::exists(dir / filename)) { miss.push_back(filename); } } return miss; } /** * Removes and recreates the output directories. * @param dir * @return 0 on success, 1 on error. */ int cleandir(path dir) { if(fs::is_directory(dir)) fs::remove_all(dir); if(!fs::create_directories(dir)) { cerr << cstr("Error creating directory ") << dir.string() << std::endl; return 1; } return 0; } void printmiss(std::vector::iterator start, std::vector::iterator end) { for(std::vector::iterator i = start; i != end; i++) { string s = i->string(); unsigned long first = 0; first = static_cast(s[0]); cout << s << cstr("\t (0x") << std::hex << first << cstr(")\n"); } } int main(int argc, char *argv[]) { uchar_type limit; if(argc != 2) { std::cerr << "Specify a limit as first argument" << std::endl; return 1; }else{ limit = std::atoi(argv[1]); } std::cout << "Creating " << static_cast(limit) - START << " files in" << std::endl; path basepath(fs::initial_path() / cstr("chartest_direct")); path basepathmake(fs::initial_path() / cstr("chartest_make")); cout << basepath.string() << std::endl; cout << basepathmake.string() << std::endl; if(cleandir(basepath) || cleandir(basepathmake)) return 1; // ofstream outfile(basepath / cstr("tf.out")); // printchars(outfile, limit); std::vector miss_direct = createfiles_direct(basepath, limit); cout << cstr("Direct: Missing files ") << miss_direct.size() << std::endl; printmiss(miss_direct.begin(), miss_direct.end()); cout << std::endl; std::vector miss_make = createfiles_make(basepathmake, limit); cout << cstr("Make: Missing files ") << miss_make.size() << std::endl; printmiss(miss_make.begin(), miss_make.end()); cout << std::endl; return 0; }