1pub mod bowl;
5
6pub mod oat;
8
9pub mod region;
11
12#[cfg(test)]
13mod tests {
14 mod bowl {
16 use std::thread;
17
18 use crate::bowl::{Bowl, GenerationBehavior, WrappedBowl};
19 use crate::oat::Oat;
20
21 #[test]
23 fn test_wrapped_bowl_generate() {
24 let wrapped_bowl: WrappedBowl = WrappedBowl::of(1, GenerationBehavior::Normal, None);
26 test_wrapped_bowl_generate_definition(wrapped_bowl)
27 }
28
29 #[test]
31 fn test_wrapped_bowl_generate_lazy() {
32 let wrapped_bowl: WrappedBowl = WrappedBowl::of(1, GenerationBehavior::Lazy, None);
34 test_wrapped_bowl_generate_definition(wrapped_bowl)
35 }
36
37 #[test]
39 fn test_bowl_new_seq_realtime() {
40 let mut bowl: Bowl = Bowl::of(1, GenerationBehavior::Realtime, None);
41
42 let oats: Vec<u16> = (0..10).map(|_| bowl.new_seq()).collect();
44
45 assert!(oats.windows(2).all(|window| window[0] < window[1]));
47 }
48
49 #[test]
51 fn test_wrapped_bowl_in_multi_thread_env() {
52 let wrapped: WrappedBowl = WrappedBowl::of(1, GenerationBehavior::Normal, None);
53 let mut handles = vec![];
54
55 for _ in 0..10 {
56 let clone = wrapped.clone();
57 handles.push(thread::spawn(move || {
58 clone.generate();
59 }));
60 }
61
62 handles.into_iter().for_each(|h| h.join().unwrap());
63 }
64
65 fn test_wrapped_bowl_generate_definition(wrapped_bowl: WrappedBowl) {
67 let oats: Vec<Oat> = (0..4095).map(|_| wrapped_bowl.generate()).collect();
69
70 assert!(oats.iter().all(|oat| oat.node() == 1));
72
73 assert!(oats
75 .windows(2)
76 .all(|window| window[0].seq() < window[1].seq()));
77
78 let oat = wrapped_bowl.generate();
80 assert_eq!(oat.seq(), 0);
81 assert_eq!(oat.node(), 1);
82 assert!(oat.timestamp() > oats.last().unwrap().timestamp())
83 }
84 }
85
86 mod oat {
88 use crate::oat::Oat;
89
90 #[test]
92 fn test_to_string() {
93 let oat = Oat::of(1, 3, 1671800400_000);
94 let s = oat.to_string();
95
96 assert_eq!(s, "X1AwCIGvFTGAA");
97 }
98
99 #[test]
101 fn test_to_bytes() {
102 let oat = Oat::of(1, 3, 1671800400_000);
103 let b: [u8; 9] = oat.to_bytes();
104
105 assert_eq!(b, [1, 0x03, 0x0, 0x88, 0x1A, 0xF1, 0x53, 0x18, 0x0]);
106 }
107
108 #[test]
110 fn test_into_bytes() {
111 let oat = Oat::of(1, 3, 1671800400_000);
112 let b: [u8; 9] = oat.into();
113
114 assert_eq!(b, [1, 0x03, 0x0, 0x88, 0x1A, 0xF1, 0x53, 0x18, 0x0]);
115 }
116
117 #[test]
119 fn test_from_string() {
120 let oat = Oat::from_string("X1AwCIGvFTGAA").unwrap();
121
122 assert_eq!(oat.node(), 1);
123 assert_eq!(oat.seq(), 3);
124 assert_eq!(oat.timestamp(), 1671800400_000);
125 }
126
127 #[test]
129 fn test_from_string_unchecked() {
130 let oat = Oat::from_string_unchecked("X1AwCIGvFTGAA");
131
132 assert_eq!(oat.node(), 1);
133 assert_eq!(oat.seq(), 3);
134 assert_eq!(oat.timestamp(), 1671800400_000);
135 }
136
137 #[test]
139 fn test_from_bytes() {
140 let oat = Oat::from_bytes([1, 0x03, 0x0, 0x88, 0x1A, 0xF1, 0x53, 0x18, 0x0]);
141
142 assert_eq!(oat.node(), 1);
143 assert_eq!(oat.seq(), 3);
144 assert_eq!(oat.timestamp(), 1671800400_000);
145 }
146
147 #[test]
149 fn test_from_bytes_ref() {
150 let oat =
151 Oat::from_bytes_ref(&[1, 0x03, 0x0, 0x88, 0x1A, 0xF1, 0x53, 0x18, 0x0]).unwrap();
152
153 assert_eq!(oat.node(), 1);
154 assert_eq!(oat.seq(), 3);
155 assert_eq!(oat.timestamp(), 1671800400_000);
156 }
157
158 #[test]
160 fn test_from_bytes_ref_invalid_length() {
161 let oat = Oat::from_bytes_ref(&[1, 0x03, 0x0, 0x88, 0x1A, 0xF1, 0x53, 0x18]);
162
163 assert!(oat.is_err());
164 assert_eq!(
165 oat.err().unwrap(),
166 crate::oat::ParseOatError::InvalidLUIDLength(8)
167 );
168 }
169
170 #[test]
171 #[should_panic]
172 fn test_of_invalid_seq_length() {
173 let oat = Oat::of(1, 1 << 12, 0);
174 assert_eq!(oat.node(), 1);
175 assert_eq!(oat.seq(), 0x1000);
176 assert_eq!(oat.timestamp(), 0);
177 }
178
179 #[test]
180 #[should_panic]
181 fn test_of_invalid_timestamp_length() {
182 let oat = Oat::of(1, 0xFF, 1 << 44);
183 assert_eq!(oat.node(), 1);
184 assert_eq!(oat.seq(), 0x1000);
185 assert_eq!(oat.timestamp(), 0);
186 }
187
188 }
189}