From d29726791535e55dcd37eac6d811733d51c5f210 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 8 Jan 2018 20:40:26 +0100 Subject: [PATCH 1/8] Implement Rng for Box with alloc feature --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ead940781ae..22a061f0571 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -624,7 +624,9 @@ impl<'a, R: ?Sized> Rng for &'a mut R where R: Rng { } } -#[cfg(feature="std")] +#[cfg(all(feature="alloc", not(feature="std")))] +use alloc::boxed::Box; +#[cfg(any(feature="std", feature="alloc"))] impl Rng for Box where R: Rng { fn next_u32(&mut self) -> u32 { (**self).next_u32() From f0787814141a6c26e77fc855f3d571d8e9ecc55c Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 8 Jan 2018 20:52:50 +0100 Subject: [PATCH 2/8] Test PRNGs without allocating --- src/prng/chacha.rs | 101 ++++++++++++++++---------------------- src/prng/isaac.rs | 109 ++++++++++++++++++++--------------------- src/prng/isaac64.rs | 117 +++++++++++++++++++------------------------- 3 files changed, 145 insertions(+), 182 deletions(-) diff --git a/src/prng/chacha.rs b/src/prng/chacha.rs index 6c4edca0093..61d475fde10 100644 --- a/src/prng/chacha.rs +++ b/src/prng/chacha.rs @@ -258,94 +258,75 @@ mod test { use super::ChaChaRng; #[test] - fn test_rng_rand_seeded() { - let s = ::test::rng().gen_iter::().take(8).collect::>(); - let mut ra: ChaChaRng = SeedableRng::from_seed(&s[..]); - let mut rb: ChaChaRng = SeedableRng::from_seed(&s[..]); - assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + fn test_chacha_construction() { + let seed = [0, 0, 1, 0, 2, 0, 3, 0]; + let mut rng1 = ChaChaRng::from_seed(&seed); + assert_eq!(rng1.next_u32(), 137206642); + + /* FIXME: enable once `from_rng` has landed + let mut rng2 = ChaChaRng::from_rng(&mut rng1).unwrap(); + assert_eq!(rng2.next_u32(), 1325750369); + */ } #[test] - fn test_rng_seeded() { - let seed : &[_] = &[0,1,2,3,4,5,6,7]; - let mut ra: ChaChaRng = SeedableRng::from_seed(seed); - let mut rb: ChaChaRng = SeedableRng::from_seed(seed); - assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); - } - - #[test] - fn test_rng_reseed() { - let s = ::test::rng().gen_iter::().take(8).collect::>(); - let mut r: ChaChaRng = SeedableRng::from_seed(&s[..]); - let string1: String = r.gen_ascii_chars().take(100).collect(); - - r.reseed(&s); - - let string2: String = r.gen_ascii_chars().take(100).collect(); - assert_eq!(string1, string2); - } - - #[test] - fn test_rng_true_values() { + fn test_chacha_true_values() { // Test vectors 1 and 2 from // https://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 - let seed : &[_] = &[0u32; 8]; - let mut ra: ChaChaRng = SeedableRng::from_seed(seed); + let seed: &[_] = &[0u32; 8]; + let mut rng1: ChaChaRng = SeedableRng::from_seed(seed); - let v = (0..16).map(|_| ra.next_u32()).collect::>(); - assert_eq!(v, - vec!(0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, + let mut results = [0u32; 16]; + for i in results.iter_mut() { *i = rng1.next_u32(); } + let expected = [0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, 0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b, 0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8, - 0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2)); + 0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2]; + assert_eq!(results, expected); - let v = (0..16).map(|_| ra.next_u32()).collect::>(); - assert_eq!(v, - vec!(0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, + for i in results.iter_mut() { *i = rng1.next_u32(); } + let expected = [0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, 0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32, 0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874, - 0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b)); + 0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b]; + assert_eq!(results, expected); - let seed : &[_] = &[0,1,2,3,4,5,6,7]; - let mut ra: ChaChaRng = SeedableRng::from_seed(seed); + let seed: &[_] = &[0,1,2,3,4,5,6,7]; + let mut rng2: ChaChaRng = SeedableRng::from_seed(seed); // Store the 17*i-th 32-bit word, // i.e., the i-th word of the i-th 16-word block - let mut v : Vec = Vec::new(); - for _ in 0..16 { - v.push(ra.next_u32()); + for i in results.iter_mut() { + *i = rng2.next_u32(); for _ in 0..16 { - ra.next_u32(); + rng2.next_u32(); } } - - assert_eq!(v, - vec!(0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036, + let expected = [0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036, 0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384, 0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530, - 0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4)); + 0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4]; + assert_eq!(results, expected); } #[test] - fn test_rng_true_bytes() { - let seed : &[_] = &[0u32; 8]; - let mut ra: ChaChaRng = SeedableRng::from_seed(seed); - let mut buf = [0u8; 32]; - ra.fill_bytes(&mut buf); + fn test_chacha_true_bytes() { + let seed: &[_] = &[0u32; 8]; + let mut rng: ChaChaRng = SeedableRng::from_seed(seed); + let mut results = [0u8; 32]; + rng.fill_bytes(&mut results); // Same as first values in test_isaac_true_values as bytes in LE order - assert_eq!(buf, - [118, 184, 224, 173, 160, 241, 61, 144, - 64, 93, 106, 229, 83, 134, 189, 40, - 189, 210, 25, 184, 160, 141, 237, 26, - 168, 54, 239, 204, 139, 119, 13, 199]); + let expected = [118, 184, 224, 173, 160, 241, 61, 144, + 64, 93, 106, 229, 83, 134, 189, 40, + 189, 210, 25, 184, 160, 141, 237, 26, + 168, 54, 239, 204, 139, 119, 13, 199]; + assert_eq!(results, expected); } #[test] - fn test_rng_clone() { - let seed : &[_] = &[0u32; 8]; + fn test_chacha_clone() { + let seed: &[_] = &[0,1,2,3,4,5,6,7]; let mut rng: ChaChaRng = SeedableRng::from_seed(seed); let mut clone = rng.clone(); for _ in 0..16 { diff --git a/src/prng/isaac.rs b/src/prng/isaac.rs index 811c8f4640b..fa76e285c15 100644 --- a/src/prng/isaac.rs +++ b/src/prng/isaac.rs @@ -377,79 +377,65 @@ mod test { use super::IsaacRng; #[test] - fn test_rng_32_rand_seeded() { - let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]); - let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]); - assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + fn test_isaac_construction() { + let seed = [1, 23, 456, 7890, 0, 0, 0, 0]; + let mut rng1 = IsaacRng::from_seed(&seed); + assert_eq!(rng1.next_u32(), 2869442790); + + /* FIXME: enable once `from_rng` has landed + let mut rng2 = IsaacRng::from_rng(&mut rng1).unwrap(); + assert_eq!(rng1.next_u32(), 3094074039); + */ } #[test] - fn test_rng_32_seeded() { + fn test_isaac_true_values_32() { let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut ra: IsaacRng = SeedableRng::from_seed(seed); - let mut rb: IsaacRng = SeedableRng::from_seed(seed); - assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); - } - - #[test] - fn test_rng_32_reseed() { - let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut r: IsaacRng = SeedableRng::from_seed(&s[..]); - let string1: String = r.gen_ascii_chars().take(100).collect(); - - r.reseed(&s[..]); - - let string2: String = r.gen_ascii_chars().take(100).collect(); - assert_eq!(string1, string2); - } - - #[test] - fn test_rng_32_true_values() { - let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut ra: IsaacRng = SeedableRng::from_seed(seed); - // Regression test that isaac is actually using the above vector - let v = (0..10).map(|_| ra.next_u32()).collect::>(); - assert_eq!(v, - vec!(2558573138, 873787463, 263499565, 2103644246, 3595684709, - 4203127393, 264982119, 2765226902, 2737944514, 3900253796)); + let mut rng1: IsaacRng = SeedableRng::from_seed(seed); + let mut results = [0u32; 10]; + for i in results.iter_mut() { *i = rng1.next_u32(); } + let expected = [ + 2558573138, 873787463, 263499565, 2103644246, 3595684709, + 4203127393, 264982119, 2765226902, 2737944514, 3900253796]; + assert_eq!(results, expected); let seed: &[_] = &[12345, 67890, 54321, 9876]; - let mut rb: IsaacRng = SeedableRng::from_seed(seed); + let mut rng2: IsaacRng = SeedableRng::from_seed(seed); // skip forward to the 10000th number - for _ in 0..10000 { rb.next_u32(); } + for _ in 0..10000 { rng2.next_u32(); } - let v = (0..10).map(|_| rb.next_u32()).collect::>(); - assert_eq!(v, - vec!(3676831399, 3183332890, 2834741178, 3854698763, 2717568474, - 1576568959, 3507990155, 179069555, 141456972, 2478885421)); + for i in results.iter_mut() { *i = rng2.next_u32(); } + let expected = [ + 3676831399, 3183332890, 2834741178, 3854698763, 2717568474, + 1576568959, 3507990155, 179069555, 141456972, 2478885421]; + assert_eq!(results, expected); } #[test] - fn test_rng_64_true_values() { + fn test_isaac_true_values_64() { // As above, using little-endian versions of above values let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut ra: IsaacRng = SeedableRng::from_seed(seed); - // Regression test that isaac is actually using the above vector - let v = (0..5).map(|_| ra.next_u64()).collect::>(); - assert_eq!(v, - vec!(3752888579798383186, 9035083239252078381, 18052294697452424037, 11876559110374379111, 16751462502657800130)); + let mut rng: IsaacRng = SeedableRng::from_seed(seed); + let mut results = [0u64; 5]; + for i in results.iter_mut() { *i = rng.next_u64(); } + let expected = [ + 3752888579798383186, 9035083239252078381,18052294697452424037, + 11876559110374379111, 16751462502657800130]; + assert_eq!(results, expected); } #[test] fn test_isaac_true_bytes() { let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut rng1 = IsaacRng::from_seed(seed); - let mut buf = [0u8; 32]; - rng1.fill_bytes(&mut buf); + let mut rng = IsaacRng::from_seed(seed); + let mut results = [0u8; 32]; + rng.fill_bytes(&mut results); // Same as first values in test_isaac_true_values as bytes in LE order - assert_eq!(buf, - [82, 186, 128, 152, 71, 240, 20, 52, - 45, 175, 180, 15, 86, 16, 99, 125, - 101, 203, 81, 214, 97, 162, 134, 250, - 103, 78, 203, 15, 150, 3, 210, 164]); + let expected = [82, 186, 128, 152, 71, 240, 20, 52, + 45, 175, 180, 15, 86, 16, 99, 125, + 101, 203, 81, 214, 97, 162, 134, 250, + 103, 78, 203, 15, 150, 3, 210, 164]; + assert_eq!(results, expected); } #[test] @@ -460,12 +446,23 @@ mod test { // Note: We only test the first 16 integers, not the full 256 of the // first block. let mut rng = IsaacRng::new_from_u64(0); - let vec = (0..16).map(|_| rng.next_u32()).collect::>(); + let mut results = [0u32; 16]; + for i in results.iter_mut() { *i = rng.next_u32(); } let expected: [u32; 16] = [ 0x71D71FD2, 0xB54ADAE7, 0xD4788559, 0xC36129FA, 0x21DC1EA9, 0x3CB879CA, 0xD83B237F, 0xFA3CE5BD, 0x8D048509, 0xD82E9489, 0xDB452848, 0xCA20E846, 0x500F972E, 0x0EEFF940, 0x00D6B993, 0xBC12C17F]; - assert_eq!(vec, expected); + assert_eq!(results, expected); + } + + #[test] + fn test_isaac_clone() { + let seed: &[_] = &[1, 23, 456, 7890, 12345]; + let mut rng: IsaacRng = SeedableRng::from_seed(seed); + let mut clone = rng.clone(); + for _ in 0..16 { + assert_eq!(rng.next_u64(), clone.next_u64()); + } } } diff --git a/src/prng/isaac64.rs b/src/prng/isaac64.rs index ed71fb7f8ba..76568f867a6 100644 --- a/src/prng/isaac64.rs +++ b/src/prng/isaac64.rs @@ -356,73 +356,57 @@ mod test { use super::Isaac64Rng; #[test] - fn test_rng_64_rand_seeded() { - let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]); - let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]); - assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + fn test_isaac64_construction() { + // Test that various construction techniques produce a working RNG. + let seed = [98784247809, 33887291965896, 0, 0]; + let mut rng1 = Isaac64Rng::from_seed(&seed); + assert_eq!(rng1.next_u64(), 14964555543728284049); + + /* FIXME: enable once `from_rng` has landed + let mut rng2 = Isaac64Rng::from_rng(&mut rng1).unwrap(); + assert_eq!(rng2.next_u64(), 919595328260451758); + */ } #[test] - fn test_rng_64_seeded() { + fn test_isaac64_true_values_64() { let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut ra: Isaac64Rng = SeedableRng::from_seed(seed); - let mut rb: Isaac64Rng = SeedableRng::from_seed(seed); - assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); - } - - #[test] - fn test_rng_64_reseed() { - let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut r: Isaac64Rng = SeedableRng::from_seed(&s[..]); - let string1: String = r.gen_ascii_chars().take(100).collect(); - - r.reseed(&s[..]); - - let string2: String = r.gen_ascii_chars().take(100).collect(); - assert_eq!(string1, string2); - } - - #[test] - fn test_rng_64_true_values() { - let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut ra: Isaac64Rng = SeedableRng::from_seed(seed); - // Regression test that isaac is actually using the above vector - let v = (0..10).map(|_| ra.next_u64()).collect::>(); - assert_eq!(v, - vec!(547121783600835980, 14377643087320773276, 17351601304698403469, - 1238879483818134882, 11952566807690396487, 13970131091560099343, - 4469761996653280935, 15552757044682284409, 6860251611068737823, - 13722198873481261842)); + let mut rng1: Isaac64Rng = SeedableRng::from_seed(seed); + let mut results = [0u64; 10]; + for i in results.iter_mut() { *i = rng1.next_u64(); } + let expected = [ + 547121783600835980, 14377643087320773276, 17351601304698403469, + 1238879483818134882, 11952566807690396487, 13970131091560099343, + 4469761996653280935, 15552757044682284409, 6860251611068737823, + 13722198873481261842]; + assert_eq!(results, expected); let seed: &[_] = &[12345, 67890, 54321, 9876]; - let mut rb: Isaac64Rng = SeedableRng::from_seed(seed); + let mut rng2: Isaac64Rng = SeedableRng::from_seed(seed); // skip forward to the 10000th number - for _ in 0..10000 { rb.next_u64(); } - - let v = (0..10).map(|_| rb.next_u64()).collect::>(); - assert_eq!(v, - vec!(18143823860592706164, 8491801882678285927, 2699425367717515619, - 17196852593171130876, 2606123525235546165, 15790932315217671084, - 596345674630742204, 9947027391921273664, 11788097613744130851, - 10391409374914919106)); + for _ in 0..10000 { rng2.next_u64(); } + + for i in results.iter_mut() { *i = rng2.next_u64(); } + let expected = [ + 18143823860592706164, 8491801882678285927, 2699425367717515619, + 17196852593171130876, 2606123525235546165, 15790932315217671084, + 596345674630742204, 9947027391921273664, 11788097613744130851, + 10391409374914919106]; + assert_eq!(results, expected); } #[test] fn test_isaac64_true_values_32() { let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut rng1 = Isaac64Rng::from_seed(seed); - let v = (0..12).map(|_| rng1.next_u32()).collect::>(); + let mut rng = Isaac64Rng::from_seed(seed); + let mut results = [0u32; 12]; + for i in results.iter_mut() { *i = rng.next_u32(); } // Subset of above values, as an LE u32 sequence - assert_eq!(v, - [141028748, 127386717, - 1058730652, 3347555894, - 851491469, 4039984500, - 2692730210, 288449107, - 646103879, 2782923823, - 4195642895, 3252674613]); + let expected = [ + 141028748, 127386717, 1058730652, 3347555894, 851491469, + 4039984500, 2692730210, 288449107, 646103879, 2782923823, + 4195642895, 3252674613]; + assert_eq!(results, expected); } #[test] @@ -445,26 +429,27 @@ mod test { #[test] fn test_isaac64_true_bytes() { let seed: &[_] = &[1, 23, 456, 7890, 12345]; - let mut rng1 = Isaac64Rng::from_seed(seed); - let mut buf = [0u8; 32]; - rng1.fill_bytes(&mut buf); + let mut rng = Isaac64Rng::from_seed(seed); + let mut results = [0u8; 32]; + rng.fill_bytes(&mut results); // Same as first values in test_isaac64_true_values as bytes in LE order - assert_eq!(buf, - [140, 237, 103, 8, 93, 196, 151, 7, - 156, 242, 26, 63, 54, 166, 135, 199, - 141, 186, 192, 50, 116, 69, 205, 240, - 98, 205, 127, 160, 83, 98, 49, 17]); + let expected = [140, 237, 103, 8, 93, 196, 151, 7, + 156, 242, 26, 63, 54, 166, 135, 199, + 141, 186, 192, 50, 116, 69, 205, 240, + 98, 205, 127, 160, 83, 98, 49, 17]; + assert_eq!(results, expected); } #[test] - fn test_isaac_new_uninitialized() { + fn test_isaac64_new_uninitialized() { // Compare the results from initializing `IsaacRng` with // `new_from_u64(0)`, to make sure it is the same as the reference // implementation when used uninitialized. // Note: We only test the first 16 integers, not the full 256 of the // first block. let mut rng = Isaac64Rng::new_from_u64(0); - let vec = (0..16).map(|_| rng.next_u64()).collect::>(); + let mut results = [0u64; 16]; + for i in results.iter_mut() { *i = rng.next_u64(); } let expected: [u64; 16] = [ 0xF67DFBA498E4937C, 0x84A5066A9204F380, 0xFEE34BD5F5514DBB, 0x4D1664739B8F80D6, 0x8607459AB52A14AA, 0x0E78BC5A98529E49, @@ -472,11 +457,11 @@ mod test { 0xD0771FAF3CB04714, 0x30E86F68A37B008D, 0x3074EBC0488A3ADF, 0x270645EA7A2790BC, 0x5601A0A8D3763C6A, 0x2F83071F53F325DD, 0xB9090F3D42D2D2EA]; - assert_eq!(vec, expected); + assert_eq!(results, expected); } #[test] - fn test_rng_clone() { + fn test_isaac64_clone() { let seed: &[_] = &[1, 23, 456, 7890, 12345]; let mut rng: Isaac64Rng = SeedableRng::from_seed(seed); let mut clone = rng.clone(); From d24a29dc5d0c60097d8ad69cff559b455cd4e49c Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 8 Jan 2018 22:00:31 +0100 Subject: [PATCH 3/8] Test WeightedChoice without allocating --- src/distributions/mod.rs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index 8ff13c696d6..1fb02d9e708 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -335,36 +335,36 @@ mod tests { }} } - t!(vec!(Weighted { weight: 1, item: 10}), [10]); + t!([Weighted { weight: 1, item: 10}], [10]); // skip some - t!(vec!(Weighted { weight: 0, item: 20}, - Weighted { weight: 2, item: 21}, - Weighted { weight: 0, item: 22}, - Weighted { weight: 1, item: 23}), + t!([Weighted { weight: 0, item: 20}, + Weighted { weight: 2, item: 21}, + Weighted { weight: 0, item: 22}, + Weighted { weight: 1, item: 23}], [21,21, 23]); // different weights - t!(vec!(Weighted { weight: 4, item: 30}, - Weighted { weight: 3, item: 31}), + t!([Weighted { weight: 4, item: 30}, + Weighted { weight: 3, item: 31}], [30,30,30,30, 31,31,31]); // check that we're binary searching // correctly with some vectors of odd // length. - t!(vec!(Weighted { weight: 1, item: 40}, - Weighted { weight: 1, item: 41}, - Weighted { weight: 1, item: 42}, - Weighted { weight: 1, item: 43}, - Weighted { weight: 1, item: 44}), + t!([Weighted { weight: 1, item: 40}, + Weighted { weight: 1, item: 41}, + Weighted { weight: 1, item: 42}, + Weighted { weight: 1, item: 43}, + Weighted { weight: 1, item: 44}], [40, 41, 42, 43, 44]); - t!(vec!(Weighted { weight: 1, item: 50}, - Weighted { weight: 1, item: 51}, - Weighted { weight: 1, item: 52}, - Weighted { weight: 1, item: 53}, - Weighted { weight: 1, item: 54}, - Weighted { weight: 1, item: 55}, - Weighted { weight: 1, item: 56}), + t!([Weighted { weight: 1, item: 50}, + Weighted { weight: 1, item: 51}, + Weighted { weight: 1, item: 52}, + Weighted { weight: 1, item: 53}, + Weighted { weight: 1, item: 54}, + Weighted { weight: 1, item: 55}, + Weighted { weight: 1, item: 56}], [50, 51, 52, 53, 54, 55, 56]); } From e7ef1d500c33df2ee9f39b0f4ed941fab08b20dd Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 8 Jan 2018 22:00:55 +0100 Subject: [PATCH 4/8] Test reseeding without allocating --- src/reseeding.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/reseeding.rs b/src/reseeding.rs index 93bc32523fb..f0f225d5780 100644 --- a/src/reseeding.rs +++ b/src/reseeding.rs @@ -148,8 +148,7 @@ impl Default for ReseedWithDefault { #[cfg(test)] mod test { use impls; - use std::default::Default; - use std::iter::repeat; + use core::default::Default; use super::{ReseedingRng, ReseedWithDefault}; use {SeedableRng, Rng}; @@ -207,25 +206,23 @@ mod test { #[test] fn test_rng_reseed() { - let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3)); - let string1: String = r.gen_ascii_chars().take(100).collect(); + let mut rng: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3)); + let mut results1 = [0u32; 32]; + for i in results1.iter_mut() { *i = rng.next_u32(); } - r.reseed((ReseedWithDefault, 3)); + rng.reseed((ReseedWithDefault, 3)); - let string2: String = r.gen_ascii_chars().take(100).collect(); - assert_eq!(string1, string2); + let mut results2 = [0u32; 32]; + for i in results2.iter_mut() { *i = rng.next_u32(); } + assert_eq!(results1, results2); } const FILL_BYTES_V_LEN: usize = 13579; #[test] fn test_rng_fill_bytes() { - let mut v = repeat(0u8).take(FILL_BYTES_V_LEN).collect::>(); + let mut v = [0u8; FILL_BYTES_V_LEN]; ::test::rng().fill_bytes(&mut v); - // Sanity test: if we've gotten here, `fill_bytes` has not infinitely - // recursed. - assert_eq!(v.len(), FILL_BYTES_V_LEN); - // To test that `fill_bytes` actually did something, check that the // average of `v` is not 0. let mut sum = 0.0; From b2ba9f89f415476a9263d08e1658be8a136fca20 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 8 Jan 2018 22:15:56 +0100 Subject: [PATCH 5/8] Don't use the vec! macro in seq.rs --- src/seq.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/seq.rs b/src/seq.rs index 57d7aeff7cf..44b3261896a 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -227,6 +227,8 @@ fn sample_indices_cache( mod test { use super::*; use {thread_rng, XorShiftRng, SeedableRng}; + #[cfg(not(feature="std"))] + use alloc::Vec; #[test] fn test_sample_iter() { @@ -254,25 +256,25 @@ mod test { let mut r = thread_rng(); // sample 0 items - assert_eq!(sample_slice(&mut r, empty, 0), vec![]); - assert_eq!(sample_slice(&mut r, &[42, 2, 42], 0), vec![]); + assert_eq!(&sample_slice(&mut r, empty, 0)[..], []); + assert_eq!(&sample_slice(&mut r, &[42, 2, 42], 0)[..], []); // sample 1 item - assert_eq!(sample_slice(&mut r, &[42], 1), vec![42]); + assert_eq!(&sample_slice(&mut r, &[42], 1)[..], [42]); let v = sample_slice(&mut r, &[1, 42], 1)[0]; assert!(v == 1 || v == 42); // sample "all" the items let v = sample_slice(&mut r, &[42, 133], 2); - assert!(v == vec![42, 133] || v == vec![133, 42]); + assert!(&v[..] == [42, 133] || v[..] == [133, 42]); - assert_eq!(sample_indices_inplace(&mut r, 0, 0), vec![]); - assert_eq!(sample_indices_inplace(&mut r, 1, 0), vec![]); - assert_eq!(sample_indices_inplace(&mut r, 1, 1), vec![0]); + assert_eq!(&sample_indices_inplace(&mut r, 0, 0)[..], []); + assert_eq!(&sample_indices_inplace(&mut r, 1, 0)[..], []); + assert_eq!(&sample_indices_inplace(&mut r, 1, 1)[..], [0]); - assert_eq!(sample_indices_cache(&mut r, 0, 0), vec![]); - assert_eq!(sample_indices_cache(&mut r, 1, 0), vec![]); - assert_eq!(sample_indices_cache(&mut r, 1, 1), vec![0]); + assert_eq!(&sample_indices_cache(&mut r, 0, 0)[..], []); + assert_eq!(&sample_indices_cache(&mut r, 1, 0)[..], []); + assert_eq!(&sample_indices_cache(&mut r, 1, 1)[..], [0]); // Make sure lucky 777's aren't lucky let slice = &[42, 777]; @@ -304,8 +306,6 @@ mod test { r.next_u32(), r.next_u32(), r.next_u32(), r.next_u32() ]; - println!("Selecting indices: len={}, amount={}, seed={:?}", length, amount, seed); - // assert that the two index methods give exactly the same result let inplace = sample_indices_inplace( &mut xor_rng(seed), length, amount); From 7ccf19d5f2d432428da085acf6b6ce42eb0a31d8 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 10 Jan 2018 07:11:41 +0100 Subject: [PATCH 6/8] Replace thread_rng with StdRng wrapper in tests --- src/distributions/exponential.rs | 2 +- src/distributions/gamma.rs | 10 ++--- src/distributions/mod.rs | 5 ++- src/distributions/normal.rs | 4 +- src/distributions/range.rs | 5 +-- src/lib.rs | 63 +++++++++++++++++--------------- src/rand_impls.rs | 6 +-- src/reseeding.rs | 2 +- src/seq.rs | 8 ++-- 9 files changed, 55 insertions(+), 50 deletions(-) diff --git a/src/distributions/exponential.rs b/src/distributions/exponential.rs index 0580f63c46b..d3e48fc84f8 100644 --- a/src/distributions/exponential.rs +++ b/src/distributions/exponential.rs @@ -105,7 +105,7 @@ mod test { #[test] fn test_exp() { let mut exp = Exp::new(10.0); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(221); for _ in 0..1000 { assert!(exp.sample(&mut rng) >= 0.0); assert!(exp.ind_sample(&mut rng) >= 0.0); diff --git a/src/distributions/gamma.rs b/src/distributions/gamma.rs index 9c30a05833e..9c4ac45aa44 100644 --- a/src/distributions/gamma.rs +++ b/src/distributions/gamma.rs @@ -334,7 +334,7 @@ mod test { #[test] fn test_chi_squared_one() { let mut chi = ChiSquared::new(1.0); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(201); for _ in 0..1000 { chi.sample(&mut rng); chi.ind_sample(&mut rng); @@ -343,7 +343,7 @@ mod test { #[test] fn test_chi_squared_small() { let mut chi = ChiSquared::new(0.5); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(202); for _ in 0..1000 { chi.sample(&mut rng); chi.ind_sample(&mut rng); @@ -352,7 +352,7 @@ mod test { #[test] fn test_chi_squared_large() { let mut chi = ChiSquared::new(30.0); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(203); for _ in 0..1000 { chi.sample(&mut rng); chi.ind_sample(&mut rng); @@ -367,7 +367,7 @@ mod test { #[test] fn test_f() { let mut f = FisherF::new(2.0, 32.0); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(204); for _ in 0..1000 { f.sample(&mut rng); f.ind_sample(&mut rng); @@ -377,7 +377,7 @@ mod test { #[test] fn test_t() { let mut t = StudentT::new(11.0); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(205); for _ in 0..1000 { t.sample(&mut rng); t.ind_sample(&mut rng); diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index 1fb02d9e708..d62874bc298 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -311,9 +311,10 @@ mod tests { fn test_rand_sample() { let mut rand_sample = RandSample::::new(); - assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0)); - assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0)); + assert_eq!(rand_sample.sample(&mut ::test::rng(231)), ConstRand(0)); + assert_eq!(rand_sample.ind_sample(&mut ::test::rng(232)), ConstRand(0)); } + #[test] fn test_weighted_choice() { // this makes assumptions about the internal implementation of diff --git a/src/distributions/normal.rs b/src/distributions/normal.rs index 55640fd3c08..71d498b573a 100644 --- a/src/distributions/normal.rs +++ b/src/distributions/normal.rs @@ -171,7 +171,7 @@ mod tests { #[test] fn test_normal() { let mut norm = Normal::new(10.0, 10.0); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(210); for _ in 0..1000 { norm.sample(&mut rng); norm.ind_sample(&mut rng); @@ -187,7 +187,7 @@ mod tests { #[test] fn test_log_normal() { let mut lnorm = LogNormal::new(10.0, 10.0); - let mut rng = ::test::rng(); + let mut rng = ::test::rng(211); for _ in 0..1000 { lnorm.sample(&mut rng); lnorm.ind_sample(&mut rng); diff --git a/src/distributions/range.rs b/src/distributions/range.rs index ccdcdf1aa16..051fb7a85ab 100644 --- a/src/distributions/range.rs +++ b/src/distributions/range.rs @@ -185,7 +185,7 @@ mod tests { #[test] fn test_integers() { - let mut rng = ::test::rng(); + let mut rng = ::test::rng(251); macro_rules! t { ($($ty:ident),*) => {{ $( @@ -214,7 +214,7 @@ mod tests { #[test] fn test_floats() { - let mut rng = ::test::rng(); + let mut rng = ::test::rng(252); macro_rules! t { ($($ty:ty),*) => {{ $( @@ -237,5 +237,4 @@ mod tests { t!(f32, f64) } - } diff --git a/src/lib.rs b/src/lib.rs index 22a061f0571..a53ef2f51f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -987,9 +987,9 @@ mod test { use super::{Rng, thread_rng, random, SeedableRng, StdRng, weak_rng}; use std::iter::repeat; - pub struct MyRng { inner: R } + pub struct TestRng { inner: R } - impl Rng for MyRng { + impl Rng for TestRng { fn next_u32(&mut self) -> u32 { self.inner.next_u32() } @@ -1001,8 +1001,9 @@ mod test { } } - pub fn rng() -> MyRng<::ThreadRng> { - MyRng { inner: ::thread_rng() } + pub fn rng(seed: u64) -> TestRng { + let seed = [seed as usize]; + TestRng { inner: StdRng::from_seed(&seed) } } struct ConstRng { i: u64 } @@ -1054,7 +1055,7 @@ mod test { #[test] fn test_gen_range() { - let mut r = thread_rng(); + let mut r = rng(101); for _ in 0..1000 { let a = r.gen_range(-3, 42); assert!(a >= -3 && a < 42); @@ -1074,27 +1075,27 @@ mod test { #[test] #[should_panic] fn test_gen_range_panic_int() { - let mut r = thread_rng(); + let mut r = rng(102); r.gen_range(5, -2); } #[test] #[should_panic] fn test_gen_range_panic_usize() { - let mut r = thread_rng(); + let mut r = rng(103); r.gen_range(5, 2); } #[test] fn test_gen_weighted_bool() { - let mut r = thread_rng(); + let mut r = rng(104); assert_eq!(r.gen_weighted_bool(0), true); assert_eq!(r.gen_weighted_bool(1), true); } #[test] fn test_gen_ascii_str() { - let mut r = thread_rng(); + let mut r = rng(105); assert_eq!(r.gen_ascii_chars().take(0).count(), 0); assert_eq!(r.gen_ascii_chars().take(10).count(), 10); assert_eq!(r.gen_ascii_chars().take(16).count(), 16); @@ -1102,7 +1103,7 @@ mod test { #[test] fn test_gen_vec() { - let mut r = thread_rng(); + let mut r = rng(106); assert_eq!(r.gen_iter::().take(0).count(), 0); assert_eq!(r.gen_iter::().take(10).count(), 10); assert_eq!(r.gen_iter::().take(16).count(), 16); @@ -1110,7 +1111,7 @@ mod test { #[test] fn test_choose() { - let mut r = thread_rng(); + let mut r = rng(107); assert_eq!(r.choose(&[1, 1, 1]).map(|&x|x), Some(1)); let v: &[isize] = &[]; @@ -1119,7 +1120,7 @@ mod test { #[test] fn test_shuffle() { - let mut r = thread_rng(); + let mut r = rng(108); let empty: &mut [isize] = &mut []; r.shuffle(empty); let mut one = [1]; @@ -1150,7 +1151,7 @@ mod test { #[test] fn test_rng_trait_object() { - let mut rng = thread_rng(); + let mut rng = rng(109); { let mut r = &mut rng as &mut Rng; r.next_u32(); @@ -1188,24 +1189,28 @@ mod test { } #[test] - fn test_std_rng_seeded() { - let s = thread_rng().gen_iter::().take(256).collect::>(); - let mut ra: StdRng = SeedableRng::from_seed(&s[..]); - let mut rb: StdRng = SeedableRng::from_seed(&s[..]); - assert!(iter_eq(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + #[cfg(target_pointer_width = "32")] + fn test_stdrng_construction() { + let seed = [1, 23, 456, 7890, 0, 0, 0, 0]; + let mut rng1 = StdRng::from_seed(&seed); + assert_eq!(rng1.next_u32(), 2869442790); + + /* FIXME: enable once `from_rng` has landed + let mut rng2 = StdRng::from_rng(&mut rng1).unwrap(); + assert_eq!(rng1.next_u32(), 3094074039); + */ } - #[test] - fn test_std_rng_reseed() { - let s = thread_rng().gen_iter::().take(256).collect::>(); - let mut r: StdRng = SeedableRng::from_seed(&s[..]); - let string1 = r.gen_ascii_chars().take(100).collect::(); - - r.reseed(&s); - - let string2 = r.gen_ascii_chars().take(100).collect::(); - assert_eq!(string1, string2); + #[cfg(target_pointer_width = "64")] + fn test_stdrng_construction() { + let seed = [1, 23, 456, 7890, 0, 0, 0, 0]; + let mut rng1 = StdRng::from_seed(&seed); + assert_eq!(rng1.next_u32(), 3477963620); + + /* FIXME: enable once `from_rng` has landed + let mut rng2 = StdRng::from_rng(&mut rng1).unwrap(); + assert_eq!(rng1.next_u32(), 3094074039); + */ } #[test] diff --git a/src/rand_impls.rs b/src/rand_impls.rs index d734aa38b0e..4b520b41bc5 100644 --- a/src/rand_impls.rs +++ b/src/rand_impls.rs @@ -249,7 +249,7 @@ impl Rand for Option { #[cfg(test)] mod tests { use impls; - use {Rng, thread_rng, Open01, Closed01}; + use {Rng, Open01, Closed01}; struct ConstantRng(u64); impl Rng for ConstantRng { @@ -278,7 +278,7 @@ mod tests { fn rand_open() { // this is unlikely to catch an incorrect implementation that // generates exactly 0 or 1, but it keeps it sane. - let mut rng = thread_rng(); + let mut rng = ::test::rng(501); for _ in 0..1_000 { // strict inequalities let Open01(f) = rng.gen::>(); @@ -291,7 +291,7 @@ mod tests { #[test] fn rand_closed() { - let mut rng = thread_rng(); + let mut rng = ::test::rng(502); for _ in 0..1_000 { // strict inequalities let Closed01(f) = rng.gen::>(); diff --git a/src/reseeding.rs b/src/reseeding.rs index f0f225d5780..cc4fef75481 100644 --- a/src/reseeding.rs +++ b/src/reseeding.rs @@ -221,7 +221,7 @@ mod test { #[test] fn test_rng_fill_bytes() { let mut v = [0u8; FILL_BYTES_V_LEN]; - ::test::rng().fill_bytes(&mut v); + ::test::rng(321).fill_bytes(&mut v); // To test that `fill_bytes` actually did something, check that the // average of `v` is not 0. diff --git a/src/seq.rs b/src/seq.rs index 44b3261896a..6dfa4bbbdcd 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -226,7 +226,7 @@ fn sample_indices_cache( #[cfg(test)] mod test { use super::*; - use {thread_rng, XorShiftRng, SeedableRng}; + use {XorShiftRng, SeedableRng}; #[cfg(not(feature="std"))] use alloc::Vec; @@ -235,7 +235,7 @@ mod test { let min_val = 1; let max_val = 100; - let mut r = thread_rng(); + let mut r = ::test::rng(401); let vals = (min_val..max_val).collect::>(); let small_sample = sample_iter(&mut r, vals.iter(), 5).unwrap(); let large_sample = sample_iter(&mut r, vals.iter(), vals.len() + 5).unwrap_err(); @@ -253,7 +253,7 @@ mod test { fn test_sample_slice_boundaries() { let empty: &[u8] = &[]; - let mut r = thread_rng(); + let mut r = ::test::rng(402); // sample 0 items assert_eq!(&sample_slice(&mut r, empty, 0)[..], []); @@ -298,7 +298,7 @@ mod test { let xor_rng = XorShiftRng::from_seed; let max_range = 100; - let mut r = thread_rng(); + let mut r = ::test::rng(403); for length in 1usize..max_range { let amount = r.gen_range(0, length); From b4c7517251fd7ed36a39a234eff8c266571248d3 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 10 Jan 2018 21:54:04 +0100 Subject: [PATCH 7/8] Final fixes to enable testing with no_std --- src/distributions/mod.rs | 2 +- src/lib.rs | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index d62874bc298..9eb2e464baf 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -405,7 +405,7 @@ mod tests { } #[test] #[should_panic] fn test_weighted_choice_weight_overflows() { - let x = ::std::u32::MAX / 2; // x + x + 2 is the overflow + let x = ::core::u32::MAX / 2; // x + x + 2 is the overflow WeightedChoice::new(&mut [Weighted { weight: x, item: 0 }, Weighted { weight: 1, item: 1 }, Weighted { weight: x, item: 2 }, diff --git a/src/lib.rs b/src/lib.rs index a53ef2f51f6..66bca0fb00f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,6 +255,7 @@ use core::mem; #[cfg(feature="std")] use std::cell::RefCell; #[cfg(feature="std")] use std::io; #[cfg(feature="std")] use std::rc::Rc; +#[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box; // external rngs pub use jitter::JitterRng; @@ -624,8 +625,6 @@ impl<'a, R: ?Sized> Rng for &'a mut R where R: Rng { } } -#[cfg(all(feature="alloc", not(feature="std")))] -use alloc::boxed::Box; #[cfg(any(feature="std", feature="alloc"))] impl Rng for Box where R: Rng { fn next_u32(&mut self) -> u32 { @@ -984,8 +983,11 @@ pub fn sample(rng: &mut R, iterable: I, amount: usize) -> Vec #[cfg(test)] mod test { use impls; - use super::{Rng, thread_rng, random, SeedableRng, StdRng, weak_rng}; - use std::iter::repeat; + #[cfg(feature="std")] + use super::{random, thread_rng, weak_rng}; + use super::{Rng, SeedableRng, StdRng}; + #[cfg(feature="alloc")] + use alloc::boxed::Box; pub struct TestRng { inner: R } @@ -1041,8 +1043,9 @@ mod test { let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87]; for &n in lengths.iter() { - let mut v = repeat(0u8).take(n).collect::>(); - r.fill_bytes(&mut v); + let mut buffer = [0u8; 87]; + let mut v = &mut buffer[0..n]; + r.fill_bytes(v); // use this to get nicer error messages. for (i, &byte) in v.iter().enumerate() { @@ -1139,6 +1142,7 @@ mod test { } #[test] + #[cfg(feature="std")] fn test_thread_rng() { let mut r = thread_rng(); r.gen::(); @@ -1150,6 +1154,7 @@ mod test { } #[test] + #[cfg(any(feature="std", feature="alloc"))] fn test_rng_trait_object() { let mut rng = rng(109); { @@ -1175,6 +1180,7 @@ mod test { } #[test] + #[cfg(feature="std")] fn test_random() { // not sure how to test this aside from just getting some values let _n : usize = random(); @@ -1214,6 +1220,7 @@ mod test { } #[test] + #[cfg(feature="std")] fn test_weak_rng() { let s = weak_rng().gen_iter::().take(256).collect::>(); let mut ra: StdRng = SeedableRng::from_seed(&s[..]); From 48285068b48662af3a1e41cc544da45bc533bb3c Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Wed, 10 Jan 2018 21:57:29 +0100 Subject: [PATCH 8/8] Simplify reseeding::test_rng_fill_bytes --- src/reseeding.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/reseeding.rs b/src/reseeding.rs index cc4fef75481..a312e7bb53a 100644 --- a/src/reseeding.rs +++ b/src/reseeding.rs @@ -223,12 +223,8 @@ mod test { let mut v = [0u8; FILL_BYTES_V_LEN]; ::test::rng(321).fill_bytes(&mut v); - // To test that `fill_bytes` actually did something, check that the - // average of `v` is not 0. - let mut sum = 0.0; - for &x in v.iter() { - sum += x as f64; - } - assert!(sum / v.len() as f64 != 0.0); + // To test that `fill_bytes` actually did something, check that not all + // bytes are zero. + assert!(!v.iter().all(|&x| x == 0)); } }