Skip to content

Commit 27be22c

Browse files
bitzoicK1-R1
andauthored
Add inline tests for all arithmetic cases in u8, u16, u32, u64, U128, and u256 (#6995)
## Description This PR adds arithmetic test cases to ensure `u8`, `u16`, `u32`, `u64`, `U128`, and `u256` behave as expected in normal conditions, when overflow is disabled, when unsafe math is enabled, and edge cases. Previously, the modulo and square root functions of `U128` would not revert, even if unsafe math is enabled. The following test cases are new for inline tests: ### `u8` - Add - Revert Add on overflow - Revert on unsafe math on overflow - Binary log of zero fails on overflow disabled - Binary log of zero returns zero on unsafe math - Divide - Divide behavior on unsafe math - Divide by zero reverts - Log still reverts when overflow enabled - Log behavior on unsafe math enabled - Log parity with Rust tests - Modulo zero still reverts with overflow enabled - Multiply - Multiply overflow still reverts on unsafe math enabled - Pow still reverts on unsafe math enabled - Root behavior the same on overflow enabled - Root behavior the same on unsafe math enabled - 0th root will fail - Subtract - Subtract underflow still reverts with unsafe math enabled ### `u16` - Add - Revert Add on overflow - Revert on unsafe math on overflow - Binary log of zero fails on overflow disabled - Binary log of zero returns zero on unsafe math - Divide - Divide behavior on unsafe math - Divide by zero reverts - Log still reverts when overflow enabled - Log behavior on unsafe math enabled - Log parity with Rust tests - Modulo zero still reverts with overflow enabled - Multiply - Multiply overflow still reverts on unsafe math enabled - Pow still reverts on unsafe math enabled - Root behavior the same on overflow enabled - Root behavior the same on unsafe math enabled - 0th root will fail - Subtract - Subtract underflow still reverts with unsafe math enabled ### `u32` - Add - Revert Add on overflow - Revert on unsafe math on overflow - Binary log of zero fails on overflow disabled - Binary log of zero returns zero on unsafe math - Divide - Divide behavior on unsafe math - Divide by zero reverts - Log still reverts when overflow enabled - Log behavior on unsafe math enabled - Log parity with Rust tests - Modulo zero still reverts with overflow enabled - Multiply - Multiply overflow still reverts on unsafe math enabled - Pow still reverts on unsafe math enabled - Root behavior the same on overflow enabled - Root behavior the same on unsafe math enabled - 0th root will fail - Subtract - Subtract underflow still reverts with unsafe math enabled ### `u64` - Add - Revert Add on overflow - Revert on unsafe math on overflow - Binary log of zero fails on overflow disabled - Binary log of zero returns zero on unsafe math - Divide - Divide behavior on unsafe math - Divide by zero reverts - Log still reverts when overflow enabled - Log behavior on unsafe math enabled - Log parity with Rust tests - Modulo zero still reverts with overflow enabled - Multiply - Multiply overflow still reverts on unsafe math enabled - Pow still reverts on unsafe math enabled - Root behavior the same on overflow enabled - Root behavior the same on unsafe math enabled - 0th root will fail - Subtract - Subtract underflow still reverts with unsafe math enabled ### `U128` - Revert Add on overflow - Revert on unsafe math on overflow - Binary log of zero fails on overflow disabled - Binary log of zero returns zero on unsafe math - Divide behavior on unsafe math - Log still reverts when overflow enabled - Log behavior on unsafe math enabled - Log parity with Rust tests - Modulo zero still reverts with overflow enabled - Multiply overflow still reverts on unsafe math enabled - Pow still reverts on unsafe math enabled - Root behavior the same on overflow enabled - Root behavior the same on unsafe math enabled - Subtract underflow still reverts with unsafe math enabled ### `u256` - Add - Revert Add on overflow - Revert on unsafe math on overflow - Binary log of zero fails on overflow disabled - Binary log of zero returns zero on unsafe math - Divide - Divide behavior on unsafe math - Divide by zero reverts - Log still reverts when overflow enabled - Log behavior on unsafe math enabled - Log parity with Rust tests - Modulo zero still reverts with overflow enabled - Multiply - Multiply overflow still reverts on unsafe math enabled - Pow still reverts on unsafe math enabled - Root behavior the same on overflow enabled - Root behavior the same on unsafe math enabled - Subtract - Subtract underflow still reverts with unsafe math enabled ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [x] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: K1-R1 <77465250+K1-R1@users.noreply.github.com>
1 parent d46f08a commit 27be22c

File tree

12 files changed

+3849
-1222
lines changed

12 files changed

+3849
-1222
lines changed

sway-lib-std/src/u128.sw

+7-1
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,9 @@ impl core::ops::Divide for U128 {
701701

702702
impl core::ops::Mod for U128 {
703703
fn modulo(self, other: Self) -> Self {
704-
assert(other != Self::zero());
704+
if panic_on_unsafe_math_enabled() {
705+
assert(other != Self::zero());
706+
}
705707

706708
// a mod b = a - b * (a / b)
707709
let quotient = self / other;
@@ -801,6 +803,10 @@ impl Root for U128 {
801803
/// Integer square root using [Newton's Method](https://en.wikipedia.org/wiki/Integer_square_root#Algorithm_using_Newton's_method).
802804
fn sqrt(self) -> Self {
803805
let zero = Self::from((0, 0));
806+
if panic_on_unsafe_math_enabled() {
807+
assert(self != zero);
808+
}
809+
804810
let mut x0 = self >> 1;
805811
let mut s = self;
806812

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
library;
2+
3+
use std::flags::{disable_panic_on_overflow, disable_panic_on_unsafe_math};
4+
5+
#[test]
6+
fn math_u8_add() {
7+
let zero = u8::zero();
8+
let one = 1u8;
9+
let two = 2u8;
10+
let max = u8::max();
11+
let half = u8::max() / 2;
12+
13+
assert(zero + zero == zero);
14+
assert(zero + one == one);
15+
assert(one + zero == one);
16+
assert(one + one == two);
17+
assert(half + half + one == max);
18+
}
19+
20+
#[test]
21+
fn math_u8_overflow_add() {
22+
let _ = disable_panic_on_overflow();
23+
24+
let a = u8::max();
25+
let b = a + 1;
26+
27+
require(b == 0_u8, b);
28+
29+
let c = a + 2;
30+
31+
require(c == 1_u8, c);
32+
33+
let d = a + u8::max();
34+
35+
require(d == u8::max() - 1, d);
36+
37+
let e = a + (u8::max() - 1);
38+
39+
require(e == u8::max() - 2, e);
40+
}
41+
42+
#[test(should_revert)]
43+
fn revert_math_u8_overflow_add() {
44+
let a = u8::max();
45+
let b = a + 1;
46+
log(b);
47+
}
48+
49+
#[test(should_revert)]
50+
fn revert_math_u8_add_unsafe_math() {
51+
let _ = disable_panic_on_unsafe_math();
52+
let a = u8::max();
53+
let b = a + 1;
54+
log(b);
55+
}
56+
57+
#[test]
58+
fn math_u16_add() {
59+
let zero = u16::zero();
60+
let one = 1u16;
61+
let two = 2u16;
62+
let max = u16::max();
63+
let half = u16::max() / 2;
64+
65+
assert(zero + zero == zero);
66+
assert(zero + one == one);
67+
assert(one + zero == one);
68+
assert(one + one == two);
69+
assert(half + half + one == max);
70+
}
71+
72+
#[test]
73+
fn math_u16_overflow_add() {
74+
let _ = disable_panic_on_overflow();
75+
76+
let a: u16 = u16::max();
77+
let b: u16 = a + 1;
78+
79+
require(b == 0_u16, b);
80+
81+
let c = a + 2;
82+
83+
require(c == 1_u16, c);
84+
85+
let d = a + u16::max();
86+
87+
require(d == u16::max() - 1, d);
88+
89+
let e = a + (u16::max() - 1);
90+
91+
require(e == u16::max() - 2, e);
92+
}
93+
94+
#[test(should_revert)]
95+
fn revert_math_u16_overflow_add() {
96+
let a = u16::max();
97+
let b = a + 1;
98+
log(b);
99+
}
100+
101+
#[test(should_revert)]
102+
fn revert_math_u16_add_unsafe_math() {
103+
let _ = disable_panic_on_unsafe_math();
104+
let a = u16::max();
105+
let b = a + 1;
106+
log(b);
107+
}
108+
109+
#[test]
110+
fn math_u32_add() {
111+
let zero = u32::zero();
112+
let one = 1u32;
113+
let two = 2u32;
114+
let max = u32::max();
115+
let half = u32::max() / 2;
116+
117+
assert(zero + zero == zero);
118+
assert(zero + one == one);
119+
assert(one + zero == one);
120+
assert(one + one == two);
121+
assert(half + half + one == max);
122+
}
123+
124+
#[test]
125+
fn math_u32_overflow_add() {
126+
let _ = disable_panic_on_overflow();
127+
128+
let a = u32::max();
129+
let b = a + 1;
130+
131+
require(b == 0_u32, b);
132+
133+
let c = a + 2;
134+
135+
require(c == 1_u32, c);
136+
137+
let d = a + u32::max();
138+
139+
require(d == u32::max() - 1, d);
140+
141+
let e = a + (u32::max() - 1);
142+
143+
require(e == u32::max() - 2, e);
144+
}
145+
146+
#[test(should_revert)]
147+
fn revert_math_u32_overflow_add() {
148+
let a = u32::max();
149+
let b = a + 1;
150+
log(b);
151+
}
152+
153+
#[test(should_revert)]
154+
fn revert_math_u32_add_unsafe_math() {
155+
let _ = disable_panic_on_unsafe_math();
156+
let a = u32::max();
157+
let b = a + 1;
158+
log(b);
159+
}
160+
161+
#[test]
162+
fn math_u64_add() {
163+
let zero = u64::zero();
164+
let one = 1u64;
165+
let two = 2u64;
166+
let max = u64::max();
167+
let half = u64::max() / 2;
168+
169+
assert(zero + zero == zero);
170+
assert(zero + one == one);
171+
assert(one + zero == one);
172+
assert(one + one == two);
173+
assert(half + half + one == max);
174+
}
175+
176+
#[test]
177+
fn math_u64_overflow_add() {
178+
let _ = disable_panic_on_overflow();
179+
180+
let a = u64::max();
181+
let b = a + 1;
182+
183+
require(b == 0_u64, b);
184+
185+
let c = a + 2;
186+
187+
require(c == 1_u64, c);
188+
189+
let d = a + u64::max();
190+
191+
require(d == u64::max() - 1, d);
192+
193+
let e = a + (u64::max() - 1);
194+
195+
require(e == u64::max() - 2, e);
196+
}
197+
198+
#[test(should_revert)]
199+
fn revert_math_u64_overflow_add() {
200+
let a = u64::max();
201+
let b = a + 1;
202+
log(b);
203+
}
204+
205+
#[test(should_revert)]
206+
fn revert_math_u64_add_unsafe_math() {
207+
let _ = disable_panic_on_unsafe_math();
208+
let a = u64::max();
209+
let b = a + 1;
210+
log(b);
211+
}
212+
213+
#[test]
214+
fn math_u256_add() {
215+
let zero = u256::zero();
216+
let one = 0x01u256;
217+
let two = 0x02u256;
218+
let max = u256::max();
219+
let half = u256::max() / 2;
220+
221+
assert(zero + zero == zero);
222+
assert(zero + one == one);
223+
assert(one + zero == one);
224+
assert(one + one == two);
225+
assert(half + half + one == max);
226+
}
227+
228+
#[test]
229+
fn math_u256_overflow_add() {
230+
let _ = disable_panic_on_overflow();
231+
232+
let a = u256::max();
233+
let b = a + 1;
234+
235+
require(b == u256::zero(), b);
236+
237+
let c = a + 2;
238+
239+
require(c == 1, c);
240+
241+
let d = a + u256::max();
242+
243+
require(d == u256::max() - 1, d);
244+
245+
let e = a + (u256::max() - 1);
246+
247+
require(e == u256::max() - 2, e);
248+
}
249+
250+
#[test(should_revert)]
251+
fn revert_math_u256_overflow_add() {
252+
let a = u256::max();
253+
let b = a + 1;
254+
log(b);
255+
}
256+
257+
#[test(should_revert)]
258+
fn revert_math_u256_add_unsafe_math() {
259+
let a = u256::max();
260+
let b = a + 1;
261+
log(b);
262+
}

0 commit comments

Comments
 (0)