diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | tools/minicargo/path.h | 15 | ||||
-rw-r--r-- | tools/testrunner/main.cpp | 298 | ||||
-rw-r--r-- | vsproject/mrustc.sln | 10 | ||||
-rw-r--r-- | vsproject/testrunner/testrunner.vcxproj | 119 | ||||
-rw-r--r-- | vsproject/testrunner/testrunner.vcxproj.filters | 25 |
6 files changed, 469 insertions, 0 deletions
@@ -21,6 +21,8 @@ /vsproject/tu_test/x64 /vsproject/minicargo/Win32 /vsproject/minicargo/x64 +/vsproject/testrunner/Win32 +/vsproject/testrunner/x64 /vsproject/packages /vsproject/*.sdf /vsproject/*.VC.db diff --git a/tools/minicargo/path.h b/tools/minicargo/path.h index 833fe90a..dd97f9be 100644 --- a/tools/minicargo/path.h +++ b/tools/minicargo/path.h @@ -116,6 +116,21 @@ public: } } path to_absolute() const; + ::std::string basename() const + { + if(!this->is_valid()) + throw ::std::runtime_error("Calling basename() on an invalid path"); + + auto pos = m_str.find_last_of(SEP); + if(pos == ::std::string::npos) + { + return m_str; + } + else + { + return m_str.substr(pos+1); + } + } const ::std::string& str() const { diff --git a/tools/testrunner/main.cpp b/tools/testrunner/main.cpp new file mode 100644 index 00000000..c5903014 --- /dev/null +++ b/tools/testrunner/main.cpp @@ -0,0 +1,298 @@ +/// +/// +/// +#include <iostream> +#include <string> +#include <vector> +#include <fstream> +#include "../minicargo/debug.h" +#include "../minicargo/path.h" +#ifdef _WIN32 +# include <Windows.h> +# define MRUSTC_PATH "x64\\Release\\mrustc.exe" +#else +#endif + +struct Options +{ + const char* output_dir = nullptr; + const char* input_glob = nullptr; + + const char* exceptions_file = nullptr; + + int parse(int argc, const char* argv[]); + + void usage_short() const; + void usage_full() const; +}; + +struct TestDesc +{ + ::std::string m_name; + ::std::string m_path; + ::std::vector<::std::string> m_pre_build; +}; + +bool run_executable(const ::helpers::path& file, const ::std::vector<const char*>& args); + +bool run_compiler(const ::helpers::path& source_file, const ::helpers::path& output, ::helpers::path libdir={}) +{ + ::std::vector<const char*> args; + args.push_back("mrustc"); + if(libdir.is_valid()) + { + args.push_back("-L"); + args.push_back(libdir.str().c_str()); + } + args.push_back(source_file.str().c_str()); + args.push_back("--out-dir"); + args.push_back(output.str().c_str()); + + run_executable(MRUSTC_PATH, args); + + return false; +} + +int main(int argc, const char* argv[]) +{ + Options opts; + if( int v = opts.parse(argc, argv) ) + { + return v; + } + + ::std::vector<::std::string> skip_list; + // > Filter out tests listed in an exceptions file (newline separated, supports comments) + if( opts.exceptions_file ) + { + auto exceptions_list = ::helpers::path(opts.exceptions_file); + } + + ::std::vector<TestDesc> tests; + + // 1. Take input glob/folder and enumerate .rs files/matches + // - If input path is a folder, find *.rs + // - Otherwise, accept glob. + { + auto input_path = ::helpers::path(opts.input_glob); +#ifdef _WIN32 + WIN32_FIND_DATA find_data; + auto mask = input_path / "*.rs"; + HANDLE find_handle = FindFirstFile( mask.str().c_str(), &find_data ); + if( find_handle == INVALID_HANDLE_VALUE ) { + ::std::cerr << "Unable to find files matching " << mask << ::std::endl; + return 1; + } + do + { + auto test_file_path = input_path / find_data.cFileName; +#else + auto* dp = opendir(path.str().c_str()); + if( dp == nullptr ) + throw ::std::runtime_error(::format( "Unable to open vendor directory '", path, "'" )); + while( const auto* dent = readdir(dp) ) + { + auto test_file_path = path / dent->d_name; +#endif + ::std::ifstream in(test_file_path.str()); + if(!in.good()) + continue ; + DEBUG("> " << test_file_path); + + TestDesc td; + + do + { + ::std::string line; + in >> line; + if( !(line[0] == '/' && line[1] == '/' && line[2] == ' ') ) + continue ; + + if( line.substr(3, 10) == "aux-build" ) + { + TODO("aux_build " << line); + } + } while( !in.eof() ); + + td.m_name = test_file_path.basename(); + td.m_name.pop_back(); + td.m_name.pop_back(); + td.m_name.pop_back(); + td.m_path = test_file_path; + + tests.push_back(td); +#ifndef _WIN32 + } + closedir(dp); +#else + } while( FindNextFile(find_handle, &find_data) ); + FindClose(find_handle); +#endif + } + + // 2. Open each file and extract the various flags required. + + // 3. Build each test to its own output subdirectory + auto outdir = opts.output_dir ? ::helpers::path(opts.output_dir) : throw ""; + for(const auto& test : tests) + { + DEBUG("> " << test.m_name); + auto depdir = outdir / "deps-" + test.m_name.c_str(); + + for(const auto& file : test.m_pre_build) + { + run_compiler(file, depdir); + } + run_compiler(test.m_path, outdir, outdir); + run_executable(outdir / test.m_name, {}); + } + + // 4. Run tests + + return 0; +} + +int Options::parse(int argc, const char* argv[]) +{ + for(int i = 1; i < argc; i ++) + { + const char* arg = argv[i]; + if( arg[0] != '-' ) + { + if( !this->input_glob ) { + this->input_glob = arg; + } + // TODO: Multiple input globs? + else { + this->usage_short(); + return 1; + } + } + else if( arg[1] != '-' ) + { + switch(arg[1]) + { + case 'o': + if( this->output_dir ) { + this->usage_short(); + return 1; + } + if( i+1 == argc ) { + this->usage_short(); + return 1; + } + this->output_dir = argv[++i]; + break; + + default: + this->usage_short(); + return 1; + } + } + else + { + if( 0 == ::std::strcmp(arg, "--help") ) + { + this->usage_full(); + return 0; + } + else if( 0 == ::std::strcmp(arg, "--exceptions") ) + { + if( this->exceptions_file ) { + this->usage_short(); + return 1; + } + if( i+1 == argc ) { + this->usage_short(); + return 1; + } + this->exceptions_file = argv[++i]; + } + else if( 0 == ::std::strcmp(arg, "--output-dir") ) + { + if( this->output_dir ) { + this->usage_short(); + return 1; + } + if( i+1 == argc ) { + this->usage_short(); + return 1; + } + this->output_dir = argv[++i]; + } + else + { + this->usage_short(); + return 1; + } + } + } + return 0; +} + +void Options::usage_short() const +{ +} +void Options::usage_full() const +{ +} + +/// +bool run_executable(const ::helpers::path& exe_name, const ::std::vector<const char*>& args) +{ +#ifdef _WIN32 + ::std::stringstream cmdline; + for (const auto& arg : args) + cmdline << arg << " "; + auto cmdline_str = cmdline.str(); + cmdline_str.pop_back(); + DEBUG("Calling " << cmdline_str); + + STARTUPINFO si = { 0 }; + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = NULL; + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.hStdError = GetStdHandle(STD_OUTPUT_HANDLE); + PROCESS_INFORMATION pi = { 0 }; + CreateProcessA(exe_name.str().c_str(), (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + CloseHandle(si.hStdOutput); + WaitForSingleObject(pi.hProcess, INFINITE); + DWORD status = 1; + GetExitCodeProcess(pi.hProcess, &status); + if (status != 0) + { + DEBUG("Executable exited with non-zero exit status " << status); + return false; + } +#else + return false; +#endif + return true; +} + + +static int giIndentLevel = 0; +void Debug_Print(::std::function<void(::std::ostream& os)> cb) +{ + for(auto i = giIndentLevel; i --; ) + ::std::cout << " "; + cb(::std::cout); + ::std::cout << ::std::endl; +} +void Debug_EnterScope(const char* name, dbg_cb_t cb) +{ + for(auto i = giIndentLevel; i --; ) + ::std::cout << " "; + ::std::cout << ">>> " << name << "("; + cb(::std::cout); + ::std::cout << ")" << ::std::endl; + giIndentLevel ++; +} +void Debug_LeaveScope(const char* name, dbg_cb_t cb) +{ + giIndentLevel --; + for(auto i = giIndentLevel; i --; ) + ::std::cout << " "; + ::std::cout << "<<< " << name << ::std::endl; +} diff --git a/vsproject/mrustc.sln b/vsproject/mrustc.sln index abeaf785..2493170e 100644 --- a/vsproject/mrustc.sln +++ b/vsproject/mrustc.sln @@ -12,6 +12,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minicargo", "minicargo\mini {12AA9964-C1BD-406A-9545-43EE63230EBE} = {12AA9964-C1BD-406A-9545-43EE63230EBE} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testrunner", "testrunner\testrunner.vcxproj", "{A6679301-7BF1-4B37-9468-687769472E24}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -44,6 +46,14 @@ Global {15F3D38B-14FF-4872-805D-6D9C52920842}.Release|x64.Build.0 = Release|x64 {15F3D38B-14FF-4872-805D-6D9C52920842}.Release|x86.ActiveCfg = Release|Win32 {15F3D38B-14FF-4872-805D-6D9C52920842}.Release|x86.Build.0 = Release|Win32 + {A6679301-7BF1-4B37-9468-687769472E24}.Debug|x64.ActiveCfg = Debug|x64 + {A6679301-7BF1-4B37-9468-687769472E24}.Debug|x64.Build.0 = Debug|x64 + {A6679301-7BF1-4B37-9468-687769472E24}.Debug|x86.ActiveCfg = Debug|Win32 + {A6679301-7BF1-4B37-9468-687769472E24}.Debug|x86.Build.0 = Debug|Win32 + {A6679301-7BF1-4B37-9468-687769472E24}.Release|x64.ActiveCfg = Release|x64 + {A6679301-7BF1-4B37-9468-687769472E24}.Release|x64.Build.0 = Release|x64 + {A6679301-7BF1-4B37-9468-687769472E24}.Release|x86.ActiveCfg = Release|Win32 + {A6679301-7BF1-4B37-9468-687769472E24}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vsproject/testrunner/testrunner.vcxproj b/vsproject/testrunner/testrunner.vcxproj new file mode 100644 index 00000000..857aea71 --- /dev/null +++ b/vsproject/testrunner/testrunner.vcxproj @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{A6679301-7BF1-4B37-9468-687769472E24}</ProjectGuid> + <RootNamespace>testrunner</RootNamespace> + <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\..\tools\minicargo\path.cpp" /> + <ClCompile Include="..\..\tools\testrunner\main.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/vsproject/testrunner/testrunner.vcxproj.filters b/vsproject/testrunner/testrunner.vcxproj.filters new file mode 100644 index 00000000..6a7df4d6 --- /dev/null +++ b/vsproject/testrunner/testrunner.vcxproj.filters @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\tools\testrunner\main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\tools\minicargo\path.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file |