// TestFunction //------------------------------------------------------------------------------ void TestProjectGeneration::TestFunction() const { AStackString<> project( "../../../../ftmp/Test/ProjectGeneration/testproj.vcxproj" ); AStackString<> solution( "../../../../ftmp/Test/ProjectGeneration/testsln.sln" ); AStackString<> filters( "../../../../ftmp/Test/ProjectGeneration/testproj.vcxproj.filters" ); EnsureFileDoesNotExist( project ); EnsureFileDoesNotExist( solution ); EnsureFileDoesNotExist( filters ); FBuildOptions options; options.m_ConfigFile = "Data/TestProjectGeneration/fbuild.bff"; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); TEST_ASSERT( fBuild.Build( AStackString<>( "TestSln" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../../../../ftmp/Test/ProjectGeneration/fbuild.fdb" ) ); EnsureFileExists( project ); EnsureFileExists( solution ); EnsureFileExists( filters ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( 1, 1, Node::VCXPROJECT_NODE ); CheckStatsNode ( 1, 1, Node::SLN_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 4, 4 ); }
// TestCopyFunction_SourceBasePath //------------------------------------------------------------------------------ void TestCopy::TestCopyFunction_SourceBasePath() const { FBuildOptions options; options.m_ConfigFile = "Data/TestCopy/copy.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> dst1( "../../../../tmp/Test/Copy/SourceBasePath/TestCopy/a.txt" ); const AStackString<> dst2( "../../../../tmp/Test/Copy/SourceBasePath/TestCopy/b.txt" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( dst1 ); EnsureFileDoesNotExist( dst2 ); // build (via alias) TEST_ASSERT( fBuild.Build( AStackString<>( "TestSourceBasePath" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../../../../tmp/Test/Copy/SourceBasePath/sourcebasepath.fdb" ) ); EnsureFileExists( dst1 ); EnsureFileExists( dst2 ); // Check stats // Seen, Built, Type CheckStatsNode ( 2, 2, Node::FILE_NODE ); CheckStatsNode ( 2, 2, Node::COPY_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 5, 5 ); }
// TestTwoDLLs //------------------------------------------------------------------------------ void TestDLL::TestTwoDLLs() const { FBuildOptions options; options.m_ConfigFile = "Data/TestDLL/fbuild.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> dllA( "../../../../tmp/Test/DLL/dllA.dll" ); const AStackString<> dllB( "../../../../tmp/Test/DLL/dllB.dll" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( dllA ); EnsureFileDoesNotExist( dllB ); // build dllB which depends on dllA TEST_ASSERT( fBuild.Build( dllB ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( GetTwoDLLsDBFileName() ) ); // make sure all output files are as expecter EnsureFileExists( dllA ); EnsureFileExists( dllB ); // Check stats // Seen, Built, Type CheckStatsNode ( 5, 2, Node::FILE_NODE ); // 2 cpp files CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 2, 2, Node::OBJECT_NODE ); CheckStatsNode ( 2, 2, Node::OBJECT_LIST_NODE ); CheckStatsNode ( 2, 2, Node::DLL_NODE ); CheckStatsTotal( 12, 9 ); }
// TestPCHClangWithCache //------------------------------------------------------------------------------ void TestPrecompiledHeaders::TestPCHClangWithCache() const { FBuildOptions options; options.m_ConfigFile = "Data/TestPrecompiledHeaders/fbuild.bff"; options.m_ForceCleanBuild = true; options.m_UseCacheRead = true; options.m_ShowSummary = true; // required to generate stats for node count checks AStackString<> obj( "../../../../ftmp/Test/PrecompiledHeaders/Clang/PCHUser.obj" ); AStackString<> pch( "../../../../ftmp/Test/PrecompiledHeaders/Clang/PrecompiledHeader.pch" ); EnsureFileDoesNotExist( obj ); EnsureFileDoesNotExist( pch ); FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize( nullptr ) ); AStackString<> target( "PCHTestClang" ); TEST_ASSERT( fBuild.Build( target ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( GetPCHDBClangFileName() ) ); EnsureFileExists( obj ); EnsureFileExists( pch ); // Check stats // Seen, Built, Type CheckStatsNode ( 2, 2, Node::FILE_NODE ); // cpp + pch CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 2, 0, Node::OBJECT_NODE );// obj + pch obj CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsTotal( 6, 4 ); // check we got both objects from the cache TEST_ASSERT( fBuild.GetStats().GetStatsFor( Node::OBJECT_NODE ).m_NumCacheHits == 2 ); // pch & the obj using it }
// TestMultipleAssemblies //------------------------------------------------------------------------------ void TestCSharp::TestMultipleAssemblies() const { FBuildOptions options; options.m_ConfigFile = "Data/TestCSharp/csharp.bff"; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); // delete files from previous runs EnsureFileDoesNotExist( "../../../../tmp/Test/CSharp/csharpassemblya.dll" ); EnsureFileDoesNotExist( "../../../../tmp/Test/CSharp/csharpassemblyb.dll" ); EnsureFileDoesNotExist( "../../../../tmp/Test/CSharp/csharpassemblyc.dll" ); // Build it TEST_ASSERT( fBuild.Build( AStackString<>( "CSharp-AssemblyC" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../../../../tmp/Test/CSharp/csharpmultipleassemblies.fdb" ) ); // Test output files EnsureFileExists( "../../../../tmp/Test/CSharp/csharpassemblya.dll" ); EnsureFileExists( "../../../../tmp/Test/CSharp/csharpassemblyb.dll" ); EnsureFileExists( "../../../../tmp/Test/CSharp/csharpassemblyc.dll" ); // Check stats // Seen, Built, Type CheckStatsNode ( 3, 3, Node::FILE_NODE ); // 2x cs CheckStatsNode ( 3, 3, Node::CS_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 7, 7 ); }
// TestGenerate_NoRebuild //------------------------------------------------------------------------------ void TestUnity::TestGenerate_NoRebuild() const { AStackString<> unity1( "../../../../tmp/Test/Unity/Unity1.cpp" ); AStackString<> unity2( "../../../../tmp/Test/Unity/Unity2.cpp" ); EnsureFileExists( unity1 ); EnsureFileExists( unity2 ); // Unity must be "built" every time, but it only writes files when they change // so record the time before and after uint64_t dateTime1 = FileIO::GetFileLastWriteTime( unity1 ); uint64_t dateTime2 = FileIO::GetFileLastWriteTime( unity2 ); // NTFS file resolution is 100ns, so sleep long enough to ensure // an invalid write would modify the time Thread::Sleep( 1 ); // 1ms FBuildStats stats = BuildGenerate(); // Make sure files have not been changed TEST_ASSERT( dateTime1 == FileIO::GetFileLastWriteTime( unity1 ) ); TEST_ASSERT( dateTime2 == FileIO::GetFileLastWriteTime( unity2 ) ); // Check stats // Seen, Built, Type CheckStatsNode ( stats, 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( stats, 1, 1, Node::UNITY_NODE ); CheckStatsTotal( stats, 2, 2 ); }
// MultipleCopyNodes //------------------------------------------------------------------------------ void TestCopy::MultipleCopyNodes() const { const AStackString<> srcFile( "Data/TestGraph/library.cpp" ); const AStackString<> dstFileA( "../../../../tmp/Test/Graph/library.multiplecopynodes1.cpp" ); const AStackString<> dstFileB( "../../../../tmp/Test/Graph/library.multiplecopynodes2.cpp" ); const AStackString<> dstFileC( "../../../../tmp/Test/Graph/library.multiplecopynodes3.cpp" ); // check files are as expected before starting test EnsureFileDoesNotExist( dstFileA ); EnsureFileDoesNotExist( dstFileB ); EnsureFileDoesNotExist( dstFileC ); EnsureFileExists( srcFile ); FBuildOptions options; options.m_ShowSummary = true; // required to generate stats for node count checks // build { FBuild fb( options ); NodeGraph & ng = fb.GetDependencyGraph(); // make a fileNode for the source FileNode * srcNode = ng.CreateFileNode( srcFile ); Dependencies empty; Node * copyA = ng.CreateCopyNode( dstFileA, srcNode, empty ); Node * copyB = ng.CreateCopyNode( dstFileB, (FileNode *)copyA, empty ); Node * copyC = ng.CreateCopyNode( dstFileC, (FileNode *)copyB, empty ); TEST_ASSERT( fb.Build( copyC ) ); TEST_ASSERT( fb.SaveDependencyGraph( "../../../../tmp/Test/Graph/multiplecopynode.fdb" ) ); EnsureFileExists( dstFileA ); EnsureFileExists( dstFileB ); EnsureFileExists( dstFileC ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::FILE_NODE ); CheckStatsNode ( 3, 3, Node::COPY_NODE ); CheckStatsTotal( 4, 4 ); } // check no rebuild { FBuild fb( options ); fb.Initialize( "../../../../tmp/Test/Graph/multiplecopynode.fdb" ); TEST_ASSERT( fb.Build( dstFileC ) ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::FILE_NODE ); CheckStatsNode ( 3, 0, Node::COPY_NODE ); CheckStatsTotal( 4, 1 ); } }
REGISTER_TESTS_END // SingleCopyNode //------------------------------------------------------------------------------ void TestCopy::SingleCopyNode() const { const AStackString<> testFileName( "Data/TestGraph/library.cpp" ); const AStackString<> testFileNameCopy( "../../../../tmp/Test/Graph/library.copynode.cpp" ); // check files are in expected states EnsureFileExists( testFileName ); EnsureFileDoesNotExist( testFileNameCopy ); FBuildOptions options; options.m_ShowSummary = true; // required to generate stats for node count checks // Build { FBuild fb( options ); NodeGraph & ng = fb.GetDependencyGraph(); // make a fileNode for the source FileNode * srcNode = ng.CreateFileNode( testFileName ); // and an ObjectNode for the output Dependencies empty; Node * dstNode = ng.CreateCopyNode( testFileNameCopy, srcNode, empty ); TEST_ASSERT( fb.Build( dstNode ) ); TEST_ASSERT( fb.SaveDependencyGraph( "../../../../tmp/Test/Graph/singlecopynode.fdb" ) ); EnsureFileExists( testFileNameCopy ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::FILE_NODE ); CheckStatsNode ( 1, 1, Node::COPY_NODE ); CheckStatsTotal( 2, 2 ); } // check no rebuild { FBuild fb( options ); fb.Initialize( "../../../../tmp/Test/Graph/singlecopynode.fdb" ); TEST_ASSERT( fb.Build( testFileNameCopy ) ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::FILE_NODE ); CheckStatsNode ( 1, 0, Node::COPY_NODE ); CheckStatsTotal( 2, 1 ); } }
// TestCompile //------------------------------------------------------------------------------ void TestUnity::TestCompile() const { FBuildOptions options; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks EnsureFileDoesNotExist( "../../../../tmp/Test/Unity/Unity.lib" ); FBuildStats stats = BuildCompile( options, false ); // don't use DB EnsureFileExists( "../../../../tmp/Test/Unity/Unity.lib" ); // Check stats // Seen, Built, Type uint32_t numF = 9; // pch + 2x generated unity files + 6 source cpp files #if defined( __WINDOWS__ ) numF++; // pch.cpp #endif CheckStatsNode ( stats, 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( stats, 1, 1, Node::UNITY_NODE ); CheckStatsNode ( stats, numF, 3, Node::FILE_NODE ); // pch + 2x generated unity files built CheckStatsNode ( stats, 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( stats, 3, 3, Node::OBJECT_NODE ); CheckStatsNode ( stats, 1, 1, Node::LIBRARY_NODE ); CheckStatsNode ( stats, 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( stats, 8+numF, 11 ); }
// Build //------------------------------------------------------------------------------ void TestExe::Build() const { FBuildOptions options; options.m_ConfigFile = "Data/TestExe/exe.bff"; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> exe( "../../../../tmp/Test/Exe/exe.exe" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( exe ); // build (via alias) TEST_ASSERT( fBuild.Build( AStackString<>( "Exe" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../../../../tmp/Test/Exe/exe.fdb" ) ); // make sure all output is where it is expected EnsureFileExists( exe ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::FILE_NODE ); // cpp CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsNode ( 1, 1, Node::EXE_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 6, 6 ); }
// REGISTER_TEST( TestMixedAssemblyWithCPP ) // TODO:A Enable REGISTER_TESTS_END // TestSingleFile //------------------------------------------------------------------------------ void TestCSharp::TestSingleFile() const { FBuildTestOptions options; options.m_ConfigFile = "Tools/FBuild/FBuildTest/Data/TestCSharp/csharp.bff"; options.m_ForceCleanBuild = true; FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); // delete files from previous runs EnsureFileDoesNotExist( "../tmp/Test/CSharp/csharpsingle.dll" ); // Build it TEST_ASSERT( fBuild.Build( AStackString<>( "CSharp-Single-Target" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../tmp/Test/CSharp/csharpsingle.fdb" ) ); // Test output file EnsureFileExists( "../tmp/Test/CSharp/csharpsingle.dll" ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 1, 1, Node::FILE_NODE ); // 1 cs file CheckStatsNode ( 1, 1, Node::CS_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 4, 4 ); }
// TestMultipleFiles //------------------------------------------------------------------------------ void TestCSharp::TestMultipleFiles() const { FBuildTestOptions options; options.m_ConfigFile = "Tools/FBuild/FBuildTest/Data/TestCSharp/csharp.bff"; options.m_ForceCleanBuild = true; FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); // delete files from previous runs EnsureFileDoesNotExist( "../tmp/Test/CSharp/csharpmulti.dll" ); // Build it TEST_ASSERT( fBuild.Build( AStackString<>( "CSharp-Multi-Target" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../tmp/Test/CSharp/csharpmulti.fdb" ) ); // Test output files EnsureFileExists( "../tmp/Test/CSharp/csharpmulti.dll" ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 3, 3, Node::FILE_NODE ); // 3x cs CheckStatsNode ( 1, 1, Node::CS_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsNode ( 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsTotal( 7, 7 ); }
REGISTER_TESTS_END // TestSingleDLL //------------------------------------------------------------------------------ void TestDLL::TestSingleDLL() const { FBuildOptions options; options.m_ConfigFile = "Data/TestDLL/fbuild.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> dll( "../../../../tmp/Test/DLL/dll.dll" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( dll ); TEST_ASSERT( fBuild.Build( dll ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( GetSingleDLLDBFileName() ) ); // make sure all output files are as expecter EnsureFileExists( dll ); // Check stats // Seen, Built, Type CheckStatsNode ( 3, 1, Node::FILE_NODE ); // cpp CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsNode ( 1, 1, Node::DLL_NODE ); CheckStatsTotal( 7, 5 ); }
// TestExeWithDLL //------------------------------------------------------------------------------ void TestDLL::TestExeWithDLL() const { FBuildOptions options; options.m_ConfigFile = "Data/TestDLL/fbuild.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> exe( "../../../../tmp/Test/DLL/exe.exe" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( exe ); // build executable with depends on DLLA TEST_ASSERT( fBuild.Build( exe ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( GetExeWithDLLDBFileName() ) ); // make sure all output files are as expecter EnsureFileExists( exe ); // Check stats // Seen, Built, Type CheckStatsNode ( 4, 2, Node::FILE_NODE ); // 2 cpp CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 2, 2, Node::OBJECT_NODE ); // exe.obj + a.obj CheckStatsNode ( 2, 2, Node::OBJECT_LIST_NODE ); // exe lib + dll lib CheckStatsNode ( 1, 1, Node::DLL_NODE ); CheckStatsNode ( 1, 1, Node::EXE_NODE ); CheckStatsTotal( 11, 9 ); }
// TestDLLWithPCH //------------------------------------------------------------------------------ void TestDLL::TestDLLWithPCH() const { FBuildOptions options; options.m_ConfigFile = "Data/TestDLL/fbuild.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> dllPCH( "../../../../tmp/Test/DLL/dllPCH.dll" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( dllPCH ); // build dllB which depends on dllA TEST_ASSERT( fBuild.Build( dllPCH ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( GetDLLWithPCHDBFileName() ) ); // make sure all output files are as expecter EnsureFileExists( dllPCH ); // Check stats // Seen, Built, Type uint32_t numF = 3; // pch.h + a.cpp + c.h #if defined( __WINDOWS__ ) numF++; // pch.cpp #endif CheckStatsNode ( numF, 2, Node::FILE_NODE ); // 1 cpp + 1 pch cpp CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 2, 2, Node::OBJECT_NODE );// obj + pch obj CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsNode ( 1, 1, Node::DLL_NODE ); CheckStatsTotal( 5+numF,7 ); }
// TestLibMerge //------------------------------------------------------------------------------ void TestBuildAndLinkLibrary::TestLibMerge() const { FBuildOptions options; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks options.m_ConfigFile = "Data/TestBuildAndLinkLibrary/fbuild.bff"; FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> lib( "../../../../tmp/Test/BuildAndLinkLibrary/merged.lib" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( lib ); // Build TEST_ASSERT( fBuild.Build( lib ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( GetMergeLibDBFileName() ) ); // make sure all output files are as expected EnsureFileExists( lib ); // Check stats // Seen, Built, Type CheckStatsNode ( 7, 4, Node::FILE_NODE ); // 3x .cpp + 3x .h + librarian CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsNode ( 3, 3, Node::OBJECT_NODE ); CheckStatsNode ( 3, 3, Node::LIBRARY_NODE ); // 2 libs + merge lib CheckStatsTotal( 15, 12 ); }
// Build_CacheHit //------------------------------------------------------------------------------ void TestCUDA::Build_CacheHit() const { FBuildOptions options; options.m_ConfigFile = "Data/TestCUDA/cuda.bff"; options.m_UseCacheRead = true; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize( "../../../../tmp/Test/CUDA/cuda.fdb" ) ); const AStackString<> obj( "../../../../tmp/Test/CUDA/test.obj" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( obj ); // build (via alias) TEST_ASSERT( fBuild.Build( AStackString<>( "CUDA-Obj" ) ) ); // make sure all output is where it is expected EnsureFileExists( obj ); // Check stats // Seen, Built, Type CheckStatsNode ( 65, 65, Node::FILE_NODE ); // many included files CheckStatsNode ( 1, 0, Node::COMPILER_NODE ); CheckStatsNode ( 1, 0, Node::OBJECT_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsTotal( 68, 66 ); // Test we got a cache hit const FBuildStats::Stats & objStats = fBuild.GetStats().GetStatsFor( Node::OBJECT_NODE ); TEST_ASSERT( objStats.m_NumCacheHits == 1 ); }
// TestCopyFunction_FileToFile //------------------------------------------------------------------------------ void TestCopy::TestCopyFunction_FileToFile() const { FBuildOptions options; options.m_ConfigFile = "Data/TestCopy/copy.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); AStackString<> dst( "../../../../tmp/Test/Copy/copy.bff.copy" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( dst ); // build (via alias) TEST_ASSERT( fBuild.Build( AStackString<>( "TestCopyFileToFile" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../../../../tmp/Test/Copy/filetofile.fdb" ) ); // make sure all output is where it is expected EnsureFileExists( dst ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::FILE_NODE ); CheckStatsNode ( 1, 1, Node::COPY_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 3, 3 ); }
// REGISTER_TEST( TestMixedAssemblyWithCPP ) // TODO:A Enable REGISTER_TESTS_END // TestSingleFile //------------------------------------------------------------------------------ void TestCSharp::TestSingleFile() const { FBuildOptions options; options.m_ConfigFile = "Data/TestCSharp/csharp.bff"; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); // delete files from previous runs EnsureFileDoesNotExist( "../../../../tmp/Test/CSharp/csharpsingle.dll" ); // Build it TEST_ASSERT( fBuild.Build( AStackString<>( "CSharp-Single-Target" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "../../../../tmp/Test/CSharp/csharpsingle.fdb" ) ); // Test output file EnsureFileExists( "../../../../tmp/Test/CSharp/csharpsingle.dll" ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::FILE_NODE ); // cs CheckStatsNode ( 1, 1, Node::CS_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 3, 3 ); }
// TestMSVC_P //------------------------------------------------------------------------------ void TestIncludeParser::TestMSVC_P() const { FBuildOptions options; options.m_ShowSummary = true; // required to generate stats for node count checks options.m_ConfigFile = "Data/TestIncludeParser/MSVC-P/fbuild.bff"; FBuild fBuild( options ); fBuild.Initialize(); const AStackString<> file( "../../../../tmp/Test/IncludeParser/MSVC-P/test.i" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( file ); // Build TEST_ASSERT( fBuild.Build( AStackString<>( "MSVC-P" ) ) ); // make sure all output files are as expected EnsureFileExists( file ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsNode ( 1, 1, Node::FILE_NODE ); CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_NODE ); CheckStatsTotal( 4, 4 ); }
// TestBuildLib //------------------------------------------------------------------------------ void TestBuildAndLinkLibrary::TestBuildLib() const { FBuildOptions options; options.m_ShowSummary = true; // required to generate stats for node count checks options.m_ConfigFile = "Data/TestBuildAndLinkLibrary/fbuild.bff"; FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); const AStackString<> lib( "../../../../tmp/Test/BuildAndLinkLibrary/test.lib" ); #if defined( __WINDOWS__ ) const AStackString<> obj1( "../../../../tmp/Test/BuildAndLinkLibrary/a.obj" ); const AStackString<> obj2( "../../../../tmp/Test/BuildAndLinkLibrary/b.obj" ); const AStackString<> obj3( "../../../../tmp/Test/BuildAndLinkLibrary/c.obj" ); #else const AStackString<> obj1( "../../../../tmp/Test/BuildAndLinkLibrary/a.o" ); const AStackString<> obj2( "../../../../tmp/Test/BuildAndLinkLibrary/b.o" ); const AStackString<> obj3( "../../../../tmp/Test/BuildAndLinkLibrary/c.o" ); #endif // clean up anything left over from previous runs EnsureFileDoesNotExist( lib ); EnsureFileDoesNotExist( obj1 ); EnsureFileDoesNotExist( obj2 ); EnsureFileDoesNotExist( obj3 ); // Build TEST_ASSERT( fBuild.Build( lib ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( GetBuildLibDBFileName() ) ); // make sure all output files are as expected EnsureFileExists( lib ); EnsureFileExists( obj1 ); EnsureFileExists( obj2 ); EnsureFileExists( obj3 ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( 7, 4, Node::FILE_NODE ); // 3 cpps + librarian CheckStatsNode ( 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( 3, 3, Node::OBJECT_NODE ); CheckStatsNode ( 1, 1, Node::LIBRARY_NODE ); CheckStatsTotal( 13, 10 ); }
void TestObjectList::ExtraOutputFolders() const { FBuildOptions options; options.m_ConfigFile = "Data/TestObjectList/ExtraOutputPaths/fbuild.bff"; const char * objectListASMFile = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/ObjectList/asm/file.asm"; const char * objectListASMDir = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/ObjectList/asm/"; const char * objectListPDBFile = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/ObjectList/pdb/file.pdb"; const char * objectListPDBDir = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/ObjectList/pdb/"; const char * libraryASMFile = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/Library/asm/file.asm"; const char * libraryASMDir = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/Library/asm/"; const char * libraryPDBFile = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/Library/pdb/file.pdb"; const char * libraryPDBDir = "../../../../tmp/Test/ObjectList/ExtraOutputPaths/Library/pdb/"; // Cleanup from previous runs to ensure we're really testing folder creation EnsureFileDoesNotExist( objectListASMFile ); EnsureDirDoesNotExist( objectListASMDir ); EnsureFileDoesNotExist( objectListPDBFile ); EnsureDirDoesNotExist( objectListPDBDir ); EnsureFileDoesNotExist( libraryASMFile ); EnsureDirDoesNotExist( libraryASMDir ); EnsureFileDoesNotExist( libraryPDBFile ); EnsureDirDoesNotExist( libraryPDBDir ); // ObjectList { FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); TEST_ASSERT( fBuild.Build( AStackString<>( "ObjectList" ) ) ); } EnsureFileExists( objectListASMFile ); EnsureFileExists( objectListPDBFile ); // Library { FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize() ); TEST_ASSERT( fBuild.Build( AStackString<>( "Library" ) ) ); } EnsureFileExists( libraryASMFile ); EnsureFileExists( libraryPDBFile ); }
// TestGenerate //------------------------------------------------------------------------------ void TestUnity::TestGenerate() const { FBuildOptions options; options.m_ShowSummary = true; // required to generate stats for node count checks options.m_ForceCleanBuild = true; EnsureFileDoesNotExist( "../../../../tmp/Test/Unity/Unity1.cpp" ); EnsureFileDoesNotExist( "../../../../tmp/Test/Unity/Unity2.cpp" ); FBuildStats stats = BuildGenerate( options, false ); // don't use DB EnsureFileExists( "../../../../tmp/Test/Unity/Unity1.cpp" ); EnsureFileExists( "../../../../tmp/Test/Unity/Unity2.cpp" ); // Check stats // Seen, Built, Type CheckStatsNode ( stats, 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( stats, 1, 1, Node::UNITY_NODE ); CheckStatsTotal( stats, 2, 2 ); }
// TestFunction_NoRebuild //------------------------------------------------------------------------------ void TestProjectGeneration::TestFunction_NoRebuild() const { AStackString<> project( "../../../../ftmp/Test/ProjectGeneration/testproj.vcxproj" ); AStackString<> filters( "../../../../ftmp/Test/ProjectGeneration/testproj.vcxproj.filters" ); EnsureFileExists( project ); EnsureFileExists( filters ); // Projects and Solutions must be "built" every time, but only write files when they change // so record the time before and after uint64_t dateTime1 = FileIO::GetFileLastWriteTime( project ); uint64_t dateTime2 = FileIO::GetFileLastWriteTime( filters ); // NTFS file resolution is 100ns and HFS is 1 second, // so sleep long enough to ensure an invalid write would modify the time #if defined( __WINDOWS__ ) Thread::Sleep( 1 ); // 1ms #else Thread::Sleep( 1000 ); // 1 second #endif // do build FBuildOptions options; options.m_ConfigFile = "Data/TestProjectGeneration/fbuild.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize( "../../../../ftmp/Test/ProjectGeneration/fbuild.fdb" ) ); TEST_ASSERT( fBuild.Build( AStackString<>( "TestProj" ) ) ); // Make sure files have not been changed TEST_ASSERT( dateTime1 == FileIO::GetFileLastWriteTime( project ) ); TEST_ASSERT( dateTime2 == FileIO::GetFileLastWriteTime( filters ) ); // Check stats // Seen, Built, Type CheckStatsNode ( 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( 1, 1, Node::VCXPROJECT_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( 3, 3 ); }
// TestPCH //------------------------------------------------------------------------------ void TestPrecompiledHeaders::TestPCH() const { FBuildOptions options; options.m_ForceCleanBuild = true; options.m_UseCacheWrite = true; options.m_ShowSummary = true; // required to generate stats for node count checks #if defined( __WINDOWS__ ) AStackString<> obj( "../../../../ftmp/Test/PrecompiledHeaders/PCHUser.obj" ); #else AStackString<> obj( "../../../../ftmp/Test/PrecompiledHeaders/PCHUser.o" ); #endif AStackString<> pch( "../../../../ftmp/Test/PrecompiledHeaders/PrecompiledHeader.pch" ); AStackString<> lib( "../../../../ftmp/Test/PrecompiledHeaders/TestPCH.lib" ); EnsureFileDoesNotExist( obj ); EnsureFileDoesNotExist( pch ); EnsureFileDoesNotExist( lib ); FBuildStats stats = Build( options, false ); // don't use DB EnsureFileExists( obj ); EnsureFileExists( pch ); EnsureFileExists( lib ); // Check stats // Seen, Built, Type CheckStatsNode ( stats, 3, 2, Node::FILE_NODE ); // cpp + pch CheckStatsNode ( stats, 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( stats, 2, 2, Node::OBJECT_NODE );// obj + pch obj CheckStatsNode ( stats, 1, 1, Node::LIBRARY_NODE ); CheckStatsNode ( stats, 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( stats, 1, 1, Node::ALIAS_NODE ); CheckStatsNode ( stats, 1, 1, Node::DLL_NODE ); CheckStatsTotal( stats, 10, 9 ); // check we wrote all objects to the cache TEST_ASSERT( stats.GetStatsFor( Node::OBJECT_NODE ).m_NumCacheStores == 1 ); // only the main obj can be cached }
REGISTER_TESTS_END // BuildResource //------------------------------------------------------------------------------ void TestResources::BuildResource() const { FBuildOptions options; options.m_ConfigFile = "Data/TestResources/fbuild.bff"; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); fBuild.Initialize(); const AStackString<> binRes( "../../../../ftmp/Test/Resources/resource.res" ); // clean up anything left over from previous runs EnsureFileDoesNotExist( "binRes" ); TEST_ASSERT( fBuild.Build( AStackString<>( "exe" ) ) ); TEST_ASSERT( fBuild.SaveDependencyGraph( "..\\..\\..\\..\\ftmp\\Test\\Resources\\resource.fdb" ) ); // make sure all output files are as expected EnsureFileExists( binRes ); // spawn exe which does a runtime check that the resource is availble Process p; p.Spawn( "..\\..\\..\\..\\ftmp\\Test\\Resources\\exe.exe", nullptr, nullptr, nullptr ); int ret = p.WaitForExit(); TEST_ASSERT( ret == 1 ); // verify expected ret code // Check stats // Seen, Built, Type // NOTE: Don't test file nodes since test used windows.h CheckStatsNode ( 2, 2, Node::OBJECT_NODE ); CheckStatsNode ( 1, 1, Node::OBJECT_LIST_NODE ); CheckStatsNode ( 1, 1, Node::LIBRARY_NODE ); CheckStatsNode ( 1, 1, Node::ALIAS_NODE ); CheckStatsNode ( 1, 1, Node::EXE_NODE ); }
// TestParallelBuild //------------------------------------------------------------------------------ void TestCLR::TestParallelBuild() const { FBuildOptions options; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks EnsureFileDoesNotExist( "../../../../ftmp/Test/CLR/clrmulti.lib" ); FBuildStats stats = Build( options, false, "CLR-Parallel-Target" ); // dont' use DB EnsureFileExists( "../../../../ftmp/Test/CLR/clrmulti.lib" ); // Check stats // Seen, Built, Type CheckStatsNode ( stats, 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( stats, 5, 3, Node::FILE_NODE ); // 3xcpp + .h CheckStatsNode ( stats, 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( stats, 3, 3, Node::OBJECT_NODE ); CheckStatsNode ( stats, 1, 1, Node::LIBRARY_NODE ); CheckStatsNode ( stats, 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( stats, 12, 10 ); }
// TestCompile //------------------------------------------------------------------------------ void TestUnity::TestCompile() const { FBuildOptions options; options.m_ForceCleanBuild = true; options.m_ShowSummary = true; // required to generate stats for node count checks EnsureFileDoesNotExist( "../../../../ftmp/Test/Unity/Unity.lib" ); FBuildStats stats = BuildCompile( options, false ); // don't use DB EnsureFileExists( "../../../../ftmp/Test/Unity/Unity.lib" ); // Check stats // Seen, Built, Type CheckStatsNode ( stats, 1, 1, Node::DIRECTORY_LIST_NODE ); CheckStatsNode ( stats, 1, 1, Node::UNITY_NODE ); CheckStatsNode ( stats, 10, 3, Node::FILE_NODE ); // pch + 2x generated unity files CheckStatsNode ( stats, 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( stats, 3, 3, Node::OBJECT_NODE ); CheckStatsNode ( stats, 1, 1, Node::LIBRARY_NODE ); CheckStatsNode ( stats, 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( stats, 18, 11 ); }
// Build_NoRebuild //------------------------------------------------------------------------------ void TestCUDA::Build_NoRebuild() const { FBuildOptions options; options.m_ConfigFile = "Data/TestCUDA/cuda.bff"; options.m_ShowSummary = true; // required to generate stats for node count checks FBuild fBuild( options ); TEST_ASSERT( fBuild.Initialize( "../../../../tmp/Test/CUDA/cuda.fdb" ) ); const AStackString<> obj( "../../../../tmp/Test/CUDA/test.obj" ); // build (via alias) TEST_ASSERT( fBuild.Build( AStackString<>( "CUDA-Obj" ) ) ); // make sure all output is where it is expected EnsureFileExists( obj ); // Check stats // Seen, Built, Type CheckStatsNode ( 65, 65, Node::FILE_NODE ); // many included files CheckStatsNode ( 1, 0, Node::COMPILER_NODE ); CheckStatsNode ( 1, 0, Node::OBJECT_NODE ); CheckStatsNode ( 1, 0, Node::OBJECT_LIST_NODE ); CheckStatsTotal( 68, 65 ); }
// Test //------------------------------------------------------------------------------ void TestCLR::Test() const { FBuildOptions options; options.m_ForceCleanBuild = true; options.m_UseCacheWrite = true; options.m_ShowSummary = true; // required to generate stats for node count checks EnsureFileDoesNotExist( "../../../../ftmp/Test/CLR/clr.lib" ); FBuildStats stats = Build( options, false, "CLR-Target" ); // dont' use DB EnsureFileExists( "../../../../ftmp/Test/CLR/clr.lib" ); // Check stats // Seen, Built, Type CheckStatsNode ( stats, 3, 1, Node::FILE_NODE ); // cpp CheckStatsNode ( stats, 1, 1, Node::COMPILER_NODE ); CheckStatsNode ( stats, 1, 1, Node::OBJECT_NODE ); CheckStatsNode ( stats, 1, 1, Node::LIBRARY_NODE ); CheckStatsNode ( stats, 1, 1, Node::ALIAS_NODE ); CheckStatsTotal( stats, 7, 5 ); TEST_ASSERT( stats.GetCacheStores() == 0 ); // cache not supported due to compiler bug }