Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -343,4 +343,4 @@ ASALocalRun/
*.[0-9].rule.txt
*.[0-9][0-9].rule.txt
*.[0-9][0-9][0-9].rule.txt
*.[0-9][0-9][0-9][0-9].rule.txt
*.[0-9][0-9][0-9][0-9].rule.txtcpp/build/
37 changes: 37 additions & 0 deletions TestVerification/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Platform.Ranges;

// Simple script to manually verify range functionality
Console.WriteLine("=== Range Coverage Verification ===\n");

// Test basic range functionality
Console.WriteLine("1. Basic Range Construction:");
var range1 = new Range<int>(1, 10);
var range2 = new Range<int>(5);
Console.WriteLine($"Range(1, 10): {range1}");
Console.WriteLine($"Range(5): {range2}");

// Test contains functionality
Console.WriteLine("\n2. Contains Tests:");
Console.WriteLine($"Range(1, 10).Contains(5): {range1.Contains(5)}");
Console.WriteLine($"Range(1, 10).Contains(15): {range1.Contains(15)}");
Console.WriteLine($"Range(1, 10).Contains(Range(2, 8)): {range1.Contains(new Range<int>(2, 8))}");

// Test difference extensions
Console.WriteLine("\n3. Difference Extensions:");
Console.WriteLine($"Range(1, 10).Difference(): {range1.Difference()}");
var doubleRange = new Range<double>(1.5, 5.5);
Console.WriteLine($"Range<double>(1.5, 5.5).Difference(): {doubleRange.Difference()}");

// Test static ranges
Console.WriteLine("\n4. Static Range Constants:");
Console.WriteLine($"Range.Int32: {Platform.Ranges.Range.Int32}");
Console.WriteLine($"Range.Byte: {Platform.Ranges.Range.Byte}");

// Test implicit operators
Console.WriteLine("\n5. Implicit Operators:");
(int min, int max) tuple = range1;
Console.WriteLine($"Range to tuple: ({tuple.min}, {tuple.max})");
Range<int> rangeFromTuple = (20, 30);
Console.WriteLine($"Tuple to Range: {rangeFromTuple}");

Console.WriteLine("\n=== All tests completed successfully! ===");
14 changes: 14 additions & 0 deletions TestVerification/TestVerification.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../csharp/Platform.Ranges/Platform.Ranges.csproj" />
</ItemGroup>

</Project>
145 changes: 143 additions & 2 deletions cpp/Platform.Ranges.Tests/EnsureExtensionsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,152 @@
{
TEST(EnsureExtensionsTests, MaximumArgumentIsGreaterOrEqualToMinimumExceptionTest)
{
EXPECT_THROW(Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(2, 1), std::logic_error);
EXPECT_THROW(Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(2, 1), std::invalid_argument);
}

TEST(EnsureExtensionsTests, MaximumArgumentIsGreaterOrEqualToMinimumValidTest)
{
EXPECT_NO_THROW(Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(1, 2));
EXPECT_NO_THROW(Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(5, 5));
EXPECT_NO_THROW(Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(1, 2, "testParam"));
EXPECT_NO_THROW(Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(1, 2, "testParam", "Test message"));
}

TEST(EnsureExtensionsTests, MaximumArgumentIsGreaterOrEqualToMinimumWithCustomMessageTest)
{
try
{
Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(5, 3, "maxParam", "Custom error message");
FAIL() << "Expected std::invalid_argument";
}
catch (const std::invalid_argument& e)
{
std::string message(e.what());
EXPECT_TRUE(message.find("Custom error message") != std::string::npos);
EXPECT_TRUE(message.find("maxParam") != std::string::npos);
}
}

TEST(EnsureExtensionsTests, MaximumArgumentIsGreaterOrEqualToMinimumWithMessageBuilderTest)
{
try
{
Ensure::Always::MaximumArgumentIsGreaterOrEqualToMinimum(5, 3, "maxParam", []() { return std::string("Lambda message"); });
FAIL() << "Expected std::invalid_argument";
}
catch (const std::invalid_argument& e)
{
std::string message(e.what());
EXPECT_TRUE(message.find("Lambda message") != std::string::npos);
}
}

TEST(EnsureExtensionsTests, ArgumentInRangeExceptionTest)
{
EXPECT_THROW(Ensure::Always::ArgumentInRange(5, 6, 7), std::logic_error);
EXPECT_THROW(Ensure::Always::ArgumentInRange(5, 6, 7), std::invalid_argument);
}

TEST(EnsureExtensionsTests, ArgumentInRangeValidTest)
{
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(5, Range<int>(1, 10)));
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(5, Range<int>(5, 5)));
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(1, Range<int>(1, 10)));
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(10, Range<int>(1, 10)));
}

