Skip to content

Commit 4ac0962

Browse files
bors[bot]japaricfinnbear
authored
Merge #316 #317
316: speed up cargo miri test r=japaric a=japaric by making some "exhaustive" tests less exhaustive 317: impl {Clone, PartialEq} for HistoryBuffer {...} r=japaric a=finnbear - `impl Clone for HistoryBuffer` - `impl PartialEq for HistoryBuffer` Both are tested fairly rigorously. Motivation is to use this type in a `yew::Properties` struct, which requires both traits to be implemented. Co-authored-by: Jorge Aparicio <[email protected]> Co-authored-by: Finn Bear <[email protected]>
3 parents 15e47d5 + 4491015 + 5f8bab4 commit 4ac0962

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Added
1111

12+
- Add `Clone` and `PartialEq` implementations to `HistoryBuffer`.
13+
1214
### Changed
1315

1416
- [breaking-change] `IndexMap` and `IndexSet` now require that keys implement the `core::hash::Hash`

src/histbuf.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,21 @@ where
238238
}
239239
}
240240

241+
impl<T, const N: usize> Clone for HistoryBuffer<T, N>
242+
where
243+
T: Clone,
244+
{
245+
fn clone(&self) -> Self {
246+
let mut ret = Self::new();
247+
for (new, old) in ret.data.iter_mut().zip(self.as_slice()) {
248+
new.write(old.clone());
249+
}
250+
ret.filled = self.filled;
251+
ret.write_at = self.write_at;
252+
ret
253+
}
254+
}
255+
241256
impl<T, const N: usize> Drop for HistoryBuffer<T, N> {
242257
fn drop(&mut self) {
243258
unsafe {
@@ -279,6 +294,15 @@ impl<T, const N: usize> Default for HistoryBuffer<T, N> {
279294
}
280295
}
281296

297+
impl<T, const N: usize> PartialEq for HistoryBuffer<T, N>
298+
where
299+
T: PartialEq,
300+
{
301+
fn eq(&self, other: &Self) -> bool {
302+
self.oldest_ordered().eq(other.oldest_ordered())
303+
}
304+
}
305+
282306
/// An iterator on the underlying buffer ordered from oldest data to newest
283307
#[derive(Clone)]
284308
pub struct OldestOrdered<'a, T, const N: usize> {
@@ -311,6 +335,7 @@ impl<'a, T, const N: usize> Iterator for OldestOrdered<'a, T, N> {
311335
mod tests {
312336
use crate::HistoryBuffer;
313337
use core::fmt::Debug;
338+
use core::sync::atomic::{AtomicUsize, Ordering};
314339

315340
#[test]
316341
fn new() {
@@ -350,6 +375,47 @@ mod tests {
350375
assert_eq!(x.as_slice(), [1; 4]);
351376
}
352377

378+
#[test]
379+
fn clone() {
380+
let mut x: HistoryBuffer<u8, 3> = HistoryBuffer::new();
381+
for i in 0..10 {
382+
assert_eq!(x.as_slice(), x.clone().as_slice());
383+
x.write(i);
384+
}
385+
386+
// Records number of clones locally and globally.
387+
static GLOBAL: AtomicUsize = AtomicUsize::new(0);
388+
#[derive(Default, PartialEq, Debug)]
389+
struct InstrumentedClone(usize);
390+
391+
impl Clone for InstrumentedClone {
392+
fn clone(&self) -> Self {
393+
GLOBAL.fetch_add(1, Ordering::Relaxed);
394+
Self(self.0 + 1)
395+
}
396+
}
397+
398+
let mut y: HistoryBuffer<InstrumentedClone, 2> = HistoryBuffer::new();
399+
let _ = y.clone();
400+
assert_eq!(GLOBAL.load(Ordering::Relaxed), 0);
401+
y.write(InstrumentedClone(0));
402+
assert_eq!(GLOBAL.load(Ordering::Relaxed), 0);
403+
assert_eq!(y.clone().as_slice(), [InstrumentedClone(1)]);
404+
assert_eq!(GLOBAL.load(Ordering::Relaxed), 1);
405+
y.write(InstrumentedClone(0));
406+
assert_eq!(GLOBAL.load(Ordering::Relaxed), 1);
407+
assert_eq!(
408+
y.clone().as_slice(),
409+
[InstrumentedClone(1), InstrumentedClone(1)]
410+
);
411+
assert_eq!(GLOBAL.load(Ordering::Relaxed), 3);
412+
assert_eq!(
413+
y.clone().clone().clone().as_slice(),
414+
[InstrumentedClone(3), InstrumentedClone(3)]
415+
);
416+
assert_eq!(GLOBAL.load(Ordering::Relaxed), 9);
417+
}
418+
353419
#[test]
354420
fn recent() {
355421
let mut x: HistoryBuffer<u8, 4> = HistoryBuffer::new();
@@ -430,4 +496,30 @@ mod tests {
430496
}
431497
}
432498
}
499+
500+
#[test]
501+
fn partial_eq() {
502+
let mut x: HistoryBuffer<u8, 3> = HistoryBuffer::new();
503+
let mut y: HistoryBuffer<u8, 3> = HistoryBuffer::new();
504+
assert_eq!(x, y);
505+
x.write(1);
506+
assert_ne!(x, y);
507+
y.write(1);
508+
assert_eq!(x, y);
509+
for _ in 0..4 {
510+
x.write(2);
511+
assert_ne!(x, y);
512+
for i in 0..5 {
513+
x.write(i);
514+
y.write(i);
515+
}
516+
assert_eq!(
517+
x,
518+
y,
519+
"{:?} {:?}",
520+
x.iter().collect::<Vec<_>>(),
521+
y.iter().collect::<Vec<_>>()
522+
);
523+
}
524+
}
433525
}

src/indexmap.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,12 @@ mod tests {
12081208
assert_eq!(a.get("k1"), a.get("k2"));
12091209
}
12101210

1211+
// tests that use this constant take too long to run under miri, specially on CI, with a map of
1212+
// this size so make the map smaller when using miri
1213+
#[cfg(not(miri))]
12111214
const MAP_SLOTS: usize = 4096;
1215+
#[cfg(miri)]
1216+
const MAP_SLOTS: usize = 64;
12121217
fn almost_filled_map() -> FnvIndexMap<usize, usize, MAP_SLOTS> {
12131218
let mut almost_filled = FnvIndexMap::new();
12141219
for i in 1..MAP_SLOTS {

0 commit comments

Comments
 (0)