/ console / types / string / src / random.rs
random.rs
 1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
 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 super::*;
17  
18  impl<E: Environment> Distribution<StringType<E>> for Standard {
19      #[inline]
20      fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> StringType<E> {
21          // Sample a random number up to 1/4th of the maximum bytes.
22          let num_bytes = rng.gen_range(1..(E::MAX_STRING_BYTES / 4) as usize);
23          // Sample a random string.
24          StringType::new(&rng.sample_iter(&Alphanumeric).take(num_bytes).map(char::from).collect::<String>())
25      }
26  }
27  
28  #[cfg(test)]
29  mod tests {
30      use super::*;
31      use alphavm_console_network_environment::Console;
32  
33      use std::collections::HashMap;
34  
35      type CurrentEnvironment = Console;
36  
37      const ITERATIONS: usize = 100;
38  
39      #[test]
40      fn test_random() {
41          // Initialize a map[string]=>occurrences to store all seen random elements.
42          let mut map = HashMap::with_capacity(ITERATIONS);
43  
44          let mut rng = TestRng::default();
45  
46          for _ in 0..ITERATIONS {
47              // Sample a random value.
48              let string: StringType<CurrentEnvironment> = Uniform::rand(&mut rng);
49  
50              // Add the new random value to the set.
51              map.entry(string).and_modify(|count| *count += 1).or_insert(1);
52          }
53          for (string, count) in map {
54              let allowed_occurrences = 1 + ITERATIONS / (string.len() * 10);
55              assert!(count <= allowed_occurrences, "Encountered an element with a count of {count}: {string}");
56          }
57      }
58  }