TEST(EnsureExtensionsTests, ArgumentInRangeWithArgumentNameTest)
{
try
{
Ensure::Always::ArgumentInRange(15, Range<int>(1, 10), "testParam");
FAIL() << "Expected std::invalid_argument";
}
catch (const std::invalid_argument& e)
{
std::string message(e.what());
EXPECT_TRUE(message.find("testParam") != std::string::npos);
EXPECT_TRUE(message.find("15") != std::string::npos);
}
}

TEST(EnsureExtensionsTests, ArgumentInRangeWithCustomMessageTest)
{
try
{
Ensure::Always::ArgumentInRange(15, Range<int>(1, 10), "testParam", "Custom range message");
FAIL() << "Expected std::invalid_argument";
}
catch (const std::invalid_argument& e)
{
std::string message(e.what());
EXPECT_TRUE(message.find("Custom range message") != std::string::npos);
}
}

TEST(EnsureExtensionsTests, ArgumentInRangeWithMessageBuilderTest)
{
try
{
Ensure::Always::ArgumentInRange(15, Range<int>(1, 10), "testParam", []() { return std::string("Lambda range message"); });
FAIL() << "Expected std::invalid_argument";
}
catch (const std::invalid_argument& e)
{
std::string message(e.what());
EXPECT_TRUE(message.find("Lambda range message") != std::string::npos);
}
}

TEST(EnsureExtensionsTests, ArgumentInRangeWithMinMaxTest)
{
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(5, 1, 10));
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(5, 1, 10, "testParam"));

try
{
Ensure::Always::ArgumentInRange(15, 1, 10, "testParam");
FAIL() << "Expected std::invalid_argument";
}
catch (const std::invalid_argument& e)
{
std::string message(e.what());
EXPECT_TRUE(message.find("testParam") != std::string::npos);
}
}

TEST(EnsureExtensionsTests, ArgumentInRangeDifferentTypesTest)
{
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(5.5, Range<double>(1.0, 10.0)));
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(5.5f, Range<float>(1.0f, 10.0f)));
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange((uint8_t)5, Range<uint8_t>(1, 10)));
EXPECT_NO_THROW(Ensure::Always::ArgumentInRange(5L, Range<int64_t>(1L, 10L)));

EXPECT_THROW(Ensure::Always::ArgumentInRange(15.5, Range<double>(1.0, 10.0)), std::invalid_argument);
EXPECT_THROW(Ensure::Always::ArgumentInRange(15.5f, Range<float>(1.0f, 10.0f)), std::invalid_argument);
EXPECT_THROW(Ensure::Always::ArgumentInRange((uint8_t)15, Range<uint8_t>(1, 10)), std::invalid_argument);
EXPECT_THROW(Ensure::Always::ArgumentInRange(15L, Range<int64_t>(1L, 10L)), std::invalid_argument);
}

