1 | use crate::cli::TestOpts; |
2 | use crate::types::{TestDescAndFn, TestId, TestName}; |
3 | use std::hash::{DefaultHasher, Hasher}; |
4 | use std::time::{SystemTime, UNIX_EPOCH}; |
5 | |
6 | pub fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> { |
7 | opts.shuffle_seed.or_else(|| { |
8 | if opts.shuffle { |
9 | Some( |
10 | SystemTime::now() |
11 | .duration_since(UNIX_EPOCH) |
12 | .expect("Failed to get system time" ) |
13 | .as_nanos() as u64, |
14 | ) |
15 | } else { |
16 | None |
17 | } |
18 | }) |
19 | } |
20 | |
21 | pub fn shuffle_tests(shuffle_seed: u64, tests: &mut [(TestId, TestDescAndFn)]) { |
22 | let test_names: Vec<&TestName> = tests.iter().map(|test| &test.1.desc.name).collect(); |
23 | let test_names_hash: u64 = calculate_hash(&test_names); |
24 | let mut rng: Rng = Rng::new(shuffle_seed, extra:test_names_hash); |
25 | shuffle(&mut rng, slice:tests); |
26 | } |
27 | |
28 | // `shuffle` is from `rust-analyzer/src/cli/analysis_stats.rs`. |
29 | fn shuffle<T>(rng: &mut Rng, slice: &mut [T]) { |
30 | for i in 0..slice.len() { |
31 | randomize_first(rng, &mut slice[i..]); |
32 | } |
33 | |
34 | fn randomize_first<T>(rng: &mut Rng, slice: &mut [T]) { |
35 | assert!(!slice.is_empty()); |
36 | let idx: usize = rng.rand_range(0..slice.len() as u64) as usize; |
37 | slice.swap(0, idx); |
38 | } |
39 | } |
40 | |
41 | struct Rng { |
42 | state: u64, |
43 | extra: u64, |
44 | } |
45 | |
46 | impl Rng { |
47 | fn new(seed: u64, extra: u64) -> Self { |
48 | Self { state: seed, extra } |
49 | } |
50 | |
51 | fn rand_range(&mut self, range: core::ops::Range<u64>) -> u64 { |
52 | self.rand_u64() % (range.end - range.start) + range.start |
53 | } |
54 | |
55 | fn rand_u64(&mut self) -> u64 { |
56 | self.state = calculate_hash(&(self.state, self.extra)); |
57 | self.state |
58 | } |
59 | } |
60 | |
61 | // `calculate_hash` is from `core/src/hash/mod.rs`. |
62 | fn calculate_hash<T: core::hash::Hash>(t: &T) -> u64 { |
63 | let mut s = DefaultHasher::new(); |
64 | t.hash(&mut s); |
65 | s.finish() |
66 | } |
67 | |