This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
// This directive will define the main entry point
#define BOOST_TEST_MODULE Base
#include <boost/test/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>
#include "rbx/Debug.h"
#include "rbx/test/Base.UnitTest.Lib.h"
#ifdef _WIN32
int BOOST_TEST_CALL_DECL
main( int argc, char* argv[] )
{
char** filteredArgv = new char*[argc];
int filteredArgc = 0;
for (int i = 0; i < argc; i++)
if (!RBX::Test::BaseGlobalFixture::processArg(argv[i]))
filteredArgv[filteredArgc++] = argv[i];
// prototype for user's unit test init function
#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
boost::unit_test::init_unit_test_func init_func = &init_unit_test;
#else
boost::unit_test::init_unit_test_func init_func = &init_unit_test_suite;
#endif
int result = ::boost::unit_test::unit_test_main( init_func, filteredArgc, filteredArgv );
delete [] filteredArgv;
return result;
}
#endif
using namespace RBX::Test;
BOOST_GLOBAL_FIXTURE(BaseGlobalFixture);
+247
View File
@@ -0,0 +1,247 @@
<?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|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E7993392-E347-400A-8742-8293564E1E8B}</ProjectGuid>
<RootNamespace>BaseUnitTest</RootNamespace>
<SccProjectName>Perforce Project</SccProjectName>
<SccLocalPath>..</SccLocalPath>
<SccProvider>MSSCCI:Perforce SCM</SccProvider>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="..\CustomBuildRules.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PropertySheets\Common.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PropertySheets\Common.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>bin\$(Configuration)\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
<LinkIncremental>true</LinkIncremental>
<PostBuildEventUseInBuild>true</PostBuildEventUseInBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<LinkIncremental>true</LinkIncremental>
<PostBuildEventUseInBuild>true</PostBuildEventUseInBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>bin\$(Configuration)\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<PostBuildEventUseInBuild>true</PostBuildEventUseInBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<LinkIncremental>false</LinkIncremental>
<PostBuildEventUseInBuild>true</PostBuildEventUseInBuild>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(CONTRIB_PATH)\boost_1_56_0\include;..\Base.UnitTest.Lib\include;..\Base\include;..\TBB_4_1\include;..\Log\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>BOOST_THREAD_BUILD_LIB;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<FloatingPointModel>Fast</FloatingPointModel>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\TBB_4_1\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<PostBuildEvent>
<Command />
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(CONTRIB_PATH)\boost_1_56_0\include;..\Base.UnitTest.Lib\include;..\Base\include;..\TBB_4_1\include;..\Log\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>BOOST_THREAD_BUILD_LIB;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<FloatingPointModel>Fast</FloatingPointModel>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\TBB_4_1\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/D "_SECURE_SCL=0" %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(CONTRIB_PATH)\boost_1_56_0\include;..\Base.UnitTest.Lib\include;..\Base\include;..\TBB_4_1\include;..\Log\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>BOOST_THREAD_BUILD_LIB;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\TBB_4_1\lib;..\boostlibs\bin\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<BaseAddress>0x00400000</BaseAddress>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
</Link>
<PostBuildEvent>
<Command />
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<ClCompile>
<AdditionalOptions>/D "_SECURE_SCL=0" %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(CONTRIB_PATH)\boost_1_56_0\include;..\Base.UnitTest.Lib\include;..\Base\include;..\TBB_4_1\include;..\Log\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>BOOST_THREAD_BUILD_LIB;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>..\TBB_4_1\lib;..\boostlibs\bin\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<BaseAddress>0x00400000</BaseAddress>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="atomic.cpp" />
<ClCompile Include="Base.UnitTest.cpp" />
<ClCompile Include="CEvent.cpp" />
<ClCompile Include="Crypt.cpp" />
<ClCompile Include="DenseHashSet.cpp" />
<ClCompile Include="intrusive_ptr.cpp" />
<ClCompile Include="Log.cpp" />
<ClCompile Include="make_shared.cpp" />
<ClCompile Include="signals.cpp" />
<ClCompile Include="spin_mutex_test.cpp" />
<ClCompile Include="TaskScheduler.cpp" />
<ClCompile Include="Time.cpp" />
<ClCompile Include="trie.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Base.UnitTest.Lib\Base.UnitTest.Lib.vcxproj">
<Project>{c5e89a79-bbc2-4ff3-80e1-69f5291f0c3c}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\Base\Base.vcxproj">
<Project>{3025c00a-7746-469b-a279-96127c72abee}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\boostlibs\boost.test.vcxproj">
<Project>{55b54c4c-1951-4d6b-af5a-794214553001}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\Log\Log.vcxproj">
<Project>{9980f6c3-b64d-4775-8793-bb6dde31ce82}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\CustomBuildRules.targets" />
</ImportGroup>
</Project>
@@ -0,0 +1,61 @@
<?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;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</Extensions>
</Filter>
<Filter Include="Libraries">
<UniqueIdentifier>{ea58b07d-f626-4911-a363-1da9ee520da9}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="atomic.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Base.UnitTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CEvent.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Crypt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="intrusive_ptr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="make_shared.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="signals.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="spin_mutex_test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TaskScheduler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Time.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="trie.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DenseHashSet.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+76
View File
@@ -0,0 +1,76 @@
#include <boost/test/unit_test.hpp>
#include "rbx/test/TimeoutFixture.h"
#include "RBX/CEvent.h"
#ifdef RBX_PLATFORM_IOS
#define TIMEOUT 60
#else
#define TIMEOUT 20
#endif
using namespace boost;
BOOST_FIXTURE_TEST_SUITE(CEvent, RBX::Test::TimeoutFixture<TIMEOUT>)
BOOST_AUTO_TEST_CASE(CEventManual)
{
RBX::CEvent e(true);
for (int i = 0; i < 100000; ++i)
{
e.Set();
e.Wait();
}
}
static void fCEventAuto(RBX::CEvent& e1, RBX::CEvent& e2)
{
for (int i = 0; i < 100000; ++i)
{
e1.Wait();
e2.Set();
}
}
BOOST_AUTO_TEST_CASE(CEventAuto)
{
RBX::CEvent e1(false);
RBX::CEvent e2(false);
boost::thread t(fCEventAuto, boost::ref(e1), boost::ref(e2));
for (int i = 0; i < 100000; ++i)
{
e1.Set();
e2.Wait();
}
t.join();
}
void waitTest(double lower, double seconds, double upper)
{
RBX::CEvent e(true);
RBX::Time start = RBX::Time::now<RBX::Time::Precise>();
e.Wait(RBX::Time::Interval::from_seconds(seconds));
RBX::Time::Interval waitTime = RBX::Time::now<RBX::Time::Precise>() - start;
#ifdef __APPLE__
BOOST_WARN_GT(waitTime.seconds(), lower);
BOOST_WARN_LT(waitTime.seconds(), upper);
#else
BOOST_CHECK_GT(waitTime.seconds(), lower);
BOOST_CHECK_LT(waitTime.seconds(), upper);
#endif
}
BOOST_AUTO_TEST_CASE(CEventTimeout)
{
waitTest(0.5, 1, 1.5);
waitTest(1, 2, 3);
waitTest(2, 3, 4);
}
BOOST_AUTO_TEST_SUITE_END()
+29
View File
@@ -0,0 +1,29 @@
#include <boost/test/unit_test.hpp>
#include "rbx/crypt.h"
using namespace boost;
BOOST_AUTO_TEST_SUITE(Crypt)
const char* message = "Hello World!";
const char* signatureBase64 = "ZLrv3Sy5zh08/+tec0tw2dMJ1JkhX/TcItuo/IuYPkP3muftzYEU3mt+uU9236Hdh2RQlUIw3me/hI06aj9KVAbS8dHSzHbF6GpkhhmwmiLW4v8XfSFb//XujR4nEadWi21mzWTVDEySJA66uotV63r3jvYmVHC+o35dBN0h5Jw=";
#ifndef RBX_PLATFORM_IOS
BOOST_AUTO_TEST_CASE(PositiveTest)
{
RBX::Crypt crypt;
BOOST_CHECK_NO_THROW(crypt.verifySignatureBase64(message, signatureBase64));
}
BOOST_AUTO_TEST_CASE(NegativeTest)
{
RBX::Crypt crypt;
BOOST_CHECK_THROW(crypt.verifySignatureBase64("Tampered message", signatureBase64), std::exception);
}
#endif
BOOST_AUTO_TEST_SUITE_END()
+207
View File
@@ -0,0 +1,207 @@
#include "rbx/DenseHash.h"
#include <boost/test/unit_test.hpp>
using namespace boost;
BOOST_AUTO_TEST_SUITE(DenseHashSet)
template <typename Set> void verifyContentsRange(const Set& set, int begin, int end)
{
BOOST_CHECK_EQUAL(set.size(), end - begin);
std::vector<int> data;
for (typename Set::const_iterator it = set.begin(); it != set.end(); ++it)
data.push_back(*it);
BOOST_CHECK_EQUAL(data.size(), end - begin);
std::sort(data.begin(), data.end());
for (size_t i = 0; i < data.size(); ++i)
BOOST_CHECK_EQUAL(data[i], begin + i);
}
BOOST_AUTO_TEST_CASE(SimpleForward)
{
RBX::DenseHashSet<int> set(-1);
for (int i = 0; i < 5; ++i)
set.insert(i);
verifyContentsRange(set, 0, 5);
}
BOOST_AUTO_TEST_CASE(SimpleBackward)
{
RBX::DenseHashSet<int> set(-1);
for (int i = 4; i >= 0; --i)
set.insert(i);
verifyContentsRange(set, 0, 5);
}
BOOST_AUTO_TEST_CASE(SimpleDuplicate)
{
RBX::DenseHashSet<int> set(-1);
for (int i = 0; i < 5; ++i)
set.insert(i);
for (int i = 4; i >= 0; --i)
set.insert(i);
verifyContentsRange(set, 0, 5);
}
struct HasherOne
{
int operator()(int value) const
{
return 1;
}
};
BOOST_AUTO_TEST_CASE(LargeBadHashFunction)
{
RBX::DenseHashSet<int, HasherOne> set(-1);
for (int i = 0; i < 512; ++i)
set.insert(i);
verifyContentsRange(set, 0, 512);
}
BOOST_AUTO_TEST_CASE(ContainsSimple)
{
RBX::DenseHashSet<int> set(0);
BOOST_CHECK_EQUAL(set.contains(1), false);
BOOST_CHECK_EQUAL(set.contains(2), false);
set.insert(1);
BOOST_CHECK_EQUAL(set.contains(1), true);
BOOST_CHECK_EQUAL(set.contains(2), false);
}
BOOST_AUTO_TEST_CASE(ContainsSieve)
{
RBX::DenseHashSet<int> sieve(0);
for (int i = 2; i < 100; ++i)
{
if (!sieve.contains(i))
{
for (int k = 2; k * i < 100; ++k)
sieve.insert(k * i);
}
}
BOOST_CHECK_EQUAL(sieve.contains(81), true);
BOOST_CHECK_EQUAL(sieve.contains(97), false);
BOOST_CHECK_EQUAL(sieve.contains(98), true);
BOOST_CHECK_EQUAL(sieve.contains(99), true);
}
BOOST_AUTO_TEST_CASE(SizeEmpty)
{
RBX::DenseHashSet<int> set(0);
BOOST_CHECK_EQUAL(set.size(), 0);
BOOST_CHECK_EQUAL(set.empty(), true);
set.insert(5);
BOOST_CHECK_EQUAL(set.size(), 1);
BOOST_CHECK_EQUAL(set.empty(), false);
BOOST_CHECK_EQUAL(*set.begin(), 5);
}
BOOST_AUTO_TEST_CASE(SizeBuckets)
{
RBX::DenseHashSet<int> set(-1);
BOOST_CHECK_EQUAL(set.size(), 0);
BOOST_CHECK_EQUAL(set.bucket_count(), 0);
for (int i = 0; i < 100; ++i)
set.insert(i*i);
for (int i = 99; i >= 0; --i)
set.insert(i*i);
BOOST_CHECK_EQUAL(set.size(), 100);
BOOST_CHECK_EQUAL(set.bucket_count(), 256);
}
BOOST_AUTO_TEST_CASE(BucketsStartingAt1)
{
RBX::DenseHashSet<int> set(-1, 1);
BOOST_CHECK_EQUAL(set.size(), 0);
BOOST_CHECK_EQUAL(set.bucket_count(), 1);
set.insert(1);
BOOST_CHECK_EQUAL(set.size(), 1);
BOOST_CHECK_EQUAL(set.bucket_count(), 2);
set.insert(4);
BOOST_CHECK_EQUAL(set.size(), 2);
BOOST_CHECK_EQUAL(set.bucket_count(), 4);
set.insert(9);
BOOST_CHECK_EQUAL(set.size(), 3);
BOOST_CHECK_EQUAL(set.bucket_count(), 4);
set.insert(16);
BOOST_CHECK_EQUAL(set.size(), 4);
BOOST_CHECK_EQUAL(set.bucket_count(), 8);
for (int i = 0; i < 100; ++i)
set.insert(i * i);
BOOST_CHECK_EQUAL(set.size(), 100);
BOOST_CHECK_EQUAL(set.bucket_count(), 256);
}
BOOST_AUTO_TEST_CASE(IteratorOps)
{
RBX::DenseHashSet<int> set(-1);
set.insert(1);
set.insert(2);
RBX::DenseHashSet<int>::const_iterator it1 = set.begin();
RBX::DenseHashSet<int>::const_iterator it2 = it1;
RBX::DenseHashSet<int>::const_iterator it3 = ++it2;
RBX::DenseHashSet<int>::const_iterator it4 = it1;
RBX::DenseHashSet<int>::const_iterator it5 = it4++;
BOOST_CHECK_EQUAL(it1 == set.begin(), true);
BOOST_CHECK_EQUAL(it1 != set.begin(), false);
BOOST_CHECK_EQUAL(it1 == set.end(), false);
BOOST_CHECK_EQUAL(it1 != set.end(), true);
BOOST_CHECK(it2 == it4);
BOOST_CHECK(it2 != it1);
BOOST_CHECK(it2 != set.end());
BOOST_CHECK(it3 == it2);
BOOST_CHECK(it5 == it1);
BOOST_CHECK(it1 == it5);
BOOST_CHECK((*it1 == 1 && *it2 == 2) || (*it1 == 2 && *it1 == 1));
}
BOOST_AUTO_TEST_SUITE_END()
+179
View File
@@ -0,0 +1,179 @@
#include <boost/test/unit_test.hpp>
#include "FastLog.h"
#include "rbx/rbxTime.h"
using namespace boost;
LOGGROUP(UnitTestOn)
LOGGROUP(UnitTestOff)
LOGVARIABLE(UnitTestOn, 1)
LOGVARIABLE(UnitTestOff, 0)
DYNAMIC_FASTFLAGVARIABLE(DebugUnitDynamicFlag, true)
BOOST_AUTO_TEST_SUITE(FastLog)
static int i = 23;
static int increment() { return ++i; }
BOOST_AUTO_TEST_CASE(TrailingSemicolon)
{
if (false)
FASTLOG(FLog::UnitTestOn, "Just Message");
else
BOOST_CHECK(true);
}
BOOST_AUTO_TEST_CASE(Conditionals)
{
int i = 2;
if (false)
FASTLOG1(FLog::UnitTestOff, "Just Message %d", increment());
else if (true)
i = 4;
BOOST_CHECK_EQUAL(i, 4);
// If this test fails, then the macro was not written properly because
// it exposes a partial if-then block. (One more reason MACROS are worse than templates :)
//
// Here is the incorrect implementation:
// #define FASTLOG1(group,level,message,arg1) if(...) RBX::FastLog(...)
//
// Here is a correct implementation:
// #define FASTLOG1(group,level,message,arg1) do { if(...) RBX::FastLog(...); } while (0)
//
// The do {} while (0) clause is one way to wrap the macro into a self-contained statement
// IMPORTANT Notice that there is NO ";" at the end of the block.
// See http://stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block
}
BOOST_AUTO_TEST_CASE(LazyEval)
{
i = 3;
FASTLOG1(FLog::UnitTestOff, "Just Message %d", increment());
BOOST_CHECK_EQUAL(i, 3);
i = 13;
FASTLOG1(FLog::Warning, "Warning %d", increment());
BOOST_CHECK_EQUAL(i, 14);
i = 23;
FASTLOG1(FLog::Error, "Just Message %d", increment());
BOOST_CHECK_EQUAL(i, 24);
}
BOOST_AUTO_TEST_CASE(BasicLog)
{
RBX::Time start = RBX::Time::now<RBX::Time::Multimedia>();
std::string nullString = "", shortString = "aaaaa", longString = "very very long string";
for(int i = 0; i < LOG_HISTORY; i++)
{
FASTLOG(FLog::UnitTestOn, "Just Message");
FASTLOG1(FLog::UnitTestOn, "Message with argument %u", 1);
FASTLOG3(FLog::UnitTestOn, "Message with pointer %p, number %u and %u", this, 3, 2);
FASTLOGS(FLog::UnitTestOn, "String message - %s", "");
FASTLOGS(FLog::UnitTestOn, "String message - %s", "AAAAA");
FASTLOGS(FLog::UnitTestOn, "Large string message - %s", "01234567890123456789");
FASTLOG1F(FLog::UnitTestOn, "Message with argument %f", 10.0f);
FASTLOG3F(FLog::UnitTestOn, "Message with argument %f %f %f", 10.0f, 5.0f, -1.0f);
FASTLOG(FLog::UnitTestOn, "Log");
FASTLOG(FLog::UnitTestOn, "One more");
FASTLOG(FLog::UnitTestOff, "Off");
FASTLOG(FLog::UnitTestOff, "Off, but on");
FASTLOGS(FLog::UnitTestOn, "Null string message - %s", nullString);
FASTLOGS(FLog::UnitTestOn, "Short string message - %s", shortString);
FASTLOGS(FLog::UnitTestOn, "Long string message - %s", longString);
}
RBX::Time finish = RBX::Time::now<RBX::Time::Multimedia>();
FASTLOG1F(FLog::UnitTestOn, "Logging took %f seconds", (float)(finish - start).seconds());
}
FASTFLAGVARIABLE(TestFastFlag, false)
BOOST_AUTO_TEST_CASE(FastFlags)
{
// We can't do the following test because the --fflags= arg might have overriden it
//BOOST_CHECK_EQUAL(FFlag::TestFastFlag, false);
FLog::SetValue("TestFastFlag", "True", FASTVARTYPE_STATIC);
BOOST_CHECK_EQUAL(FFlag::TestFastFlag, true);
FLog::SetValue("TestFastFlag", "False", FASTVARTYPE_STATIC);
BOOST_CHECK_EQUAL(FFlag::TestFastFlag, false);
}
BOOST_AUTO_TEST_CASE(SettingUnknownGroups)
{
FLog::SetValue("UnknownGroup", "1", FASTVARTYPE_STATIC);
FLog::SetValue("UnknownFlag", "true", FASTVARTYPE_STATIC);
{
FLog::Channel UnknownGroup = 0;
FLog::RegisterLogGroup("UnknownGroup", &UnknownGroup);
bool UnknownFlag = 0;
FLog::RegisterFlag("UnknownFlag", &UnknownFlag);
BOOST_CHECK_EQUAL(UnknownGroup, 1);
BOOST_CHECK_EQUAL(UnknownFlag, true);
}
}
BOOST_AUTO_TEST_CASE(DynamicVariables)
{
FLog::SetValue("DebugUnitDynamicFlag", "false", FASTVARTYPE_STATIC);
BOOST_CHECK_EQUAL(DFFlag::DebugUnitDynamicFlag, true);
FLog::SetValue("DebugUnitDynamicFlag", "false", FASTVARTYPE_DYNAMIC);
BOOST_CHECK_EQUAL(DFFlag::DebugUnitDynamicFlag, false);
}
FASTINTVARIABLE(TestFastInt, 3)
BOOST_AUTO_TEST_CASE(FastInts)
{
FLog::SetValue("TestFastInt", "2", FASTVARTYPE_STATIC);
BOOST_CHECK_EQUAL(FInt::TestFastInt, 2);
}
SYNCHRONIZED_FASTFLAGVARIABLE(TestSynchronizedFlag, false);
BOOST_AUTO_TEST_CASE(SynchronizedFlagVariables)
{
FLog::SetValue("TestSynchronizedFlag", "true", FASTVARTYPE_STATIC);
BOOST_CHECK_EQUAL(SFFlag::TestSynchronizedFlag, false);
FLog::SetValue("TestSynchronizedFlag", "true", FASTVARTYPE_SYNC);
BOOST_CHECK_EQUAL(SFFlag::TestSynchronizedFlag, true);
BOOST_CHECK_EQUAL(*SFFlag::TestSynchronizedFlagIsSync, true);
FLog::ResetSynchronizedVariablesState();
BOOST_CHECK_EQUAL(*SFFlag::TestSynchronizedFlagIsSync, false);
FLog::SetValueFromServer("TestSynchronizedFlag", "true");
BOOST_CHECK_EQUAL(SFFlag::TestSynchronizedFlag, true);
BOOST_CHECK_EQUAL(*SFFlag::TestSynchronizedFlagIsSync, true);
}
SYNCHRONIZED_FASTINTVARIABLE(UnitSynchronizedInt, 0);
BOOST_AUTO_TEST_CASE(SynchronizedIntVariables)
{
FLog::SetValue("UnitSynchronizedInt", "1", FASTVARTYPE_STATIC);
BOOST_CHECK_EQUAL(SFInt::UnitSynchronizedInt, 0);
FLog::SetValue("UnitSynchronizedInt", "1", FASTVARTYPE_SYNC);
BOOST_CHECK_EQUAL(SFInt::UnitSynchronizedInt, 1);
// flag state was reset in the previous test, so IsSynce should be false here
BOOST_CHECK_EQUAL(*SFInt::UnitSynchronizedIntIsSync, false);
FLog::SetValueFromServer("UnitSynchronizedInt", "2");
BOOST_CHECK_EQUAL(SFInt::UnitSynchronizedInt, 2);
BOOST_CHECK_EQUAL(*SFInt::UnitSynchronizedIntIsSync, true);
}
BOOST_AUTO_TEST_SUITE_END()
+62
View File
@@ -0,0 +1,62 @@
#include <boost/test/unit_test.hpp>
#include "rbx/TaskScheduler.h"
#include "rbx/TaskScheduler.Job.h"
BOOST_AUTO_TEST_SUITE(TaskScheduler)
class ParallelTestJob : public RBX::TaskScheduler::Job
{
public:
int maxConcurrency;
ParallelTestJob()
:Job("ParallelTestJob", shared_ptr<RBX::TaskScheduler::Arbiter>())
{
maxConcurrency = 0;
}
RBX::Time::Interval sleepTime(const Stats& stats)
{
return computeStandardSleepTime(stats, 10);
}
virtual Job::Error error(const Stats& stats)
{
Job::Error result = computeStandardErrorCyclicExecutiveSleeping(stats, 10);
return result;
}
virtual RBX::TaskScheduler::StepResult step(const Stats& stats)
{
RBX::Time::Interval(0.1).sleep();
if (this->allotedConcurrency > maxConcurrency)
maxConcurrency = this->allotedConcurrency;
return RBX::TaskScheduler::Stepped;
}
virtual int getDesiredConcurrencyCount() const
{
return 4;
}
protected:
/*implement*/ double getPriorityFactor() { return 1.0; }
};
BOOST_AUTO_TEST_CASE(ParallelTest)
{
shared_ptr<ParallelTestJob> job(new ParallelTestJob());
RBX::TaskScheduler::singleton().add(job);
for (int i = 0; i < 20; ++i)
{
RBX::Time::Interval(1).sleep();
if (job->maxConcurrency > 1)
break;
}
BOOST_CHECK_GT(job->maxConcurrency, 1);
RBX::TaskScheduler::singleton().removeBlocking(job);
}
BOOST_AUTO_TEST_SUITE_END()
+89
View File
@@ -0,0 +1,89 @@
#include <boost/test/unit_test.hpp>
#include "rbx/rbxtime.h"
#include "rbxformat.h"
using namespace boost;
BOOST_AUTO_TEST_SUITE(Format)
BOOST_AUTO_TEST_CASE(SmallString)
{
std::string s;
for (int i=0; i<125; ++i)
s += "x";
BOOST_CHECK( RBX::format("%s", s.c_str()) == s);
}
BOOST_AUTO_TEST_CASE(BigString)
{
std::string s;
for (int i=0; i<500; ++i)
s += "x";
BOOST_CHECK( RBX::format("%s", s.c_str()) == s);
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(Time)
template <RBX::Time::SampleMethod T>
static void test()
{
BOOST_CHECK(true);
for (int i=0; i<1e7; ++i)
RBX::Time::now<T>();
}
BOOST_AUTO_TEST_CASE(Fast)
{
test<RBX::Time::Fast>();
}
BOOST_AUTO_TEST_CASE(Multimedia)
{
test<RBX::Time::Multimedia>();
}
BOOST_AUTO_TEST_CASE(Precise)
{
test<RBX::Time::Precise>();
}
template <RBX::Time::SampleMethod T>
static void testAccuracy()
{
RBX::Time was = RBX::Time::now<T>();
#ifdef _DEBUG
for (int i=0; i<1e4; ++i)
#else
for (int i=0; i<1e6; ++i)
#endif
{
RBX::Time now = RBX::Time::now<T>();
double sec = (now - was).seconds();
BOOST_CHECK_GE(sec, 0.0);
//BOOST_CHECK_LE(sec, 0.0011);
was = now;
}
}
BOOST_AUTO_TEST_CASE(FastAccuracy)
{
testAccuracy<RBX::Time::Fast>();
}
BOOST_AUTO_TEST_CASE(MultimediaAccuracy)
{
testAccuracy<RBX::Time::Multimedia>();
}
BOOST_AUTO_TEST_CASE(PreciseAccuracy)
{
testAccuracy<RBX::Time::Precise>();
}
BOOST_AUTO_TEST_SUITE_END()
+227
View File
@@ -0,0 +1,227 @@
#include <boost/test/unit_test.hpp>
#include "concurrent.h"
#include "rbx/atomic.h"
#include "rbx/boost.hpp"
namespace AtomicTest
{
BOOST_AUTO_TEST_SUITE(Atomic)
template<class V, class UV>
static void test()
{
#ifndef RBX_PLATFORM_IOS
{
rbx::atomic<V> v;
v = 0;
BOOST_CHECK_EQUAL(++v, (V)1);
BOOST_CHECK_EQUAL(--v, (V)0);
BOOST_CHECK_EQUAL(--v, -(V)1);
BOOST_CHECK_EQUAL(++v, (V)0);
/* // we dont test unsigned until further notice
rbx::atomic<UV> uv;
uv = 0;
BOOST_CHECK_EQUAL(--uv, (UV)~0);
BOOST_CHECK_EQUAL(++uv, (UV)0);
*/
}
#endif
{
rbx::atomic<V> v;
BOOST_CHECK_EQUAL(++v, (V)1);
BOOST_CHECK_EQUAL(--v, (V)0);
BOOST_CHECK_EQUAL(--v, -(V)1);
BOOST_CHECK_EQUAL(++v, (V)0);
#ifndef RBX_PLATFORM_IOS
/* // we dont test unsigned until further notice
rbx::atomic<UV> uv;
BOOST_CHECK_EQUAL(--uv, (UV)~0);
BOOST_CHECK_EQUAL(++uv, (UV)0);
*/
#endif
}
}
BOOST_AUTO_TEST_CASE(Int)
{
test<int, unsigned int>();
}
BOOST_AUTO_TEST_CASE(Long)
{
test<long, unsigned long>();
}
// may need longlong test when we finally implement it
template<typename T>
struct TestIncrement
{
TestIncrement()
{
const int threads = 8;
const int iterations = 1000000;
rbx::atomic<T> state;
util::ConcurrentLoops<Incrementer>::run(Incrementer(state), iterations, threads);
BOOST_CHECK_EQUAL(state, threads * iterations);
util::ConcurrentLoops<Decrementer>::run(Decrementer(state), iterations / 2, threads);
BOOST_CHECK_EQUAL(state, threads * iterations / 2);
util::ConcurrentLoops<Decrementer>::run(Decrementer(state), iterations / 2, threads);
BOOST_CHECK_EQUAL(state, 0);
}
private:
struct Incrementer
{
int operator()(int)
{
++state_;
return 0;
}
Incrementer(rbx::atomic<T> &state) : state_(state) {}
private:
rbx::atomic<T> &state_;
};
struct Decrementer
{
int operator()(int)
{
--state_;
return 0;
}
Decrementer(rbx::atomic<T> &state) : state_(state) {}
private:
rbx::atomic<T> &state_;
};
};
template <typename T>
struct TestCASFalsePositive
{
TestCASFalsePositive()
{
const int threads = 8;
const int iterations = 1000000;
rbx::atomic<T> state;
BOOST_CHECK_EQUAL(state, 0);
BOOST_CHECK_EQUAL(util::ConcurrentLoops<StateGrabber>::run(StateGrabber(state), iterations, threads), 0);
BOOST_CHECK_EQUAL(state, 0);
}
private:
struct StateGrabber
{
int operator()(int index)
{
const T target = index + 1;
if (0 == state_.compare_and_swap(target, 0))
{
if (state_.compare_and_swap(0, target) != target)
return 1;
}
return 0;
}
StateGrabber(rbx::atomic<T> &state) : state_(state) {}
private:
rbx::atomic<T> &state_;
};
};
template <typename T, int NThreads, int NIterations>
struct TestSwap
{
TestSwap()
{
rbx::atomic<T> histogram[NThreads + 1];
rbx::atomic<T> state;
BOOST_CHECK_EQUAL(state, 0);
for (auto &h : histogram) // curly braces are important here due to compiler bug in visual studio < 2015
{
BOOST_CHECK_EQUAL(h, 0);
}
++histogram[0];
BOOST_CHECK_EQUAL(histogram[0], 1);
BOOST_CHECK_EQUAL(util::ConcurrentLoops<StateSwapper>::run(StateSwapper(state, histogram), NIterations, NThreads), 0);
BOOST_CHECK_LE(state, NThreads);
--histogram[state];
for (auto &h : histogram) // curly braces are important here due to compiler bug in visual studio < 2015
{
BOOST_CHECK_EQUAL(h, 0);
}
}
private:
struct StateSwapper
{
int operator()(int index)
{
const T target = index + 1;
const T old = state_.swap(target);
if (old > NThreads)
return 1;
++histogram_[target];
--histogram_[old];
return 0;
}
StateSwapper(rbx::atomic<T> &state, rbx::atomic<T> *histogram)
: state_(state)
, histogram_(histogram) {}
private:
rbx::atomic<T> &state_;
rbx::atomic<T> *histogram_;
};
};
// The tests below are independent tests -- only atomicity relative to
// the same kind of operation performed in another threads is tested.
// Currenly there are no tests for cas vs. inc/dec vs. swap() atomicity.
// TODO
BOOST_AUTO_TEST_CASE(increment)
{
TestIncrement<int> test_int;
TestIncrement<long> test_long;
}
BOOST_AUTO_TEST_CASE(cas_false_positive)
{
TestCASFalsePositive<int> test_int;
TestCASFalsePositive<long> test_long;
}
BOOST_AUTO_TEST_CASE(swap)
{
TestSwap<int, 8, 1000000> test_int;
TestSwap<long, 8, 1000000> test_long;
}
BOOST_AUTO_TEST_SUITE_END() // Atomic
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <boost/thread.hpp>
namespace util
{
template <typename F>
struct ConcurrentLoops
{
static int run(F f, int iterations, int num_threads)
{
int result = 0;
std::vector<std::pair<boost::thread*, int> > threads(num_threads);
int index = 0;
for (auto &it : threads)
{
it.first = new boost::thread(threadFunc, f, index++, iterations, it.second);
}
for (auto &it : threads)
{
it.first->join();
delete it.first;
it.first = 0;
if (it.second)
result = it.second;
}
return result;
}
private:
static void threadFunc(F &f, int index, int iterations, int &result)
{
for (int i = 0; i < iterations; ++i)
{
result = f(index);
if (result)
break;
}
}
}; // struct ConcurrentLoops
} // namespace utils
+304
View File
@@ -0,0 +1,304 @@
#include <boost/test/unit_test.hpp>
#include "boost/shared_ptr.hpp"
#include "boost/weak_ptr.hpp"
#include "rbx/intrusive_ptr_target.h"
#include "rbx/intrusive_weak_ptr.h"
namespace IntrusiveTest
{
class CountedBase : boost::noncopyable
{
public:
std::string foo;
static int count;
int id;
CountedBase()
{
count++;
static int guid = 0;
id = ++guid;
}
~CountedBase()
{
foo = "bye base!";
count--;
}
};
int CountedBase::count = 0;
class Counted
: public rbx::intrusive_ptr_target<Counted>
, public CountedBase
{
public:
Counted() {
}
virtual ~Counted()
{
foo = "bye!";
}
};
class CountedChild : public Counted
{
public:
~CountedChild()
{
foo = "bye child!";
}
};
class QuickCounted
: public rbx::quick_intrusive_ptr_target<QuickCounted>
, public CountedBase
{
public:
QuickCounted() {
}
virtual ~QuickCounted()
{
foo = "bye!";
}
};
class QuickCountedChild : public QuickCounted
{
public:
~QuickCountedChild()
{
foo = "bye child!";
}
};
class CountedFixture
{
int count;
public:
CountedFixture() {
count = CountedBase::count;
}
~CountedFixture() {
BOOST_CHECK_EQUAL(CountedBase::count, count);
}
};
BOOST_FIXTURE_TEST_SUITE(intrusive_ptr, CountedFixture)
BOOST_AUTO_TEST_CASE(Test)
{
boost::intrusive_ptr<Counted> p1 = new CountedChild();
BOOST_CHECK_EQUAL(1, Counted::count);
//BOOST_CHECK_EQUAL(1, p1.use_count());
{
boost::intrusive_ptr<Counted> p2 = p1;
boost::intrusive_ptr<Counted> p3(p1);
//BOOST_CHECK_EQUAL(3, p1.use_count());
//BOOST_CHECK_EQUAL(3, p2.use_count());
//BOOST_CHECK_EQUAL(3, p3.use_count());
p3.reset();
BOOST_CHECK_EQUAL(1, Counted::count);
//BOOST_CHECK_EQUAL(2, p1.use_count());
//BOOST_CHECK_EQUAL(2, p2.use_count());
//BOOST_CHECK_EQUAL(0, p3.use_count());
}
//BOOST_CHECK_EQUAL(1, p1.use_count());
}
BOOST_AUTO_TEST_CASE(Operators)
{
boost::intrusive_ptr<Counted> p1 = new CountedChild();
BOOST_CHECK_EQUAL(1, Counted::count);
Counted* c1 = p1.get();
BOOST_CHECK_EQUAL(1, Counted::count);
Counted& c2 = *p1;
BOOST_CHECK_EQUAL(1, Counted::count);
BOOST_CHECK_EQUAL(c1, &c2);
BOOST_CHECK_EQUAL(c2.id, p1->id);
BOOST_CHECK_EQUAL(c2.id, (*p1).id);
}
#ifdef _DEBUG
#define ccc 1
#else
#define ccc 10000000
#endif
BOOST_AUTO_TEST_CASE(Perf_Intrusive)
{
boost::intrusive_ptr<Counted> p1 = new CountedChild();
boost::intrusive_ptr<Counted> w;
for (int i = 0; i < ccc; ++i)
{
boost::intrusive_ptr<Counted> w1 = p1;
w = p1;
w.reset();
}
}
BOOST_AUTO_TEST_CASE(Perf_Quick)
{
boost::intrusive_ptr<QuickCounted> p1 = new QuickCountedChild();
boost::intrusive_ptr<QuickCounted> w;
for (int i = 0; i < ccc; ++i)
{
boost::intrusive_ptr<QuickCounted> w1 = p1;
w = p1;
w.reset();
}
}
BOOST_AUTO_TEST_CASE(Perf_Shared)
{
boost::shared_ptr<Counted> p1(new CountedChild());
boost::shared_ptr<Counted> w;
for (int i = 0; i < ccc; ++i)
{
boost::shared_ptr<Counted> w1 = p1;
w = p1;
w.reset();
}
}
BOOST_AUTO_TEST_CASE(PerfDelete_Intrusive)
{
for (int i = 0; i <= ccc/10; ++i)
{
boost::intrusive_ptr<Counted> p1 = new CountedChild();
}
}
BOOST_AUTO_TEST_CASE(PerfDelete_Quick)
{
for (int i = 0; i <= ccc/10; ++i)
{
boost::intrusive_ptr<QuickCounted> p1 = new QuickCountedChild();
}
}
BOOST_AUTO_TEST_CASE(PerfDelete_Shared)
{
for (int i = 0; i <= ccc/10; ++i)
{
boost::shared_ptr<Counted> p1(new CountedChild());
}
}
BOOST_AUTO_TEST_CASE(PerfWeak_Intrusive)
{
boost::intrusive_ptr<Counted> p1 = new CountedChild();
rbx::intrusive_weak_ptr<Counted> w;
for (int i = 0; i < ccc; ++i)
{
rbx::intrusive_weak_ptr<Counted> w1 = p1;
w = p1;
w.reset();
}
}
BOOST_AUTO_TEST_CASE(PerfWeak_Shared)
{
boost::shared_ptr<Counted> p1(new CountedChild());
boost::weak_ptr<Counted> w;
for (int i = 0; i < ccc; ++i)
{
boost::weak_ptr<Counted> w1 = p1;
w = p1;
w.reset();
}
}
BOOST_AUTO_TEST_CASE(WeakTest)
{
boost::intrusive_ptr<CountedChild> p1 = new CountedChild();
BOOST_CHECK_EQUAL(1, Counted::count);
//BOOST_CHECK_EQUAL(1, p1.use_count());
rbx::intrusive_weak_ptr<CountedChild> w1 = p1;
//BOOST_CHECK_EQUAL(1, p1.use_count());
rbx::intrusive_weak_ptr<CountedChild> w2 = w1;
//BOOST_CHECK_EQUAL(1, p1.use_count());
rbx::intrusive_weak_ptr<Counted> w4(w1);
rbx::intrusive_weak_ptr<Counted> w5(p1);
rbx::intrusive_weak_ptr<Counted> w6(p1.get());
rbx::intrusive_weak_ptr<Counted> w;
w = w1;
w = p1;
w = p1.get();
boost::intrusive_ptr<Counted> p2 = w1.lock();
//BOOST_CHECK_EQUAL(2, p1.use_count());
BOOST_CHECK_EQUAL(1, Counted::count);
{
if (boost::intrusive_ptr<Counted> p3 = w1.lock())
//BOOST_CHECK_EQUAL(3, p1.use_count());
;
else
BOOST_CHECK(false);
}
p1.reset();
BOOST_CHECK_NO_THROW(boost::intrusive_ptr<Counted>(w1.lock()).get());
p2.reset();
BOOST_CHECK_EQUAL(0, Counted::count);
//BOOST_CHECK_EQUAL(0, p1.use_count());
p2 = w1.lock();
BOOST_CHECK(!p2);
//BOOST_CHECK_THROW(boost::intrusive_ptr<Counted>(w1.lock()).get(), rbx::bad_weak_ptr);
}
#ifndef RBX_PLATFORM_IOS
class OF
: public rbx::intrusive_ptr_target<OF, int, 1, 2>
{
};
BOOST_AUTO_TEST_CASE(Overflow)
{
boost::intrusive_ptr<OF> of(new OF());
boost::intrusive_ptr<OF> of2;
BOOST_CHECK_THROW(of2 = of, rbx::too_many_refs);
BOOST_CHECK_THROW(of2 = of, std::exception);
rbx::intrusive_weak_ptr<OF> w[10];
w[0] = of;
w[1] = w[0];
BOOST_CHECK_THROW(w[2] = w[0], rbx::too_many_refs);
BOOST_CHECK_THROW(w[2] = w[0], std::exception);
}
#endif
BOOST_AUTO_TEST_SUITE_END()
}
+31
View File
@@ -0,0 +1,31 @@
#include <boost/test/unit_test.hpp>
#include "boost/shared_ptr.hpp"
#include "boost/weak_ptr.hpp"
#include "rbx/make_shared.h"
using namespace boost;
struct Counted : boost::noncopyable {
static int count;
Counted() { count++; }
~Counted() { count--; }
};
int Counted::count = 0;
BOOST_AUTO_TEST_SUITE(MakeShared)
BOOST_AUTO_TEST_CASE(Destructor)
{
BOOST_CHECK_EQUAL(0, Counted::count);
shared_ptr<Counted> p = rbx::make_shared<Counted>();
BOOST_CHECK_EQUAL(1, Counted::count);
weak_ptr<Counted> w = p;
BOOST_CHECK_EQUAL(1, Counted::count);
p.reset();
BOOST_CHECK_EQUAL(0, Counted::count);
}
BOOST_AUTO_TEST_SUITE_END()
+483
View File
@@ -0,0 +1,483 @@
#include <boost/test/unit_test.hpp>
#include "rbx/signal.h"
class Foo {};
static void add(int i, int& result)
{
result += i;
}
static void throw_runtime_error()
{
throw std::runtime_error("");
}
static void exception_handler(std::exception& ex)
{
BOOST_CHECK(false);
}
static void addConnection(int i, int& result, rbx::signal<void(int)>& sig1)
{
add(i, result);
sig1.connect(boost::bind(&add, _1, boost::ref(result)));
}
static void removeConnection(int i, int& result, rbx::signals::connection& connection)
{
add(i, result);
connection.disconnect();
}
static void append(std::string* s, const char* append)
{
*s += append;
}
void emptyFunction()
{
}
void emptyFunction2(int)
{
}
class SignalsFixture
{
boost::function<void(std::exception&)> slot_exception_handler;
public:
SignalsFixture()
{
slot_exception_handler = rbx::signals::slot_exception_handler;
rbx::signals::slot_exception_handler = &exception_handler;
}
~SignalsFixture()
{
rbx::signals::slot_exception_handler = slot_exception_handler;
}
};
BOOST_FIXTURE_TEST_SUITE(Signals, SignalsFixture)
BOOST_AUTO_TEST_CASE(SimpleTest)
{
rbx::signal<void(int)> sig1;
//char m[1111];
//sprintf(m, "%d %d", rbx::signal<void(int)>::sizeof_slot(), rbx::signal<void(int, std::string, bool)>::sizeof_slot());
int result = 0;
rbx::signals::connection connection = sig1.connect(boost::bind(&add, _1, boost::ref(result)));
sig1(12);
BOOST_CHECK_EQUAL(12, result);
connection.disconnect();
result = 0;
sig1(12);
BOOST_CHECK_EQUAL(0, result);
}
BOOST_AUTO_TEST_CASE(EmptyTest)
{
rbx::signal<void(int)> sig1;
BOOST_CHECK(sig1.empty());
int result = 0;
rbx::signals::connection connection = sig1.connect(boost::bind(&add, _1, boost::ref(result)));
BOOST_CHECK(!sig1.empty());
rbx::signals::connection connection2 = sig1.connect(boost::bind(&add, _1, boost::ref(result)));
BOOST_CHECK(!sig1.empty());
connection.disconnect();
BOOST_CHECK(!sig1.empty());
connection2.disconnect();
BOOST_CHECK(sig1.empty());
}
BOOST_AUTO_TEST_CASE(SimpleTest2)
{
rbx::signal<void(bool, int)> sig1;
int result = 0;
rbx::signals::connection connection = sig1.connect(boost::bind(&add, _2, boost::ref(result)));
sig1(true, 12);
BOOST_CHECK_EQUAL(12, result);
connection.disconnect();
result = 0;
sig1(false, 12);
BOOST_CHECK_EQUAL(0, result);
}
BOOST_AUTO_TEST_CASE(SimpleTest3)
{
rbx::signal<void(bool, const char*, int)> sig1;
int result = 0;
rbx::signals::connection connection = sig1.connect(boost::bind(&add, _3, boost::ref(result)));
sig1(false, "", 12);
BOOST_CHECK_EQUAL(12, result);
connection.disconnect();
result = 0;
sig1(false, "", 12);
BOOST_CHECK_EQUAL(0, result);
}
BOOST_AUTO_TEST_CASE(SimpleTest4)
{
rbx::signal<void(bool, const char*, Foo, int)> sig1;
int result = 0;
rbx::signals::connection connection = sig1.connect(boost::bind(&add, _4, boost::ref(result)));
sig1(false, "", Foo(), 12);
BOOST_CHECK_EQUAL(12, result);
connection.disconnect();
result = 0;
sig1(false, "", Foo(), 12);
BOOST_CHECK_EQUAL(0, result);
}
/* A simplified version of PartInstance::TouchedSignal */
class TouchedSignal : public rbx::signal<void()>
{
private:
typedef rbx::signal<void()> Super;
class TouchedSlot
{
boost::function<void()> inner;
public:
TouchedSlot(const boost::function<void()>& inner):inner(inner)
{
}
TouchedSlot(const TouchedSlot& other) : inner(other.inner)
{
}
TouchedSlot& operator=(const TouchedSlot& other);
~TouchedSlot()
{
// Try to create a deadlock
rbx::signal<void()> sig;
rbx::signals::scoped_connection connection(sig.connect(boost::bind(emptyFunction)));
sig();
}
void operator()()
{
if (inner)
inner();
}
};
public:
template<typename F>
rbx::signals::connection connect(F slot)
{
return Super::connect(TouchedSlot(slot));
}
static void disc(rbx::signals::connection* c)
{
c->disconnect();
}
};
BOOST_AUTO_TEST_CASE(Deadlock)
{
// This code will deadlock if ~TouchedSignal is called within a signal mutex.
// It happened when I tried to optimize next() by passig the shared_ptr<slot> by
// reference. This caused the slot to be collected within the mutex, which has side
// effects. We must avoid any side effects within the mutex to avoid deadlocks and
// also to avoid thread starvation if the mutex is a spin mutex.
TouchedSignal* tester = new TouchedSignal();
rbx::signals::connection connection;
connection = tester->connect(boost::bind(TouchedSignal::disc, &connection));
(*tester)();
connection.disconnect();
delete tester;
}
BOOST_AUTO_TEST_CASE(ExceptionHandling)
{
int exceptionCount = 0;
rbx::signals::slot_exception_handler = boost::bind(add, 1, boost::ref(exceptionCount));
rbx::signal<void(int)> sig1;
rbx::signals::connection connection = sig1.connect(boost::bind(throw_runtime_error));
int result = 0;
sig1.connect(boost::bind(&add, _1, boost::ref(result)));
sig1(12);
BOOST_CHECK_EQUAL(12, result);
BOOST_CHECK_EQUAL(1, exceptionCount);
connection.disconnect();
result = 0;
sig1(12);
BOOST_CHECK_EQUAL(12, result);
}
BOOST_AUTO_TEST_CASE(EmptySlot)
{
rbx::signal<void(int)> sig1;
int result = 0;
rbx::signals::connection connection = sig1.connect(boost::bind(emptyFunction2, _1));
sig1(12);
BOOST_CHECK_EQUAL(0, result);
connection.disconnect();
result = 0;
sig1(12);
BOOST_CHECK_EQUAL(0, result);
}
BOOST_AUTO_TEST_CASE(RemoveWhileFiring)
{
rbx::signal<void(int)> sig1;
int result = 0;
rbx::signals::connection connectionToRemove;
// add a dummy slot
sig1.connect(boost::bind(&add, _1, boost::ref(result)));
rbx::signals::connection connectionThatRemoves = sig1.connect(boost::bind(&removeConnection, _1, boost::ref(result), boost::ref(connectionToRemove)));
// add another slot
connectionToRemove = sig1.connect(boost::bind(&add, _1, boost::ref(result)));
BOOST_CHECK(connectionToRemove.connected());
result = 0;
sig1(1);
BOOST_CHECK(!connectionToRemove.connected());
BOOST_CHECK_EQUAL(3, result);
// Now call them again, expecting to lose one slot call
result = 0;
sig1(1);
BOOST_CHECK_EQUAL(2, result);
// Now cause the slot to remove its own connection:
connectionToRemove = connectionThatRemoves;
BOOST_CHECK(connectionToRemove.connected());
result = 0;
sig1(1);
BOOST_CHECK(!connectionToRemove.connected());
BOOST_CHECK_EQUAL(2, result);
result = 0;
sig1(1);
BOOST_CHECK_EQUAL(1, result);
}
BOOST_AUTO_TEST_CASE(AddWhileFiring)
{
rbx::signal<void(int)> sig1;
int result = 0;
// add a dummy slot
sig1.connect(boost::bind(&add, _1, boost::ref(result)));
rbx::signals::connection connection = sig1.connect(boost::bind(&addConnection, _1, boost::ref(result), boost::ref(sig1)));
result = 0;
sig1(1);
BOOST_CHECK_EQUAL(2, result);
result = 0;
sig1(1);
BOOST_CHECK_EQUAL(3, result);
connection.disconnect();
result = 0;
sig1(1);
BOOST_CHECK_EQUAL(3, result);
}
BOOST_AUTO_TEST_CASE(FireOrder)
{
// This may not be guaranteed in the future, but slots are added to the head of the chain.
// The reason for having this test is to warn that there may be breaking changes.
rbx::signal<void(std::string*)> sig1;
std::string result;
sig1.connect(boost::bind(&append, _1, "World"));
sig1.connect(boost::bind(&append, _1, "Hello"));
sig1(&result);
BOOST_CHECK_EQUAL(result, "HelloWorld");
}
BOOST_AUTO_TEST_CASE(DoubleDisconnect)
{
rbx::signal<void(std::string*)> sig1;
std::string result;
rbx::signals::connection c1 = sig1.connect(boost::bind(&append, _1, "Hi"));
rbx::signals::connection c2 = c1;
sig1(&result);
BOOST_CHECK_EQUAL(result, "Hi");
c1.disconnect();
sig1(&result);
BOOST_CHECK_EQUAL(result, "Hi");
c2.disconnect();
sig1(&result);
BOOST_CHECK_EQUAL(result, "Hi");
}
BOOST_AUTO_TEST_CASE(DisconnectWhileFiring)
{
rbx::signal<void(rbx::signals::connection*)> sig1;
rbx::signals::connection connection = sig1.connect(boost::bind(&rbx::signals::connection::disconnect, _1));
BOOST_CHECK(connection.connected());
sig1(&connection);
BOOST_CHECK(!connection.connected());
}
BOOST_AUTO_TEST_CASE(AssignmentOperator)
{
rbx::signal<void(std::string*)> sig1;
std::string result;
{
rbx::signals::scoped_connection connection(sig1.connect(boost::bind(&append, _1, "[Not Me!]")));
connection = sig1.connect(boost::bind(&append, _1, "Hello"));
sig1(&result);
BOOST_CHECK_EQUAL(result, "Hello");
}
result.clear();
sig1(&result);
BOOST_CHECK_EQUAL(result, "");
}
static void doubleDisconnect(rbx::signals::connection& connection, std::string* s)
{
*s += "Hi";
connection.disconnect();
connection.disconnect();
}
static void dont_call_me()
{
BOOST_CHECK(false);
}
static void remove_connections(rbx::signals::connection* c1, rbx::signals::connection* c2, rbx::signals::connection* c3)
{
c3->disconnect();
c2->disconnect();
c1->disconnect();
}
BOOST_AUTO_TEST_CASE(MultiDisconnect)
{
// Tests CS1502 - a bug that Simon found
rbx::signal<void()> sig1;
rbx::signals::connection c1 = sig1.connect(boost::bind(&dont_call_me));
rbx::signals::connection c2 = sig1.connect(boost::bind(&dont_call_me));
rbx::signals::connection c3;
c3 = sig1.connect(boost::bind(remove_connections, &c1, &c2, &c3));
sig1();
}
BOOST_AUTO_TEST_CASE(ReentrantDoubleDisconnect)
{
rbx::signal<void(std::string*)> sig1;
std::string result;
rbx::signals::connection connection = sig1.connect(boost::bind(doubleDisconnect, boost::ref(connection), &result));
sig1(&result);
BOOST_CHECK_EQUAL(result, "Hi");
}
static void reset(rbx::signal<void(std::string*)>& sig1, rbx::signals::scoped_connection& connection, std::string message, std::string* s)
{
*s += message;
connection = sig1.connect(boost::bind(&reset, boost::ref(sig1), boost::ref(connection), message + "#", _1));
}
BOOST_AUTO_TEST_CASE(ReentrantResetScopedConnection)
{
rbx::signal<void(std::string*)> sig1;
std::string result;
rbx::signals::scoped_connection connection;
reset(sig1, connection, "Reset", &result);
BOOST_CHECK_EQUAL(result, "Reset");
result.clear();
sig1.connect(boost::bind(&append, _1, "Hello"));
sig1(&result);
BOOST_CHECK_EQUAL(result, "HelloReset#");
result.clear();
sig1(&result);
BOOST_CHECK_EQUAL(result, "Reset##Hello");
result.clear();
sig1(&result);
BOOST_CHECK_EQUAL(result, "Reset###Hello");
}
BOOST_AUTO_TEST_CASE(SlotChain)
{
// Make sure a huge chain of slots doesn't cause a stack crash on destruction
// See DE131
rbx::signal<void()> signal;
for (int i = 0; i < 1000; ++i)
signal.connect(boost::function<void()>());
BOOST_CHECK(true);
}
BOOST_AUTO_TEST_CASE(ReverseDestruction)
{
// Make sure it is safe to disconnect a connection after the slot has been destroyed
rbx::signals::connection connection;
{
rbx::signal<void()> signal;
connection = signal.connect(boost::function<void()>());
}
connection.disconnect();
BOOST_CHECK(true);
}
#ifndef _DEBUG
BOOST_AUTO_TEST_CASE(PerfSignal)
{
rbx::signal<void(std::string, int)> sig1;
int result = 0;
rbx::signals::scoped_connection connection[10];
for (int i = 0; i < 5; ++i)
connection[i] = sig1.connect(boost::bind(&add, _2, boost::ref(result)));
for (int i = 0; i < 1e6; ++i)
sig1("Hello World", 12);
}
BOOST_AUTO_TEST_CASE(PerfConnect)
{
rbx::signal<void(bool, int)> sig1;
int result = 0;
for (int i = 0; i < 1e6; ++i)
{
rbx::signals::connection connection = sig1.connect(boost::bind(&add, _2, boost::ref(result)));
connection.disconnect();
}
}
#endif
BOOST_AUTO_TEST_SUITE_END()
+52
View File
@@ -0,0 +1,52 @@
#include <boost/test/unit_test.hpp>
#include "concurrent.h"
#include "rbx/threadsafe.h"
namespace spin_mutex_test
{
BOOST_AUTO_TEST_SUITE(spin_mutex)
struct ConcurrentAccess
{
ConcurrentAccess()
{
const int threads = 8;
const int iterations = 1000000;
rbx::spin_mutex mutex;
int value = 0;
int expected_value = 0;
for (int i = 1; i <= threads; ++i)
expected_value += i * iterations;
BOOST_CHECK_EQUAL(util::ConcurrentLoops<Adder>::run(Adder(mutex, value), iterations, threads), 0);
BOOST_CHECK_EQUAL(value, expected_value);
}
private:
struct Adder
{
int operator()(int index)
{
rbx::spin_mutex::scoped_lock lock(mutex_);
value_ += index + 1;
return 0;
}
Adder(rbx::spin_mutex& mutex, int& value) : mutex_(mutex), value_(value) {}
private:
rbx::spin_mutex& mutex_;
int& value_;
};
};
BOOST_AUTO_TEST_CASE(concurrent_access)
{
ConcurrentAccess test;
}
BOOST_AUTO_TEST_SUITE_END() // spin_mutex
} // namespace spin_mutex_test
+129
View File
@@ -0,0 +1,129 @@
#include <boost/test/unit_test.hpp>
#include <map>
#include <string>
#include <boost/unordered_map.hpp>
#include "rbx/trie.h"
BOOST_AUTO_TEST_SUITE(Trie)
BOOST_AUTO_TEST_CASE(NameConflict)
{
int v;
rbx::trie<int, 10> trie;
trie["ab"] = 1;
BOOST_CHECK(trie.lookup("ab", v));
BOOST_CHECK_EQUAL(v, 1);
trie["a"] = 2;
BOOST_CHECK(trie.lookup("ab", v));
BOOST_CHECK_EQUAL(v, 1);
BOOST_CHECK(trie.lookup("a", v));
BOOST_CHECK_EQUAL(v, 2);
trie["ac"] = 3;
BOOST_CHECK(trie.lookup("ab", v));
BOOST_CHECK_EQUAL(v, 1);
BOOST_CHECK(trie.lookup("a", v));
BOOST_CHECK_EQUAL(v, 2);
BOOST_CHECK(trie.lookup("ac", v));
BOOST_CHECK_EQUAL(v, 3);
trie["acart"] = 4;
BOOST_CHECK(!trie.lookup("aca", v));
BOOST_CHECK(!trie.lookup("acar", v));
BOOST_CHECK(trie.lookup("acart", v));
BOOST_CHECK_EQUAL(v, 4);
BOOST_CHECK(trie.lookup("ab", v));
BOOST_CHECK_EQUAL(v, 1);
BOOST_CHECK(trie.lookup("a", v));
BOOST_CHECK_EQUAL(v, 2);
BOOST_CHECK(trie.lookup("ac", v));
BOOST_CHECK_EQUAL(v, 3);
}
static std::string newKey()
{
std::string key;
for (int k = 0; k < 10; ++k)
{
int r = 32 + rand() % 96;
key += (char) r;
}
return key;
}
typedef rbx::trie<int, 30> Trie;
static std::string init(Trie& trie, std::map<std::string, int>& map, boost::unordered_map<std::string, int>& hashmap)
{
std::string key;
for (int i = 0; i < 100; ++i)
{
key = newKey();
static int j = 0;
int value = ++j;
trie[key.c_str()] = value;
map[key] = value;
hashmap[key] = value;
int v;
BOOST_REQUIRE(trie.lookup(key.c_str(), v));
BOOST_REQUIRE_EQUAL(v, value);
BOOST_REQUIRE_EQUAL(map[key], value);
}
return key;
}
BOOST_AUTO_TEST_CASE(SimpleTest)
{
Trie trie;
std::map<std::string, int> map;
boost::unordered_map<std::string, int> hashmap;
std::string key = init(trie, map, hashmap);
}
#ifndef _DEBUG
BOOST_AUTO_TEST_CASE(PerfTrie)
{
Trie trie;
std::map<std::string, int> map;
boost::unordered_map<std::string, int> hashmap;
std::string key = init(trie, map, hashmap);
int v;
for (int i = 0; i < 1000000; ++i)
trie.lookup(key.c_str(), v);
}
BOOST_AUTO_TEST_CASE(PerfMap)
{
Trie trie;
std::map<std::string, int> map;
boost::unordered_map<std::string, int> hashmap;
std::string key = init(trie, map, hashmap);
for (int i = 0; i < 1000000; ++i)
map.find(key);
}
BOOST_AUTO_TEST_CASE(PerfHashMap)
{
Trie trie;
std::map<std::string, int> map;
boost::unordered_map<std::string, int> hashmap;
std::string key = init(trie, map, hashmap);
for (int i = 0; i < 1000000; ++i)
hashmap.find(key);
}
#endif
BOOST_AUTO_TEST_SUITE_END()