TEST(EnsureExtensionsTests, OnDebugMethodsTest)
{
// OnDebug methods should not throw in release builds (with NDEBUG)
// and should behave like Always methods in debug builds (without NDEBUG)
EXPECT_NO_THROW(Ensure::OnDebug::MaximumArgumentIsGreaterOrEqualToMinimum(1, 2));
EXPECT_NO_THROW(Ensure::OnDebug::MaximumArgumentIsGreaterOrEqualToMinimum(1, 2, "testParam"));
EXPECT_NO_THROW(Ensure::OnDebug::MaximumArgumentIsGreaterOrEqualToMinimum(1, 2, "testParam", "Test message"));
EXPECT_NO_THROW(Ensure::OnDebug::MaximumArgumentIsGreaterOrEqualToMinimum(1, 2, "testParam", []() { return std::string("Lambda message"); }));

EXPECT_NO_THROW(Ensure::OnDebug::ArgumentInRange(5, Range<int>(1, 10)));
EXPECT_NO_THROW(Ensure::OnDebug::ArgumentInRange(5, Range<int>(1, 10), "testParam"));
EXPECT_NO_THROW(Ensure::OnDebug::ArgumentInRange(5, Range<int>(1, 10), "testParam", "Test message"));
EXPECT_NO_THROW(Ensure::OnDebug::ArgumentInRange(5, Range<int>(1, 10), "testParam", []() { return std::string("Lambda message"); }));
EXPECT_NO_THROW(Ensure::OnDebug::ArgumentInRange(5, 1, 10));
EXPECT_NO_THROW(Ensure::OnDebug::ArgumentInRange(5, 1, 10, "testParam"));

// In debug builds, these should throw, but in release builds they shouldn't
#ifndef NDEBUG
EXPECT_THROW(Ensure::OnDebug::MaximumArgumentIsGreaterOrEqualToMinimum(2, 1), std::invalid_argument);
EXPECT_THROW(Ensure::OnDebug::ArgumentInRange(15, Range<int>(1, 10)), std::invalid_argument);
#endif
}
}
112 changes: 112 additions & 0 deletions cpp/Platform.Ranges.Tests/RangeExtensionsTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
namespace Platform::Ranges::Tests
{
TEST(RangeExtensionsTests, DifferenceIntTest)
{
auto range = Range(1, 5);
ASSERT_EQ(4, Difference(range));

auto zeroRange = Range(10, 10);
ASSERT_EQ(0, Difference(zeroRange));

auto negativeRange = Range(-10, -5);
ASSERT_EQ(5, Difference(negativeRange));

auto crossZeroRange = Range(-5, 5);
ASSERT_EQ(10, Difference(crossZeroRange));
}

TEST(RangeExtensionsTests, DifferenceUnsignedTypesTest)
{
auto byteRange = Range<std::uint8_t>(1, 5);
ASSERT_EQ(4, Difference(byteRange));

auto ushortRange = Range<std::uint16_t>(1, 5);
ASSERT_EQ(4, Difference(ushortRange));

auto uintRange = Range<std::uint32_t>(1, 5);
ASSERT_EQ(4U, Difference(uintRange));

auto ulongRange = Range<std::uint64_t>(1, 5);
ASSERT_EQ(4UL, Difference(ulongRange));

// Test with maximum ranges
auto maxByteRange = Range<std::uint8_t>(std::numeric_limits<std::uint8_t>::min(), std::numeric_limits<std::uint8_t>::max());
ASSERT_EQ(255, Difference(maxByteRange));

auto maxUshortRange = Range<std::uint16_t>(std::numeric_limits<std::uint16_t>::min(), std::numeric_limits<std::uint16_t>::max());
ASSERT_EQ(65535, Difference(maxUshortRange));
}

TEST(RangeExtensionsTests, DifferenceSignedTypesTest)
{
auto sbyteRange = Range<std::int8_t>(1, 5);
ASSERT_EQ(4, Difference(sbyteRange));

auto shortRange = Range<std::int16_t>(1, 5);
ASSERT_EQ(4, Difference(shortRange));

auto intRange = Range<std::int32_t>(1, 5);
ASSERT_EQ(4, Difference(intRange));

auto longRange = Range<std::int64_t>(1, 5);
ASSERT_EQ(4L, Difference(longRange));

// Test with negative values
auto negativeSbyteRange = Range<std::int8_t>(-10, -5);
ASSERT_EQ(5, Difference(negativeSbyteRange));

auto negativeShortRange = Range<std::int16_t>(-100, -50);
ASSERT_EQ(50, Difference(negativeShortRange));

auto negativeIntRange = Range<std::int32_t>(-1000, -500);
ASSERT_EQ(500, Difference(negativeIntRange));

auto negativeLongRange = Range<std::int64_t>(-10000L, -5000L);
ASSERT_EQ(5000L, Difference(negativeLongRange));
}

TEST(RangeExtensionsTests, DifferenceFloatingPointTest)
{
auto floatRange = Range<float>(1.0f, 5.0f);
ASSERT_FLOAT_EQ(4.0f, Difference(floatRange));

auto doubleRange = Range<double>(1.0, 5.0);
ASSERT_DOUBLE_EQ(4.0, Difference(doubleRange));

auto zeroFloatRange = Range<float>(10.5f, 10.5f);
ASSERT_FLOAT_EQ(0.0f, Difference(zeroFloatRange));

auto zeroDoubleRange = Range<double>(10.5, 10.5);
ASSERT_DOUBLE_EQ(0.0, Difference(zeroDoubleRange));

auto negativeFloatRange = Range<float>(-10.5f, -5.5f);
ASSERT_FLOAT_EQ(5.0f, Difference(negativeFloatRange));

auto negativeDoubleRange = Range<double>(-10.5, -5.5);
ASSERT_DOUBLE_EQ(5.0, Difference(negativeDoubleRange));

auto decimalFloatRange = Range<float>(1.25f, 3.75f);
ASSERT_FLOAT_EQ(2.5f, Difference(decimalFloatRange));

auto decimalDoubleRange = Range<double>(1.25, 3.75);
ASSERT_DOUBLE_EQ(2.5, Difference(decimalDoubleRange));
}

TEST(RangeExtensionsTests, DifferenceEdgeCasesTest)
{
// Zero-width ranges
auto zeroIntRange = Range(42, 42);
ASSERT_EQ(0, Difference(zeroIntRange));

auto zeroFloatRange = Range(3.14f, 3.14f);
ASSERT_FLOAT_EQ(0.0f, Difference(zeroFloatRange));

auto zeroDoubleRange = Range(2.718, 2.718);
ASSERT_DOUBLE_EQ(0.0, Difference(zeroDoubleRange));

// Large ranges
auto largeIntRange = Range(std::numeric_limits<int>::min() / 2, std::numeric_limits<int>::max() / 2);
auto expectedDiff = static_cast<long long>(std::numeric_limits<int>::max() / 2) - static_cast<long long>(std::numeric_limits<int>::min() / 2);
ASSERT_EQ(expectedDiff, Difference(largeIntRange));
}
}
Loading
Loading