Skip to content

Commit dfc29ad

Browse files
committed
fieldvec: add a bunch of unit tests
1 parent 0e3d954 commit dfc29ad

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

src/primitives/decode.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,15 @@ mod tests {
12621262
}
12631263
}
12641264

1265+
#[test]
1266+
#[allow(clippy::assertions_on_constants)]
1267+
fn constant_sanity() {
1268+
assert!(
1269+
crate::primitives::correction::NO_ALLOC_MAX_LENGTH > 6,
1270+
"The NO_ALLOC_MAX_LENGTH constant must be > 6. See its documentation for why.",
1271+
);
1272+
}
1273+
12651274
macro_rules! check_invalid_segwit_addresses {
12661275
($($test_name:ident, $reason:literal, $address:literal);* $(;)?) => {
12671276
$(

src/primitives/fieldvec.rs

+122
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,125 @@ impl<F> ops::IndexMut<ops::RangeFull> for FieldVec<F> {
434434
&mut self.inner_a[..self.len][index]
435435
}
436436
}
437+
438+
#[cfg(test)]
439+
mod tests {
440+
use super::*;
441+
use crate::{Fe1024, Fe32};
442+
443+
#[test]
444+
fn push_pop() {
445+
let mut x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
446+
let x_1: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH - 1).collect();
447+
448+
assert_eq!(x.len(), NO_ALLOC_MAX_LENGTH);
449+
assert!(!x.is_empty());
450+
451+
assert_eq!(x.pop(), Some(NO_ALLOC_MAX_LENGTH - 1));
452+
assert_eq!(x, x_1);
453+
x.push(NO_ALLOC_MAX_LENGTH - 1);
454+
455+
let mut y: FieldVec<_> = None.into_iter().collect();
456+
for i in 0..NO_ALLOC_MAX_LENGTH {
457+
y.push(i);
458+
assert_eq!(y[i], i);
459+
y[i] = i + 1;
460+
assert_eq!(y[i], i + 1);
461+
y[i] -= 1;
462+
}
463+
assert_eq!(x, y);
464+
465+
for i in (0..NO_ALLOC_MAX_LENGTH).rev() {
466+
assert_eq!(y.pop(), Some(i));
467+
}
468+
assert_eq!(y.len(), 0);
469+
assert!(y.is_empty());
470+
}
471+
472+
#[test]
473+
fn iter_slice() {
474+
let mut x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
475+
assert!(x.iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
476+
assert!(x[..].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
477+
assert!(x[0..].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
478+
assert!(x[..NO_ALLOC_MAX_LENGTH].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
479+
assert!(x[1..].iter().copied().eq(1..NO_ALLOC_MAX_LENGTH));
480+
assert!(x[..NO_ALLOC_MAX_LENGTH - 1].iter().copied().eq(0..NO_ALLOC_MAX_LENGTH - 1));
481+
assert!(x[1..NO_ALLOC_MAX_LENGTH - 1].iter().copied().eq(1..NO_ALLOC_MAX_LENGTH - 1));
482+
483+
// mutable slicing
484+
x[..].reverse();
485+
assert!(x.iter().copied().eq((0..NO_ALLOC_MAX_LENGTH).rev()));
486+
x[..NO_ALLOC_MAX_LENGTH].reverse();
487+
assert!(x.iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
488+
x[0..].reverse();
489+
assert!(x.iter().copied().eq((0..NO_ALLOC_MAX_LENGTH).rev()));
490+
x[0..NO_ALLOC_MAX_LENGTH].reverse();
491+
assert!(x.iter().copied().eq(0..NO_ALLOC_MAX_LENGTH));
492+
493+
for elem in x.iter_mut() {
494+
*elem += 1;
495+
}
496+
assert!(x.iter().copied().eq(1..NO_ALLOC_MAX_LENGTH + 1));
497+
}
498+
499+
#[test]
500+
fn field_ops() {
501+
let qs: FieldVec<_> = FieldVec::from_powers(Fe32::Q, NO_ALLOC_MAX_LENGTH - 1);
502+
let ps: FieldVec<_> = FieldVec::from_powers(Fe32::P, NO_ALLOC_MAX_LENGTH - 1);
503+
let pzr: FieldVec<_> = FieldVec::from_powers(Fe32::Z, 3);
504+
505+
assert_eq!(qs.len(), NO_ALLOC_MAX_LENGTH);
506+
assert_eq!(ps.len(), NO_ALLOC_MAX_LENGTH);
507+
assert_eq!(pzr.len(), 4);
508+
509+
let pzr = pzr.lift::<Fe32>(); // should work and be a no-op
510+
511+
// This is somewhat weird behavior but mathematically reasonable. The
512+
// `from_powers` constructor shouldn't ever be called with 0 as a base.
513+
// If you need a particular different output from this call, feel free
514+
// to change this test....but think twice about what you're doing.
515+
assert!(qs.iter().copied().eq(Some(Fe32::P)
516+
.into_iter()
517+
.chain(iter::repeat(Fe32::Q).take(NO_ALLOC_MAX_LENGTH - 1))));
518+
// These checks though are correct and unambiguous.
519+
assert!(ps.iter().copied().eq(iter::repeat(Fe32::P).take(NO_ALLOC_MAX_LENGTH)));
520+
assert_eq!(pzr.iter().copied().collect::<Vec<_>>(), [Fe32::P, Fe32::Z, Fe32::Y, Fe32::G,]);
521+
522+
let pow2 = pzr.clone().mul_pointwise(&pzr);
523+
assert_eq!(pow2.iter().copied().collect::<Vec<_>>(), [Fe32::P, Fe32::Y, Fe32::S, Fe32::J,]);
524+
525+
let lifted = pzr.lift::<Fe1024>();
526+
assert_eq!(
527+
lifted.iter().copied().collect::<Vec<_>>(),
528+
[
529+
Fe1024::from(Fe32::P),
530+
Fe1024::from(Fe32::Z),
531+
Fe1024::from(Fe32::Y),
532+
Fe1024::from(Fe32::G),
533+
]
534+
);
535+
}
536+
537+
#[test]
538+
fn construct_too_far() {
539+
let x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH + 1).collect();
540+
let y: FieldVec<_> = FieldVec::from_powers(Fe32::Q, NO_ALLOC_MAX_LENGTH);
541+
assert_eq!(x.len(), NO_ALLOC_MAX_LENGTH + 1);
542+
assert_eq!(y.len(), NO_ALLOC_MAX_LENGTH + 1);
543+
}
544+
545+
#[test]
546+
#[cfg_attr(not(feature = "alloc"), should_panic)]
547+
fn access_too_far() {
548+
let x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH + 1).collect();
549+
let _ = x[0];
550+
}
551+
552+
#[test]
553+
#[cfg_attr(not(feature = "alloc"), should_panic)]
554+
fn push_too_far() {
555+
let mut x: FieldVec<_> = (0..NO_ALLOC_MAX_LENGTH).collect();
556+
x.push(100);
557+
}
558+
}

0 commit comments

Comments
 (0)