diff --git a/Test/Applications/x2tTester/README.md b/Test/Applications/x2tTester/README.md index ae811d656d..b513096fc1 100644 --- a/Test/Applications/x2tTester/README.md +++ b/Test/Applications/x2tTester/README.md @@ -9,14 +9,17 @@ You need to create an xml configuration file. It must contain: # report.csv path - # folder with test documents - + # directory with test documents + - # results folder - + # results directory + # path to x2t + + # num cores to use + You can use the following template: @@ -24,9 +27,10 @@ You can use the following template: - - + + + USAGE diff --git a/Test/Applications/x2tTester/main.cpp b/Test/Applications/x2tTester/main.cpp index a420c08317..64ae8f84b5 100644 --- a/Test/Applications/x2tTester/main.cpp +++ b/Test/Applications/x2tTester/main.cpp @@ -12,16 +12,24 @@ int wmain(int argc, wchar_t** argv) int main(int argc, char** argv) #endif { +#ifdef _WIN32 + UINT currConsoleCP = GetConsoleOutputCP(); + SetConsoleOutputCP(CP_UTF8); +#endif + std::wstring config_path; if(argc < 2) config_path = L"./config.xml"; else config_path = std::wstring(argv[1]); + SetConsoleOutputCP(CP_UTF8); + Cx2tTester tester(config_path); tester.Start(); +#ifdef _WIN32 + SetConsoleOutputCP(currConsoleCP); +#endif + return 0; } -// linux support -// multitask -// etc.. diff --git a/Test/Applications/x2tTester/x2tTester.cpp b/Test/Applications/x2tTester/x2tTester.cpp index cdbabf3bda..a9fa6aa389 100644 --- a/Test/Applications/x2tTester/x2tTester.cpp +++ b/Test/Applications/x2tTester/x2tTester.cpp @@ -1,23 +1,13 @@ #include "x2tTester.h" #include "../../../X2tConverter/src/run.h" -struct FormatsList +struct FormatsList; +class Cx2tTester; +class CConverter; + +FormatsList::FormatsList() { -public: - std::vector documents; - std::vector presentations; - std::vector spreadsheets; - std::vector crossplatform; - std::vector images; - - FormatsList(); - - bool isDocoment(int format); - bool isPresentation(int format); - bool isSpreadsheet(int format); - bool isCrossplatform(int format); - bool isImage(int format); -}; +} bool FormatsList::isDocoment(int format) { @@ -40,7 +30,7 @@ bool FormatsList::isImage(int format) return std::find(images.begin(), images.end(), format) != images.end(); } -FormatsList::FormatsList() +void FormatsList::SetDefault() { documents.push_back(AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX); documents.push_back(AVS_OFFICESTUDIO_FILE_DOCUMENT_DOC); @@ -86,166 +76,36 @@ FormatsList::FormatsList() images.push_back(AVS_OFFICESTUDIO_FILE_IMAGE_PNG); } -Cx2tTester::Cx2tTester(std::wstring configPath) + +Cx2tTester::Cx2tTester(const std::wstring& configPath) { m_bIsUseSystemFonts = true; setConfig(configPath); - m_xmlParams = m_outputFolder + L"/params.xml"; + if(NSFile::CFileBinary::Exists(m_reportFile)) + NSFile::CFileBinary::Remove(m_reportFile); - // todo check - m_reportStream.open(m_reportPath); - if(!m_reportStream.is_open()) + if(!m_reportStream.CreateFileW(m_reportFile)) { std::wcerr << "Report file is not open!" << std::endl; exit(-1); } + + m_coresCS.InitializeCriticalSection(); + m_reportCS.InitializeCriticalSection(); + m_outputCS.InitializeCriticalSection(); + + m_currentProc = 0; setReportHeader(); } Cx2tTester::~Cx2tTester() { - m_reportStream.close(); -} + m_coresCS.DeleteCriticalSection(); + m_reportCS.DeleteCriticalSection(); + m_outputCS.DeleteCriticalSection(); -void Cx2tTester::Start() -{ - // check fonts - std::wstring sFontsDirectory = NSFile::GetProcessDirectory() + L"/fonts"; - CApplicationFontsWorker oWorker; - oWorker.m_sDirectory = sFontsDirectory; - if (!NSDirectory::Exists(oWorker.m_sDirectory)) - NSDirectory::CreateDirectory(oWorker.m_sDirectory); - - oWorker.m_bIsUseSystemFonts = m_bIsUseSystemFonts; - - for (std::vector::iterator i = m_arAdditionalFontsDirs.begin(); i != m_arAdditionalFontsDirs.end(); i++) - oWorker.m_arAdditionalFolders.push_back(*i); - - oWorker.m_bIsNeedThumbnails = false; - NSFonts::IApplicationFonts* pFonts = oWorker.Check(); - RELEASEINTERFACE(pFonts); - - // setup & clear output folder - if(NSDirectory::Exists(m_outputFolder)) - NSDirectory::DeleteDirectory(m_outputFolder); - - NSDirectory::CreateDirectory(m_outputFolder); - - std::vector files = NSDirectory::GetFiles(m_inputFolder, false); - COfficeFileFormatChecker checker; - - FormatsList formatsList; - - for(std::wstring& file : files) - { - // setup folder for output files - std::wstring output_files_folder = m_outputFolder + L'/' + NSFile::GetFileName(file); - - if(NSDirectory::Exists(output_files_folder)) - NSDirectory::DeleteDirectory(output_files_folder); - - NSDirectory::CreateDirectory(output_files_folder); - - std::wstring input_ext = NSFile::GetFileExtention(file); - int input_format = COfficeFileFormatChecker::GetFormatByExtension(L'.' + input_ext); - - // setup output_formats - std::vector output_formats; - - if(formatsList.isDocoment(input_format)) - output_formats = formatsList.documents; - - if(formatsList.isPresentation(input_format)) - output_formats = formatsList.presentations; - - if(formatsList.isSpreadsheet(input_format)) - output_formats = formatsList.spreadsheets; - - for(auto it : formatsList.crossplatform) - output_formats.push_back(it); - - for(auto it : formatsList.images) - output_formats.push_back(it); - - - // input_format in many output exts - for(int& output_format : output_formats) - { - if(input_format == output_format) - continue; - - std::wstring output_file_path = output_files_folder - + L"/" + NSFile::GetFileName(file) + checker.GetExtensionByType(output_format); - - // creating temporary xml file with params - NSStringUtils::CStringBuilder builder; - builder.WriteString(L""); - - builder.WriteString(L""); - - builder.WriteString(L""); - builder.WriteEncodeXmlString(file); - builder.WriteString(L""); - - builder.WriteString(L""); - builder.WriteEncodeXmlString(output_file_path); - builder.WriteString(L""); - - - builder.WriteString(L""); - builder.WriteString(std::to_wstring(input_format)); - builder.WriteString(L""); - - - builder.WriteString(L""); - builder.WriteString(std::to_wstring(output_format)); - builder.WriteString(L""); - - builder.WriteString(L"./"); - builder.WriteString(L"true"); - - builder.WriteString(L""); - builder.WriteEncodeXmlString(sFontsDirectory + L"/AllFonts.js"); - builder.WriteString(L""); - - builder.WriteString(L""); - builder.WriteEncodeXmlString(sFontsDirectory); - builder.WriteString(L""); - - if(formatsList.isImage(output_format)) - { - builder.WriteString(L"42false10001000"); - builder.WriteString(L"{"spreadsheetLayout":{"gridLines":true,"headings":true,"fitToHeight":1,"fitToWidth":1,"orientation":"landscape"}}"); - } - - builder.WriteString(L""); - - std::wstring xml_params = builder.GetData(); - - NSFile::CFileBinary::SaveToFile(m_xmlParams, xml_params, true); - - std::wcout << file << L" to " << output_file_path << L"... "; - int exit_code = convert(); - - if(!exit_code) - std::wcout << "OK" << std::endl; - else - std::wcout << "BAD" << std::endl; - - // writing report - Report report; - report.inputFile = file; - report.outputFile = output_file_path; - report.inputExt = checker.GetExtensionByType(input_format); - report.outputExt = checker.GetExtensionByType(output_format); - report.exitCode = exit_code; - - writeReport(report); - } - } - m_reportStream.close(); - NSFile::CFileBinary::Remove(m_xmlParams); + m_reportStream.CloseFile(); } void Cx2tTester::setConfig(const std::wstring& configPath) @@ -261,10 +121,11 @@ void Cx2tTester::setConfig(const std::wstring& configPath) std::wstring name = node.GetName(); // key-value - if(name == L"reportPath") m_reportPath = node.GetText(); - else if(name == L"inputFolder") m_inputFolder = node.GetText(); - else if(name == L"outputFolder") m_outputFolder = node.GetText(); + if(name == L"reportPath") m_reportFile = node.GetText(); + else if(name == L"inputDirectory") m_inputDirectory = node.GetText(); + else if(name == L"outputDirectory") m_outputDirectory = node.GetText(); else if(name == L"x2tPath") m_x2tPath = node.GetText(); + else if(name == L"cores") m_maxProc = std::stoi(node.GetText()); else if (name == L"fonts") { m_bIsUseSystemFonts = (1 == node.ReadValueInt(L"system", 1)) ? true : false; @@ -276,54 +137,255 @@ void Cx2tTester::setConfig(const std::wstring& configPath) m_arAdditionalFontsDirs.push_back(oNodeDir.GetText()); } } - // arrays - else - { - XmlUtils::CXmlNodes array; - node.GetNodes(L"item", array); - - std::wstring input_ext = L'.' + name; - int input_format = COfficeFileFormatChecker::GetFormatByExtension(input_ext); - - if(!input_format) - continue; - - for (int i = 0; i < array.GetCount(); i++) - { - XmlUtils::CXmlNode item; - array.GetAt(i, item); - - std::wstring output_ext = L'.' + item.GetText(); - - int output_format = COfficeFileFormatChecker::GetFormatByExtension(output_ext); - - if(!output_format) - continue; - - m_formats[input_format].push_back(output_format); - } - } } } // else err } -void Cx2tTester::setReportHeader() +void Cx2tTester::Start() { - m_reportStream << L"Input file" << L"\t"; - m_reportStream << L"Output file" << L"\t"; - m_reportStream << L"Input extension" << L"\t"; - m_reportStream << L"Output extension" << L"\t"; - m_reportStream << L"Exit code" << L"\n"; + // check fonts + std::wstring fonts_directory = NSFile::GetProcessDirectory() + L"/fonts"; + CApplicationFontsWorker fonts_worker; + fonts_worker.m_sDirectory = fonts_directory; + if (!NSDirectory::Exists(fonts_worker.m_sDirectory)) + NSDirectory::CreateDirectory(fonts_worker.m_sDirectory); + + fonts_worker.m_bIsUseSystemFonts = m_bIsUseSystemFonts; + + for (std::vector::iterator i = m_arAdditionalFontsDirs.begin(); i != m_arAdditionalFontsDirs.end(); i++) + fonts_worker.m_arAdditionalFolders.push_back(*i); + + fonts_worker.m_bIsNeedThumbnails = false; + NSFonts::IApplicationFonts* pFonts = fonts_worker.Check(); + RELEASEINTERFACE(pFonts); + + // setup & clear output folder + if(NSDirectory::Exists(m_outputDirectory)) + NSDirectory::DeleteDirectory(m_outputDirectory); + + NSDirectory::CreateDirectory(m_outputDirectory); + + std::vector files = NSDirectory::GetFiles(m_inputDirectory, false); + FormatsList formats_list; + formats_list.SetDefault(); + + if(files.size() < m_maxProc) + m_maxProc = files.size(); + + for(std::wstring& input_file : files) + { + // setup folder for output files + std::wstring output_files_directory = m_outputDirectory + L'/' + NSFile::GetFileName(input_file); + + if(NSDirectory::Exists(output_files_directory)) + NSDirectory::DeleteDirectory(output_files_directory); + + NSDirectory::CreateDirectory(output_files_directory); + + std::wstring input_ext = NSFile::GetFileExtention(input_file); + int input_format = COfficeFileFormatChecker::GetFormatByExtension(L'.' + input_ext); + + // setup output_formats + std::vector output_formats; + + if(formats_list.isDocoment(input_format)) + output_formats = formats_list.documents; + + if(formats_list.isPresentation(input_format)) + output_formats = formats_list.presentations; + + if(formats_list.isSpreadsheet(input_format)) + output_formats = formats_list.spreadsheets; + + for(auto it : formats_list.crossplatform) + output_formats.push_back(it); + + for(auto it : formats_list.images) + output_formats.push_back(it); + + // waiting... + while(isAllBusy()) + Sleep(100); + + // setup & start new coverter + m_currentProc++; + CConverter *converter = new CConverter(this); + converter->SetInputFile(input_file); + converter->SetInputFormat(input_format); + converter->SetOutputFilesDirectory(output_files_directory); + converter->SetOutputFormats(output_formats); + converter->SetFontsDirectory(fonts_directory); + converter->SetX2tPath(m_x2tPath); + + converter->DestroyOnFinish(); + converter->Start(0); + } + + // waiting all procs end + while(!isAllFree()) + Sleep(100); } + void Cx2tTester::writeReport(const Report& report) { - m_reportStream << report.inputFile << L"\t"; - m_reportStream << report.outputFile << L"\t"; - m_reportStream << report.inputExt << L"\t"; - m_reportStream << report.outputExt << L"\t"; - m_reportStream << report.exitCode << L"\n"; + CTemporaryCS CS(&m_reportCS); + + m_reportStream.WriteStringUTF8(report.inputFile + L"\t", true); + m_reportStream.WriteStringUTF8(report.outputFile + L"\t", true); + m_reportStream.WriteStringUTF8(report.inputExt + L"\t", true); + m_reportStream.WriteStringUTF8(report.outputExt + L"\t", true); + m_reportStream.WriteStringUTF8(std::to_wstring(report.exitCode) + L"\n", true); } -int Cx2tTester::convert() +void Cx2tTester::writeReports(const std::vector& reports) { - return NSX2T::Convert(NSFile::GetDirectoryName(m_x2tPath), m_xmlParams); + CTemporaryCS CS(&m_reportCS); + for(auto& report : reports) + { + m_reportStream.WriteStringUTF8(report.inputFile + L"\t", true); + m_reportStream.WriteStringUTF8(report.outputFile + L"\t", true); + m_reportStream.WriteStringUTF8(report.inputExt + L"\t", true); + m_reportStream.WriteStringUTF8(report.outputExt + L"\t", true); + m_reportStream.WriteStringUTF8(std::to_wstring(report.exitCode) + L"\n", true); + } } + +bool Cx2tTester::isAllBusy() +{ + CTemporaryCS CS(&m_coresCS); + return m_currentProc == m_maxProc; +} +bool Cx2tTester::isAllFree() +{ + CTemporaryCS CS(&m_coresCS); + return m_currentProc == 0; +} + +void Cx2tTester::setReportHeader() +{ + m_reportStream.WriteStringUTF8(L"Input file\t", false); + m_reportStream.WriteStringUTF8(L"Output file\t", true); + m_reportStream.WriteStringUTF8(L"Input extension\t", true); + m_reportStream.WriteStringUTF8(L"Output extension\t", true); + m_reportStream.WriteStringUTF8(L"Exit code\n", true); +} + + +CConverter::CConverter(Cx2tTester* internal) : m_internal(internal) +{ +} +CConverter::~CConverter() +{ + Stop(); +} + +void CConverter::SetInputFile(const std::wstring& inputFile) +{ + m_inputFile = inputFile; +} +void CConverter::SetInputFormat(int inputFormat) +{ + m_inputFormat = inputFormat; +} + +void CConverter::SetOutputFilesDirectory(const std::wstring& outputFilesDirectory) +{ + m_outputFilesDirectory = outputFilesDirectory; +} +void CConverter::SetOutputFormats(const std::vector outputFormats) +{ + m_outputFormats = outputFormats; +} + +void CConverter::SetFontsDirectory(const std::wstring& fontsDirectory) +{ + m_fontsDirectory = fontsDirectory; +} +void CConverter::SetX2tPath(const std::wstring& x2tPath) +{ + m_x2tPath = x2tPath; +} + +DWORD CConverter::ThreadProc() +{ + std::wstring xml_params_file = m_outputFilesDirectory + L"/params.xml"; + std::vector reports; + + // input_format in many output exts + for(int& output_format : m_outputFormats) + { + if(m_inputFormat == output_format) + continue; + + std::wstring output_file = m_outputFilesDirectory + + L"/" + NSFile::GetFileName(m_inputFile) + checker.GetExtensionByType(output_format); + + // creating temporary xml file with params + NSStringUtils::CStringBuilder builder; + builder.WriteString(L""); + + builder.WriteString(L""); + + builder.WriteString(L""); + builder.WriteEncodeXmlString(m_inputFile); + builder.WriteString(L""); + + builder.WriteString(L""); + builder.WriteEncodeXmlString(output_file); + builder.WriteString(L""); + + builder.WriteString(L""); + builder.WriteString(std::to_wstring(m_inputFormat)); + builder.WriteString(L""); + + builder.WriteString(L""); + builder.WriteString(std::to_wstring(output_format)); + builder.WriteString(L""); + + builder.WriteString(L"./"); + builder.WriteString(L"true"); + + builder.WriteString(L""); + builder.WriteEncodeXmlString(m_fontsDirectory + L"/AllFonts.js"); + builder.WriteString(L""); + + builder.WriteString(L""); + builder.WriteEncodeXmlString(m_fontsDirectory); + builder.WriteString(L""); + + builder.WriteString(L"42false10001000"); + builder.WriteString(L"{"spreadsheetLayout":{"gridLines":true,"headings":true,"fitToHeight":1,"fitToWidth":1,"orientation":"landscape"}}"); + + builder.WriteString(L""); + + std::wstring xml_params = builder.GetData(); + + NSFile::CFileBinary::SaveToFile(xml_params_file, xml_params, true); + + int exit_code = NSX2T::Convert(NSFile::GetDirectoryName(m_x2tPath), xml_params_file); + + // writing report + Cx2tTester::Report report; + report.inputFile = m_inputFile; + report.outputFile = output_file; + report.inputExt = checker.GetExtensionByType(m_inputFormat); + report.outputExt = checker.GetExtensionByType(output_format); + report.exitCode = exit_code; + reports.push_back(report); + + std::string input_file_UTF8 = U_TO_UTF8(m_inputFile); + std::string output_file_UTF8 = U_TO_UTF8(output_file); + + CTemporaryCS CS(&m_internal->m_outputCS); + if(!exit_code) + std::cout << input_file_UTF8 << " to " << output_file_UTF8 << " " << "OK" << std::endl; + else + std::cout << input_file_UTF8 << " to " << output_file_UTF8 << " " << "BAD" << std::endl; + + } + NSFile::CFileBinary::Remove(xml_params_file); + m_internal->writeReports(reports); + m_internal->m_currentProc--; + return 0; +} + + diff --git a/Test/Applications/x2tTester/x2tTester.h b/Test/Applications/x2tTester/x2tTester.h index ab761092e9..89d75efaa0 100644 --- a/Test/Applications/x2tTester/x2tTester.h +++ b/Test/Applications/x2tTester/x2tTester.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "../../../Common/OfficeFileFormats.h" @@ -20,16 +19,31 @@ #include "../../../OfficeUtils/src/OfficeUtils.h" +struct FormatsList +{ +public: + std::vector documents; + std::vector presentations; + std::vector spreadsheets; + std::vector crossplatform; + std::vector images; + FormatsList(); + + bool isDocoment(int format); + bool isPresentation(int format); + bool isSpreadsheet(int format); + bool isCrossplatform(int format); + bool isImage(int format); + + void SetDefault(); +}; + + +// setups folders, parse xml config, takes formats, create CConverters class Cx2tTester { public: - Cx2tTester(std::wstring configPath); - ~Cx2tTester(); - - void Start(); - -private: struct Report { std::wstring inputFile; @@ -39,28 +53,72 @@ private: int exitCode; }; + Cx2tTester(const std::wstring& configPath); + ~Cx2tTester(); + void setConfig(const std::wstring& configPath); - void setReportHeader(); + void Start(); void writeReport(const Report& report); - int convert(); + void writeReports(const std::vector& reports); - std::wstring m_reportPath; - std::wstring m_inputFolder; - std::wstring m_outputFolder; + bool isAllBusy(); + bool isAllFree(); + + NSCriticalSection::CRITICAL_SECTION m_coresCS; + NSCriticalSection::CRITICAL_SECTION m_reportCS; + NSCriticalSection::CRITICAL_SECTION m_outputCS; + + int m_currentProc; + int m_maxProc; + +private: + void setReportHeader(); + + // takes from config + std::wstring m_reportFile; + std::wstring m_inputDirectory; + std::wstring m_outputDirectory; std::wstring m_x2tPath; // fonts bool m_bIsUseSystemFonts; std::vector m_arAdditionalFontsDirs; - std::wstring m_xmlParams; + NSFile::CFileBinary m_reportStream; +}; - std::wofstream m_reportStream; +// generates temp xml, convert, calls m_internal->writeReport +class CConverter : public NSThreads::CBaseThread +{ +public: + CConverter(Cx2tTester* internal); + virtual ~CConverter(); - // from 1 to N formats - std::map> m_formats; + void SetInputFile(const std::wstring& inputFile); + void SetInputFormat(int inputFormat); + void SetOutputFilesDirectory(const std::wstring& outputFilesDirectory); + void SetOutputFormats(const std::vector outputFormats); + + void SetFontsDirectory(const std::wstring& fontsDirectory); + void SetX2tPath (const std::wstring& x2tPath); + + virtual DWORD ThreadProc(); + +private: + Cx2tTester* m_internal; + + std::wstring m_inputFile; + int m_inputFormat; + + std::wstring m_outputFilesDirectory; + std::vector m_outputFormats; + + std::wstring m_fontsDirectory; + COfficeFileFormatChecker checker; + + std::wstring m_x2tPath; }; #endif // X2T_TESTER_H