1 use crate::RingBuffer;
2 use core::sync::atomic::Ordering;
3 #[cfg(feature = "std")]
4 use std::thread;
5
head_tail<T>(rb: &RingBuffer<T>) -> (usize, usize)6 fn head_tail<T>(rb: &RingBuffer<T>) -> (usize, usize) {
7 (
8 rb.head.load(Ordering::Acquire),
9 rb.tail.load(Ordering::Acquire),
10 )
11 }
12
13 #[test]
capacity()14 fn capacity() {
15 let cap = 13;
16 let buf = RingBuffer::<i32>::new(cap);
17 assert_eq!(buf.capacity(), cap);
18 }
19 #[test]
split_capacity()20 fn split_capacity() {
21 let cap = 13;
22 let buf = RingBuffer::<i32>::new(cap);
23 let (prod, cons) = buf.split();
24
25 assert_eq!(prod.capacity(), cap);
26 assert_eq!(cons.capacity(), cap);
27 }
28
29 #[cfg(feature = "std")]
30 #[test]
split_threads()31 fn split_threads() {
32 let buf = RingBuffer::<i32>::new(10);
33 let (prod, cons) = buf.split();
34
35 let pjh = thread::spawn(move || {
36 let _ = prod;
37 });
38
39 let cjh = thread::spawn(move || {
40 let _ = cons;
41 });
42
43 pjh.join().unwrap();
44 cjh.join().unwrap();
45 }
46
47 #[test]
push()48 fn push() {
49 let cap = 2;
50 let buf = RingBuffer::<i32>::new(cap);
51 let (mut prod, _) = buf.split();
52
53 assert_eq!(head_tail(&prod.rb), (0, 0));
54
55 assert_eq!(prod.push(123), Ok(()));
56 assert_eq!(head_tail(&prod.rb), (0, 1));
57
58 assert_eq!(prod.push(234), Ok(()));
59 assert_eq!(head_tail(&prod.rb), (0, 2));
60
61 assert_eq!(prod.push(345), Err(345));
62 assert_eq!(head_tail(&prod.rb), (0, 2));
63 }
64
65 #[test]
pop_empty()66 fn pop_empty() {
67 let cap = 2;
68 let buf = RingBuffer::<i32>::new(cap);
69 let (_, mut cons) = buf.split();
70
71 assert_eq!(head_tail(&cons.rb), (0, 0));
72
73 assert_eq!(cons.pop(), None);
74 assert_eq!(head_tail(&cons.rb), (0, 0));
75 }
76
77 #[test]
push_pop_one()78 fn push_pop_one() {
79 let cap = 2;
80 let buf = RingBuffer::<i32>::new(cap);
81 let (mut prod, mut cons) = buf.split();
82
83 let vcap = cap + 1;
84 let values = [12, 34, 56, 78, 90];
85 assert_eq!(head_tail(&cons.rb), (0, 0));
86
87 for (i, v) in values.iter().enumerate() {
88 assert_eq!(prod.push(*v), Ok(()));
89 assert_eq!(head_tail(&cons.rb), (i % vcap, (i + 1) % vcap));
90
91 assert_eq!(cons.pop().unwrap(), *v);
92 assert_eq!(head_tail(&cons.rb), ((i + 1) % vcap, (i + 1) % vcap));
93
94 assert_eq!(cons.pop(), None);
95 assert_eq!(head_tail(&cons.rb), ((i + 1) % vcap, (i + 1) % vcap));
96 }
97 }
98
99 #[test]
push_pop_all()100 fn push_pop_all() {
101 let cap = 2;
102 let buf = RingBuffer::<i32>::new(cap);
103 let (mut prod, mut cons) = buf.split();
104
105 let vcap = cap + 1;
106 let values = [(12, 34, 13), (56, 78, 57), (90, 10, 91)];
107 assert_eq!(head_tail(&cons.rb), (0, 0));
108
109 for (i, v) in values.iter().enumerate() {
110 assert_eq!(prod.push(v.0), Ok(()));
111 assert_eq!(head_tail(&cons.rb), (cap * i % vcap, (cap * i + 1) % vcap));
112
113 assert_eq!(prod.push(v.1), Ok(()));
114 assert_eq!(head_tail(&cons.rb), (cap * i % vcap, (cap * i + 2) % vcap));
115
116 assert_eq!(prod.push(v.2).unwrap_err(), v.2);
117 assert_eq!(head_tail(&cons.rb), (cap * i % vcap, (cap * i + 2) % vcap));
118
119 assert_eq!(cons.pop().unwrap(), v.0);
120 assert_eq!(
121 head_tail(&cons.rb),
122 ((cap * i + 1) % vcap, (cap * i + 2) % vcap)
123 );
124
125 assert_eq!(cons.pop().unwrap(), v.1);
126 assert_eq!(
127 head_tail(&cons.rb),
128 ((cap * i + 2) % vcap, (cap * i + 2) % vcap)
129 );
130
131 assert_eq!(cons.pop(), None);
132 assert_eq!(
133 head_tail(&cons.rb),
134 ((cap * i + 2) % vcap, (cap * i + 2) % vcap)
135 );
136 }
137 }
138
139 #[test]
empty_full()140 fn empty_full() {
141 let buf = RingBuffer::<i32>::new(1);
142 let (mut prod, cons) = buf.split();
143
144 assert!(prod.is_empty());
145 assert!(cons.is_empty());
146 assert!(!prod.is_full());
147 assert!(!cons.is_full());
148
149 assert_eq!(prod.push(123), Ok(()));
150
151 assert!(!prod.is_empty());
152 assert!(!cons.is_empty());
153 assert!(prod.is_full());
154 assert!(cons.is_full());
155 }
156
157 #[test]
len_remaining()158 fn len_remaining() {
159 let buf = RingBuffer::<i32>::new(2);
160 let (mut prod, mut cons) = buf.split();
161
162 assert_eq!(prod.len(), 0);
163 assert_eq!(cons.len(), 0);
164 assert_eq!(prod.remaining(), 2);
165 assert_eq!(cons.remaining(), 2);
166
167 assert_eq!(prod.push(123), Ok(()));
168
169 assert_eq!(prod.len(), 1);
170 assert_eq!(cons.len(), 1);
171 assert_eq!(prod.remaining(), 1);
172 assert_eq!(cons.remaining(), 1);
173
174 assert_eq!(prod.push(456), Ok(()));
175
176 assert_eq!(prod.len(), 2);
177 assert_eq!(cons.len(), 2);
178 assert_eq!(prod.remaining(), 0);
179 assert_eq!(cons.remaining(), 0);
180
181 assert_eq!(cons.pop(), Some(123));
182
183 assert_eq!(prod.len(), 1);
184 assert_eq!(cons.len(), 1);
185 assert_eq!(prod.remaining(), 1);
186 assert_eq!(cons.remaining(), 1);
187
188 assert_eq!(cons.pop(), Some(456));
189
190 assert_eq!(prod.len(), 0);
191 assert_eq!(cons.len(), 0);
192 assert_eq!(prod.remaining(), 2);
193 assert_eq!(cons.remaining(), 2);
194
195 // now head is at 2, so tail will be at 0. This caught an overflow error
196 // when tail+1 < head because of the substraction of usize.
197 assert_eq!(prod.push(789), Ok(()));
198
199 assert_eq!(prod.len(), 1);
200 assert_eq!(cons.len(), 1);
201 assert_eq!(prod.remaining(), 1);
202 assert_eq!(cons.remaining(), 1);
203 }
204