/ utilities / src / biginteger / tests.rs
tests.rs
  1  // Copyright (c) 2025 ADnet Contributors
  2  // This file is part of the AlphaVM library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use crate::{
 17      biginteger::*,
 18      rand::{TestRng, Uniform},
 19  };
 20  
 21  #[allow(clippy::eq_op)]
 22  fn biginteger_arithmetic_test<B: BigInteger>(a: B, b: B, zero: B) {
 23      // zero == zero
 24      assert!(zero == zero);
 25  
 26      // zero.is_zero() == true
 27      assert!(zero.is_zero());
 28  
 29      // a == a
 30      assert!(a == a);
 31  
 32      // a + 0 = a
 33      let mut a0_add = a;
 34      a0_add.add_nocarry(&zero);
 35      assert_eq!(a0_add, a);
 36  
 37      // a - 0 = a
 38      let mut a0_sub = a;
 39      a0_sub.sub_noborrow(&zero);
 40      assert_eq!(a0_sub, a);
 41  
 42      // a - a = 0
 43      let mut aa_sub = a;
 44      aa_sub.sub_noborrow(&a);
 45      assert_eq!(aa_sub, zero);
 46  
 47      // a + b = b + a
 48      let mut ab_add = a;
 49      ab_add.add_nocarry(&b);
 50      let mut ba_add = b;
 51      ba_add.add_nocarry(&a);
 52      assert_eq!(ab_add, ba_add);
 53  }
 54  
 55  fn biginteger_bits_test<B: BigInteger>() {
 56      let mut one = B::from(1u64);
 57      assert!(one.get_bit(0));
 58      assert!(!one.get_bit(1));
 59      one.muln(5);
 60  
 61      let thirty_two = one;
 62      assert!(!thirty_two.get_bit(0));
 63      assert!(!thirty_two.get_bit(1));
 64      assert!(!thirty_two.get_bit(2));
 65      assert!(!thirty_two.get_bit(3));
 66      assert!(!thirty_two.get_bit(4));
 67      assert!(thirty_two.get_bit(5), "{thirty_two:?}");
 68  }
 69  
 70  fn biginteger_bytes_test<B: BigInteger>(rng: &mut TestRng) {
 71      let mut bytes = [0u8; 256];
 72      let x: B = Uniform::rand(rng);
 73      x.write_le(bytes.as_mut()).unwrap();
 74      let y = B::read_le(bytes.as_ref()).unwrap();
 75      assert_eq!(x, y);
 76  }
 77  
 78  fn biginteger_to_string_test<B: BigInteger>(rng: &mut TestRng) {
 79      const ITERATIONS: u64 = 1_000_000;
 80  
 81      // Sanity check the integers starting from 0 to ITERATIONS.
 82      for integer in 0..ITERATIONS {
 83          assert_eq!(format!("{integer}"), B::from(integer).to_string());
 84      }
 85  
 86      // If the BigInteger has more than one limb, sanity check
 87      // that the second limb conversion is also correct.
 88      if B::NUM_LIMBS > 1 {
 89          let start = u64::MAX as u128;
 90          for integer in start..(start + ITERATIONS as u128) {
 91              let mut buffer = vec![0u8; 8 * B::NUM_LIMBS];
 92              buffer.iter_mut().zip(&integer.to_le_bytes()).for_each(|(buf, val)| {
 93                  *buf = *val;
 94              });
 95              assert_eq!(format!("{integer}"), B::read_le(&*buffer).unwrap().to_string());
 96          }
 97      }
 98  
 99      // Sample random integers and check they match against num-bigint.
100      for _ in 0..ITERATIONS {
101          let candidate: B = Uniform::rand(rng);
102          let candidate_hex = format!("{candidate:?}");
103          let reference = num_bigint::BigUint::parse_bytes(candidate_hex.as_bytes(), 16).unwrap();
104          assert_eq!(reference.to_str_radix(10), candidate.to_string());
105      }
106  }
107  
108  fn test_biginteger<B: BigInteger>(zero: B) {
109      let mut rng = TestRng::default();
110  
111      let a: B = Uniform::rand(&mut rng);
112      let b: B = Uniform::rand(&mut rng);
113      biginteger_arithmetic_test(a, b, zero);
114      biginteger_bytes_test::<B>(&mut rng);
115      biginteger_bits_test::<B>();
116      biginteger_to_string_test::<B>(&mut rng);
117  }
118  
119  #[test]
120  fn test_biginteger256() {
121      test_biginteger(BigInteger256::new([0u64; 4]));
122  }
123  
124  #[test]
125  fn test_biginteger384() {
126      test_biginteger(BigInteger384::new([0u64; 6]));
127  }