Skip to content

Commit f212907

Browse files
committed
test(target_chains/starknet): add byte array tests
1 parent ef92222 commit f212907

File tree

2 files changed

+148
-2
lines changed

2 files changed

+148
-2
lines changed

target_chains/starknet/contracts/src/byte_array.cairo

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use core::array::ArrayTrait;
12
use core::fmt::{Debug, Formatter};
3+
use super::util::one_shift_left_bytes_u256;
24

35
/// A byte array with storage format similar to `core::ByteArray`, but
46
/// suitable for reading data from it.
@@ -35,8 +37,13 @@ pub impl ByteArrayImpl of ByteArrayTrait {
3537
if data.len() == 0 {
3638
assert!(num_last_bytes == 0);
3739
} else {
40+
assert!(num_last_bytes > 0);
3841
assert!(num_last_bytes <= 31);
39-
// TODO: check that unused bytes are zeroed.
42+
let last: u256 = (*data.at(data.len() - 1)).into();
43+
assert!(
44+
last / one_shift_left_bytes_u256(num_last_bytes) == 0,
45+
"ByteArrayImpl::new: last value is too large"
46+
);
4047
}
4148
ByteArray { num_last_bytes, data }
4249
}
@@ -62,3 +69,100 @@ pub impl ByteArrayImpl of ByteArrayTrait {
6269
}
6370
}
6471
}
72+
73+
#[cfg(test)]
74+
mod tests {
75+
use super::{ByteArray, ByteArrayImpl};
76+
use pyth::util::array_felt252_to_bytes31;
77+
78+
#[test]
79+
fn empty_byte_array() {
80+
let mut array = ByteArrayImpl::new(array![], 0);
81+
assert!(array.len() == 0);
82+
assert!(array.pop_front() == Option::None);
83+
}
84+
85+
#[test]
86+
fn byte_array_3_zeros() {
87+
let mut array = ByteArrayImpl::new(array_felt252_to_bytes31(array![0]), 3);
88+
assert!(array.len() == 3);
89+
assert!(array.pop_front() == Option::Some((0.try_into().unwrap(), 3)));
90+
assert!(array.len() == 0);
91+
assert!(array.pop_front() == Option::None);
92+
}
93+
94+
#[test]
95+
fn byte_array_3_bytes() {
96+
let mut array = ByteArrayImpl::new(array_felt252_to_bytes31(array![0x010203]), 3);
97+
assert!(array.len() == 3);
98+
assert!(array.pop_front() == Option::Some((0x010203.try_into().unwrap(), 3)));
99+
assert!(array.len() == 0);
100+
assert!(array.pop_front() == Option::None);
101+
}
102+
103+
#[test]
104+
fn byte_array_single_full() {
105+
let value_31_bytes = 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
106+
let mut array = ByteArrayImpl::new(array_felt252_to_bytes31(array![value_31_bytes]), 31);
107+
assert!(array.len() == 31);
108+
assert!(array.pop_front() == Option::Some((value_31_bytes.try_into().unwrap(), 31)));
109+
assert!(array.len() == 0);
110+
assert!(array.pop_front() == Option::None);
111+
}
112+
113+
#[test]
114+
fn byte_array_two_full() {
115+
let value_31_bytes = 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
116+
let value2_31_bytes = 0x2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f;
117+
let mut array = ByteArrayImpl::new(
118+
array_felt252_to_bytes31(array![value_31_bytes, value2_31_bytes]), 31
119+
);
120+
assert!(array.len() == 62);
121+
assert!(array.pop_front() == Option::Some((value_31_bytes.try_into().unwrap(), 31)));
122+
assert!(array.len() == 31);
123+
assert!(array.pop_front() == Option::Some((value2_31_bytes.try_into().unwrap(), 31)));
124+
assert!(array.len() == 0);
125+
assert!(array.pop_front() == Option::None);
126+
}
127+
128+
#[test]
129+
fn byte_array_3_items() {
130+
let value_31_bytes = 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
131+
let value2_31_bytes = 0x2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f;
132+
let value3_5_bytes = 0x4142434445;
133+
let mut array = ByteArrayImpl::new(
134+
array_felt252_to_bytes31(array![value_31_bytes, value2_31_bytes, value3_5_bytes]), 5
135+
);
136+
assert!(array.len() == 67);
137+
assert!(array.pop_front() == Option::Some((value_31_bytes.try_into().unwrap(), 31)));
138+
assert!(array.len() == 36);
139+
assert!(array.pop_front() == Option::Some((value2_31_bytes.try_into().unwrap(), 31)));
140+
assert!(array.len() == 5);
141+
assert!(array.pop_front() == Option::Some((value3_5_bytes.try_into().unwrap(), 5)));
142+
assert!(array.pop_front() == Option::None);
143+
}
144+
145+
#[test]
146+
#[should_panic]
147+
fn byte_array_empty_invalid() {
148+
ByteArrayImpl::new(array![], 5);
149+
}
150+
151+
#[test]
152+
#[should_panic]
153+
fn byte_array_last_too_large() {
154+
ByteArrayImpl::new(array_felt252_to_bytes31(array![1, 2, 3]), 35);
155+
}
156+
157+
#[test]
158+
#[should_panic]
159+
fn byte_array_last_zero_invalid() {
160+
ByteArrayImpl::new(array_felt252_to_bytes31(array![1, 2, 0]), 0);
161+
}
162+
163+
#[test]
164+
#[should_panic]
165+
fn byte_array_last_too_many_bytes() {
166+
ByteArrayImpl::new(array_felt252_to_bytes31(array![1, 2, 0x010203]), 2);
167+
}
168+
}

