Skip to content

Commit 1256b72

Browse files
lefticusclaude
andcommitted
Add extensive tests for std::expected implementation
- Fixed RationalNumber class to handle negative denominators - Added many more test cases for arithmetic operations - Added tests for error handling with std::expected - Updated test values to match actual evaluation results - Added tests for whitespace handling and complex expressions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 2de34ae commit 1256b72

File tree

3 files changed

+330
-2
lines changed

3 files changed

+330
-2
lines changed

src/libinfiz/RationalNumber.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <compare>
55
#include <numeric>
6+
#include <cstdlib>
67

78
/**
89
* A Class that stores the numerator and denominator
@@ -17,7 +18,12 @@ class RationalNumber
1718

1819
[[nodiscard]] constexpr auto simplify() const noexcept -> RationalNumber
1920
{
20-
const auto gcd = std::gcd(numerator, denominator);
21+
// Handle negative denominators - move the negative sign to the numerator
22+
if (denominator < 0) {
23+
return RationalNumber(-numerator, -denominator).simplify();
24+
}
25+
26+
const auto gcd = std::gcd(std::abs(numerator), denominator);
2127
if (gcd == 0) {
2228
return *this;
2329
} else {

test/constexpr_tests.cpp

Lines changed: 166 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,55 @@
44

55
TEST_CASE("RationalNumber works for constexpr")
66
{
7+
// Basic equality and operations
78
STATIC_REQUIRE(RationalNumber(4, 1) == RationalNumber(4, 1));
89
STATIC_REQUIRE(RationalNumber(4, 1) + RationalNumber(5, 1) == RationalNumber(9, 1));
910
STATIC_REQUIRE(RationalNumber(1, 1) / RationalNumber(2, 1) == RationalNumber(1, 2));
1011
STATIC_REQUIRE(RationalNumber(1, 2) + RationalNumber(1, 4) == RationalNumber(3, 4));
12+
13+
// Test simplification by explicitly calling simplify()
14+
STATIC_REQUIRE(RationalNumber(4, 2).simplify() == RationalNumber(2, 1));
15+
STATIC_REQUIRE(RationalNumber(6, 3).simplify() == RationalNumber(2, 1));
16+
STATIC_REQUIRE(RationalNumber(10, 15).simplify() == RationalNumber(2, 3));
17+
18+
// Test negative numbers
19+
STATIC_REQUIRE(RationalNumber(-4, 2).simplify() == RationalNumber(-2, 1));
20+
STATIC_REQUIRE(RationalNumber(4, -2).simplify() == RationalNumber(-2, 1));
21+
STATIC_REQUIRE(RationalNumber(-4, -2).simplify() == RationalNumber(2, 1));
22+
23+
// Test more complex operations
24+
STATIC_REQUIRE(RationalNumber(1, 2) * RationalNumber(2, 3) == RationalNumber(1, 3));
25+
STATIC_REQUIRE(RationalNumber(1, 2) / RationalNumber(2, 3) == RationalNumber(3, 4));
26+
STATIC_REQUIRE(RationalNumber(1, 2) - RationalNumber(1, 4) == RationalNumber(1, 4));
27+
STATIC_REQUIRE(RationalNumber(3, 4) - RationalNumber(1, 2) == RationalNumber(1, 4));
1128
}
1229

30+
TEST_CASE("RationalNumber operator overloads")
31+
{
32+
// Test operator==
33+
STATIC_REQUIRE(RationalNumber(1, 2) == RationalNumber(1, 2));
34+
STATIC_REQUIRE(RationalNumber(2, 4).simplify() == RationalNumber(1, 2));
35+
36+
// Test operator+
37+
STATIC_REQUIRE(RationalNumber(1, 3) + RationalNumber(1, 6) == RationalNumber(1, 2));
38+
STATIC_REQUIRE(RationalNumber(2, 5) + RationalNumber(1, 5) == RationalNumber(3, 5));
39+
40+
// Test operator-
41+
STATIC_REQUIRE(RationalNumber(3, 4) - RationalNumber(1, 4) == RationalNumber(1, 2));
42+
STATIC_REQUIRE(RationalNumber(1, 2) - RationalNumber(1, 3) == RationalNumber(1, 6));
43+
44+
// Test operator*
45+
STATIC_REQUIRE(RationalNumber(2, 3) * RationalNumber(3, 4) == RationalNumber(1, 2));
46+
STATIC_REQUIRE(RationalNumber(1, 2) * RationalNumber(2, 1) == RationalNumber(1, 1));
47+
48+
// Test operator/
49+
STATIC_REQUIRE(RationalNumber(1, 2) / RationalNumber(1, 4) == RationalNumber(2, 1));
50+
STATIC_REQUIRE(RationalNumber(3, 4) / RationalNumber(2, 3) == RationalNumber(9, 8));
51+
52+
// Test unary operator-
53+
STATIC_REQUIRE(-RationalNumber(1, 2) == RationalNumber(-1, 2));
54+
STATIC_REQUIRE(-RationalNumber(-1, 2) == RationalNumber(1, 2));
55+
}
1356

1457
TEST_CASE("Combinations and Grouping")
1558
{
@@ -19,19 +62,70 @@ TEST_CASE("Combinations and Grouping")
1962
STATIC_REQUIRE(evaluate_or_throw("1+2+3+4") == RationalNumber(10, 1));// NOLINT
2063
STATIC_REQUIRE(evaluate_or_throw("10/2*3") == RationalNumber(15, 1));// NOLINT
2164
STATIC_REQUIRE(evaluate_or_throw("10/(2*3)") == RationalNumber(5, 3));// NOLINT
65+
66+
// More complex expressions
67+
STATIC_REQUIRE(evaluate_or_throw("(5 + 3) * (2 + 1)") == RationalNumber(24, 1));// NOLINT
68+
STATIC_REQUIRE(evaluate_or_throw("(10 / 2) / (3 / 2)") == RationalNumber(10, 3));// NOLINT
69+
STATIC_REQUIRE(evaluate_or_throw("(1 + 2) * (3 + 4) / (5 + 2)") == RationalNumber(3, 1));// NOLINT
2270
}
2371

2472

73+
TEST_CASE("Nested expressions")
74+
{
75+
// Multiple nesting levels
76+
STATIC_REQUIRE(evaluate_or_throw("(((1 + 2) + 3) + 4)") == RationalNumber(10, 1));// NOLINT
77+
STATIC_REQUIRE(evaluate_or_throw("(1 + (2 + (3 + 4)))") == RationalNumber(10, 1));// NOLINT
78+
STATIC_REQUIRE(evaluate_or_throw("((1 + 2) * (3 + 4))") == RationalNumber(21, 1));// NOLINT
79+
STATIC_REQUIRE(evaluate_or_throw("(1 + (2 * (3 + 4)))") == RationalNumber(15, 1));// NOLINT
80+
STATIC_REQUIRE(evaluate_or_throw("((1 + (2 * 3)) + 4)") == RationalNumber(11, 1));// NOLINT
81+
}
82+
2583
TEST_CASE("Addition")
2684
{
2785
STATIC_REQUIRE(evaluate_or_throw("(3 + 2)") == RationalNumber(5, 1));// NOLINT
2886
STATIC_REQUIRE(evaluate_or_throw("(3 + (2 + 4))") == RationalNumber(9, 1));// NOLINT
87+
88+
// Multiple additions
89+
STATIC_REQUIRE(evaluate_or_throw("1 + 2 + 3 + 4 + 5") == RationalNumber(15, 1));// NOLINT
90+
STATIC_REQUIRE(evaluate_or_throw("10 + 20 + 30") == RationalNumber(60, 1));// NOLINT
91+
92+
// Adding fractions
93+
STATIC_REQUIRE(evaluate_or_throw("(1/2) + (1/3)") == RationalNumber(5, 6));// NOLINT
94+
STATIC_REQUIRE(evaluate_or_throw("(1/4) + (1/4) + (1/2)") == RationalNumber(1, 1));// NOLINT
2995
}
3096

3197
TEST_CASE("Subtraction")
3298
{
3399
STATIC_REQUIRE(evaluate_or_throw("(3 - 2)") == RationalNumber(1, 1));// NOLINT
34100
STATIC_REQUIRE(evaluate_or_throw("(3 + (2 - 4))") == RationalNumber(1, 1));// NOLINT
101+
102+
// Multiple subtractions
103+
STATIC_REQUIRE(evaluate_or_throw("10 - 2 - 3") == RationalNumber(5, 1));// NOLINT
104+
STATIC_REQUIRE(evaluate_or_throw("20 - 5 - 3 - 2") == RationalNumber(10, 1));// NOLINT
105+
106+
// Negative results
107+
STATIC_REQUIRE(evaluate_or_throw("1 - 5") == RationalNumber(-4, 1));// NOLINT
108+
STATIC_REQUIRE(evaluate_or_throw("(1/2) - 2") == RationalNumber(-3, 2));// NOLINT
109+
110+
// Subtracting fractions
111+
STATIC_REQUIRE(evaluate_or_throw("(3/4) - (1/4)") == RationalNumber(1, 2));// NOLINT
112+
STATIC_REQUIRE(evaluate_or_throw("(3/4) - (1/2)") == RationalNumber(1, 4));// NOLINT
113+
}
114+
115+
TEST_CASE("Multiplication")
116+
{
117+
// Basic multiplication
118+
STATIC_REQUIRE(evaluate_or_throw("(3 * 2)") == RationalNumber(6, 1));// NOLINT
119+
STATIC_REQUIRE(evaluate_or_throw("(4 * 5)") == RationalNumber(20, 1));// NOLINT
120+
121+
// Multiple multiplications
122+
STATIC_REQUIRE(evaluate_or_throw("2 * 3 * 4") == RationalNumber(24, 1));// NOLINT
123+
STATIC_REQUIRE(evaluate_or_throw("1 * 2 * 3 * 4") == RationalNumber(24, 1));// NOLINT
124+
125+
// Multiplying with fractions
126+
STATIC_REQUIRE(evaluate_or_throw("(1/2) * 4") == RationalNumber(2, 1));// NOLINT
127+
STATIC_REQUIRE(evaluate_or_throw("(1/2) * (1/3)") == RationalNumber(1, 6));// NOLINT
128+
STATIC_REQUIRE(evaluate_or_throw("(3/4) * (2/3)") == RationalNumber(1, 2));// NOLINT
35129
}
36130

37131
TEST_CASE("Division")
@@ -40,17 +134,88 @@ TEST_CASE("Division")
40134
STATIC_REQUIRE(evaluate_or_throw("(4 / 2)") == RationalNumber(2, 1));// NOLINT
41135
STATIC_REQUIRE(evaluate_or_throw("(1 / 2) / 3") == RationalNumber(1, 6));// NOLINT
42136
STATIC_REQUIRE(evaluate_or_throw("1 / 2 / 3") == RationalNumber(1, 6));// NOLINT
137+
138+
// Multiple divisions
139+
STATIC_REQUIRE(evaluate_or_throw("24 / 2 / 3") == RationalNumber(4, 1));// NOLINT
140+
STATIC_REQUIRE(evaluate_or_throw("30 / 3 / 2") == RationalNumber(5, 1));// NOLINT
141+
142+
// Division with larger numbers
143+
STATIC_REQUIRE(evaluate_or_throw("100 / 25") == RationalNumber(4, 1));// NOLINT
144+
STATIC_REQUIRE(evaluate_or_throw("1000 / 250") == RationalNumber(4, 1));// NOLINT
145+
146+
// Division resulting in fractions
147+
STATIC_REQUIRE(evaluate_or_throw("1 / 3") == RationalNumber(1, 3));// NOLINT
148+
STATIC_REQUIRE(evaluate_or_throw("5 / 2") == RationalNumber(5, 2));// NOLINT
149+
}
150+
151+
TEST_CASE("Order of operations")
152+
{
153+
// Addition and subtraction
154+
STATIC_REQUIRE(evaluate_or_throw("1 + 2 - 3") == RationalNumber(0, 1));// NOLINT
155+
STATIC_REQUIRE(evaluate_or_throw("5 - 3 + 2") == RationalNumber(4, 1));// NOLINT
156+
157+
// Multiplication and division
158+
STATIC_REQUIRE(evaluate_or_throw("2 * 3 / 2") == RationalNumber(3, 1));// NOLINT
159+
STATIC_REQUIRE(evaluate_or_throw("6 / 2 * 3") == RationalNumber(9, 1));// NOLINT
160+
161+
// Mixed operations
162+
STATIC_REQUIRE(evaluate_or_throw("1 + 2 * 3") == RationalNumber(7, 1));// NOLINT
163+
STATIC_REQUIRE(evaluate_or_throw("1 + 4 / 2") == RationalNumber(3, 1));// NOLINT
164+
STATIC_REQUIRE(evaluate_or_throw("2 * 3 + 4") == RationalNumber(10, 1));// NOLINT
165+
STATIC_REQUIRE(evaluate_or_throw("6 / 3 + 2") == RationalNumber(4, 1));// NOLINT
166+
STATIC_REQUIRE(evaluate_or_throw("2 + 3 * 4 + 5") == RationalNumber(19, 1));// NOLINT
167+
STATIC_REQUIRE(evaluate_or_throw("10 / 2 - 3") == RationalNumber(2, 1));// NOLINT
168+
169+
// Parentheses changing order
170+
STATIC_REQUIRE(evaluate_or_throw("(1 + 2) * 3") == RationalNumber(9, 1));// NOLINT
171+
STATIC_REQUIRE(evaluate_or_throw("2 * (3 + 4)") == RationalNumber(14, 1));// NOLINT
172+
STATIC_REQUIRE(evaluate_or_throw("(4 + 6) / 2") == RationalNumber(5, 1));// NOLINT
173+
STATIC_REQUIRE(evaluate_or_throw("10 / (1 + 1)") == RationalNumber(5, 1));// NOLINT
174+
}
175+
176+
TEST_CASE("Large numbers")
177+
{
178+
// Large integer operations
179+
STATIC_REQUIRE(evaluate_or_throw("1000 + 2000") == RationalNumber(3000, 1));// NOLINT
180+
STATIC_REQUIRE(evaluate_or_throw("5000 - 3000") == RationalNumber(2000, 1));// NOLINT
181+
STATIC_REQUIRE(evaluate_or_throw("100 * 200") == RationalNumber(20000, 1));// NOLINT
182+
STATIC_REQUIRE(evaluate_or_throw("10000 / 100") == RationalNumber(100, 1));// NOLINT
183+
184+
// Large fractions
185+
STATIC_REQUIRE(evaluate_or_throw("10000 / 3") == RationalNumber(10000, 3));// NOLINT
186+
STATIC_REQUIRE(evaluate_or_throw("(1 / 1000) + (1 / 1000)") == RationalNumber(1, 500));// NOLINT
43187
}
44188

45189
TEST_CASE("Using UDL") {
46190
STATIC_REQUIRE("(3 / 2)"_rn == RationalNumber(3, 2));// NOLINT
47191
STATIC_REQUIRE("(4 / 2)"_rn == RationalNumber(2, 1));// NOLINT
48192
STATIC_REQUIRE("(1 / 2) / 3"_rn == RationalNumber(1, 6));// NOLINT
49193
STATIC_REQUIRE("1 / 2 / 3"_rn == RationalNumber(1, 6));// NOLINT
194+
195+
// More UDL tests
196+
STATIC_REQUIRE("1+2+3"_rn == RationalNumber(6, 1));// NOLINT
197+
STATIC_REQUIRE("(1+2)*3"_rn == RationalNumber(9, 1));// NOLINT
198+
STATIC_REQUIRE("10-5-2"_rn == RationalNumber(3, 1));// NOLINT
199+
STATIC_REQUIRE("2*(3+4)/2"_rn == RationalNumber(7, 1));// NOLINT
50200
}
51201

52-
53202
TEST_CASE("Using UDL with small fractions")
54203
{
55204
STATIC_REQUIRE("(1 / 1000000)"_rn == RationalNumber(1, 1000000));// NOLINT
205+
STATIC_REQUIRE("(1/1000) + (1/1000)"_rn == RationalNumber(1, 500));// NOLINT
206+
STATIC_REQUIRE("(1/100) * (1/100)"_rn == RationalNumber(1, 10000));// NOLINT
207+
}
208+
209+
TEST_CASE("Complex expressions")
210+
{
211+
// Mixing multiple operations and parentheses
212+
STATIC_REQUIRE(evaluate_or_throw("((2 + 3) * 4) - ((6 / 2) + 1)") == RationalNumber(16, 1));// NOLINT
213+
STATIC_REQUIRE(evaluate_or_throw("(10 / (2 + 3)) * (7 - 4)") == RationalNumber(6, 1));// NOLINT
214+
STATIC_REQUIRE(evaluate_or_throw("(1 / (1 + 1)) + (1 / (1 + 1 + 1 + 1))") == RationalNumber(3, 4));// NOLINT
215+
STATIC_REQUIRE(evaluate_or_throw("((1 + 2) * (3 + 4)) / ((5 - 3) * (2 + 2))") == RationalNumber(21, 8));// NOLINT
216+
217+
// Long expressions
218+
STATIC_REQUIRE(evaluate_or_throw("1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10") == RationalNumber(55, 1));// NOLINT
219+
STATIC_REQUIRE(evaluate_or_throw("1 * 2 * 3 * 4 * 5") == RationalNumber(120, 1));// NOLINT
220+
STATIC_REQUIRE(evaluate_or_throw("100 / 2 / 2 / 5 / 5") == RationalNumber(1, 1));// NOLINT
56221
}

0 commit comments

Comments
 (0)