target_chains/starknet/contracts/src/util.cairo

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,49 @@ pub const ONE_SHIFT_64: u128 = 0x10000000000000000;
88
pub const UNEXPECTED_OVERFLOW: felt252 = 'unexpected overflow';
99
pub const UNEXPECTED_ZERO: felt252 = 'unexpected zero';
1010

11-
// Returns 1 << (8 * `n_bytes`) as u128, where `n_bytes` must be < BYTES_IN_U128.
11+
// Returns 1 << (8 * `n_bytes`) as u256.
12+
//
13+
// Panics if `n_bytes >= 32`.
14+
pub fn one_shift_left_bytes_u256(n_bytes: u8) -> u256 {
15+
match n_bytes {
16+
0 => 0x1,
17+
1 => 0x100,
18+
2 => 0x10000,
19+
3 => 0x1000000,
20+
4 => 0x100000000,
21+
5 => 0x10000000000,
22+
6 => 0x1000000000000,
23+
7 => 0x100000000000000,
24+
8 => 0x10000000000000000,
25+
9 => 0x1000000000000000000,
26+
10 => 0x100000000000000000000,
27+
11 => 0x10000000000000000000000,
28+
12 => 0x1000000000000000000000000,
29+
13 => 0x100000000000000000000000000,
30+
14 => 0x10000000000000000000000000000,
31+
15 => 0x1000000000000000000000000000000,
32+
16 => 0x100000000000000000000000000000000,
33+
17 => 0x10000000000000000000000000000000000,
34+
18 => 0x1000000000000000000000000000000000000,
35+
19 => 0x100000000000000000000000000000000000000,
36+
20 => 0x10000000000000000000000000000000000000000,
37+
21 => 0x1000000000000000000000000000000000000000000,
38+
22 => 0x100000000000000000000000000000000000000000000,
39+
23 => 0x10000000000000000000000000000000000000000000000,
40+
24 => 0x1000000000000000000000000000000000000000000000000,
41+
25 => 0x100000000000000000000000000000000000000000000000000,
42+
26 => 0x10000000000000000000000000000000000000000000000000000,
43+
27 => 0x1000000000000000000000000000000000000000000000000000000,
44+
28 => 0x100000000000000000000000000000000000000000000000000000000,
45+
29 => 0x10000000000000000000000000000000000000000000000000000000000,
46+
30 => 0x1000000000000000000000000000000000000000000000000000000000000,
47+
31 => 0x100000000000000000000000000000000000000000000000000000000000000,
48+
_ => core::panic_with_felt252('n_bytes too big'),
49+
}
50+
}
51+
52+
53+
// Returns 1 << (8 * `n_bytes`) as u128.
1254
//
1355
// Panics if `n_bytes >= 16`.
1456
pub fn one_shift_left_bytes_u128(n_bytes: u8) -> u128 {

0 commit comments

Comments
 (0)