Auto merge of #48549 - alexcrichton:update-cargo, r=Mark-Simulacrum
Update Cargo submodule Hopefully a routine update...
This commit is contained in:
commit
178becdd7c
712
src/Cargo.lock
generated
712
src/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -759,7 +759,9 @@ impl<'a> Builder<'a> {
|
|||||||
// be resolved because MinGW has the import library. The downside is we
|
// be resolved because MinGW has the import library. The downside is we
|
||||||
// don't get newer functions from Windows, but we don't use any of them
|
// don't get newer functions from Windows, but we don't use any of them
|
||||||
// anyway.
|
// anyway.
|
||||||
|
if mode != Mode::Tool {
|
||||||
cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
|
cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
|
||||||
|
}
|
||||||
|
|
||||||
if self.is_very_verbose() {
|
if self.is_very_verbose() {
|
||||||
cargo.arg("-v");
|
cargo.arg("-v");
|
||||||
|
@ -12,7 +12,7 @@ core = { path = "../libcore" }
|
|||||||
std_unicode = { path = "../libstd_unicode" }
|
std_unicode = { path = "../libstd_unicode" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.3"
|
rand = "0.4"
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "collectionstests"
|
name = "collectionstests"
|
||||||
|
@ -8,9 +8,13 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::panic;
|
use std::cmp;
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
use std::collections::binary_heap::{Drain, PeekMut};
|
use std::collections::binary_heap::{Drain, PeekMut};
|
||||||
|
use std::panic::{self, AssertUnwindSafe};
|
||||||
|
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||||
|
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator() {
|
fn test_iterator() {
|
||||||
@ -300,3 +304,80 @@ fn assert_covariance() {
|
|||||||
d
|
d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// old binaryheap failed this test
|
||||||
|
//
|
||||||
|
// Integrity means that all elements are present after a comparison panics,
|
||||||
|
// even if the order may not be correct.
|
||||||
|
//
|
||||||
|
// Destructors must be called exactly once per element.
|
||||||
|
#[test]
|
||||||
|
fn panic_safe() {
|
||||||
|
static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Ord, Clone, Debug)]
|
||||||
|
struct PanicOrd<T>(T, bool);
|
||||||
|
|
||||||
|
impl<T> Drop for PanicOrd<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// update global drop count
|
||||||
|
DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: PartialOrd> PartialOrd for PanicOrd<T> {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||||
|
if self.1 || other.1 {
|
||||||
|
panic!("Panicking comparison");
|
||||||
|
}
|
||||||
|
self.0.partial_cmp(&other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
const DATASZ: usize = 32;
|
||||||
|
const NTEST: usize = 10;
|
||||||
|
|
||||||
|
// don't use 0 in the data -- we want to catch the zeroed-out case.
|
||||||
|
let data = (1..DATASZ + 1).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// since it's a fuzzy test, run several tries.
|
||||||
|
for _ in 0..NTEST {
|
||||||
|
for i in 1..DATASZ + 1 {
|
||||||
|
DROP_COUNTER.store(0, Ordering::SeqCst);
|
||||||
|
|
||||||
|
let mut panic_ords: Vec<_> = data.iter()
|
||||||
|
.filter(|&&x| x != i)
|
||||||
|
.map(|&x| PanicOrd(x, false))
|
||||||
|
.collect();
|
||||||
|
let panic_item = PanicOrd(i, true);
|
||||||
|
|
||||||
|
// heapify the sane items
|
||||||
|
rng.shuffle(&mut panic_ords);
|
||||||
|
let mut heap = BinaryHeap::from(panic_ords);
|
||||||
|
let inner_data;
|
||||||
|
|
||||||
|
{
|
||||||
|
// push the panicking item to the heap and catch the panic
|
||||||
|
let thread_result = {
|
||||||
|
let mut heap_ref = AssertUnwindSafe(&mut heap);
|
||||||
|
panic::catch_unwind(move || {
|
||||||
|
heap_ref.push(panic_item);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
assert!(thread_result.is_err());
|
||||||
|
|
||||||
|
// Assert no elements were dropped
|
||||||
|
let drops = DROP_COUNTER.load(Ordering::SeqCst);
|
||||||
|
assert!(drops == 0, "Must not drop items. drops={}", drops);
|
||||||
|
inner_data = heap.clone().into_vec();
|
||||||
|
drop(heap);
|
||||||
|
}
|
||||||
|
let drops = DROP_COUNTER.load(Ordering::SeqCst);
|
||||||
|
assert_eq!(drops, DATASZ);
|
||||||
|
|
||||||
|
let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::<Vec<_>>();
|
||||||
|
data_sorted.sort();
|
||||||
|
assert_eq!(data_sorted, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,9 +8,15 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::panic;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
|
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
use rand::{Rng, thread_rng};
|
use rand::{Rng, thread_rng};
|
||||||
|
|
||||||
@ -1341,3 +1347,162 @@ fn test_copy_from_slice_dst_shorter() {
|
|||||||
let mut dst = [0; 3];
|
let mut dst = [0; 3];
|
||||||
dst.copy_from_slice(&src);
|
dst.copy_from_slice(&src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_LEN: usize = 80;
|
||||||
|
|
||||||
|
static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
|
||||||
|
// FIXME #5244: AtomicUsize is not Copy.
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
||||||
|
];
|
||||||
|
|
||||||
|
static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||||
|
|
||||||
|
#[derive(Clone, Eq)]
|
||||||
|
struct DropCounter {
|
||||||
|
x: u32,
|
||||||
|
id: usize,
|
||||||
|
version: Cell<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DropCounter {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.partial_cmp(other) == Some(Ordering::Equal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for DropCounter {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
self.version.set(self.version.get() + 1);
|
||||||
|
other.version.set(other.version.get() + 1);
|
||||||
|
VERSIONS.fetch_add(2, Relaxed);
|
||||||
|
self.x.partial_cmp(&other.x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for DropCounter {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.partial_cmp(other).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DropCounter {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
DROP_COUNTS[self.id].fetch_add(1, Relaxed);
|
||||||
|
VERSIONS.fetch_sub(self.version.get(), Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test {
|
||||||
|
($input:ident, $func:ident) => {
|
||||||
|
let len = $input.len();
|
||||||
|
|
||||||
|
// Work out the total number of comparisons required to sort
|
||||||
|
// this array...
|
||||||
|
let mut count = 0usize;
|
||||||
|
$input.to_owned().$func(|a, b| { count += 1; a.cmp(b) });
|
||||||
|
|
||||||
|
// ... and then panic on each and every single one.
|
||||||
|
for panic_countdown in 0..count {
|
||||||
|
// Refresh the counters.
|
||||||
|
VERSIONS.store(0, Relaxed);
|
||||||
|
for i in 0..len {
|
||||||
|
DROP_COUNTS[i].store(0, Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
let v = $input.to_owned();
|
||||||
|
let _ = thread::spawn(move || {
|
||||||
|
let mut v = v;
|
||||||
|
let mut panic_countdown = panic_countdown;
|
||||||
|
v.$func(|a, b| {
|
||||||
|
if panic_countdown == 0 {
|
||||||
|
SILENCE_PANIC.with(|s| s.set(true));
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
panic_countdown -= 1;
|
||||||
|
a.cmp(b)
|
||||||
|
})
|
||||||
|
}).join();
|
||||||
|
|
||||||
|
// Check that the number of things dropped is exactly
|
||||||
|
// what we expect (i.e. the contents of `v`).
|
||||||
|
for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
|
||||||
|
let count = c.load(Relaxed);
|
||||||
|
assert!(count == 1,
|
||||||
|
"found drop count == {} for i == {}, len == {}",
|
||||||
|
count, i, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the most recent versions of values were dropped.
|
||||||
|
assert_eq!(VERSIONS.load(Relaxed), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(target_os = "emscripten", ignore)] // no threads
|
||||||
|
fn panic_safe() {
|
||||||
|
let prev = panic::take_hook();
|
||||||
|
panic::set_hook(Box::new(move |info| {
|
||||||
|
if !SILENCE_PANIC.with(|s| s.get()) {
|
||||||
|
prev(info);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
|
for len in (1..20).chain(70..MAX_LEN) {
|
||||||
|
for &modulus in &[5, 20, 50] {
|
||||||
|
for &has_runs in &[false, true] {
|
||||||
|
let mut input = (0..len)
|
||||||
|
.map(|id| {
|
||||||
|
DropCounter {
|
||||||
|
x: rng.next_u32() % modulus,
|
||||||
|
id: id,
|
||||||
|
version: Cell::new(0),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if has_runs {
|
||||||
|
for c in &mut input {
|
||||||
|
c.x = c.id as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..5 {
|
||||||
|
let a = rng.gen::<usize>() % len;
|
||||||
|
let b = rng.gen::<usize>() % len;
|
||||||
|
if a < b {
|
||||||
|
input[a..b].reverse();
|
||||||
|
} else {
|
||||||
|
input.swap(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test!(input, sort_by);
|
||||||
|
test!(input, sort_unstable_by);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,3 +16,6 @@ path = "../libcore/tests/lib.rs"
|
|||||||
[[bench]]
|
[[bench]]
|
||||||
name = "corebenches"
|
name = "corebenches"
|
||||||
path = "../libcore/benches/lib.rs"
|
path = "../libcore/benches/lib.rs"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
rand = "0.4"
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
extern crate rand;
|
||||||
|
|
||||||
mod any;
|
mod any;
|
||||||
mod array;
|
mod array;
|
||||||
|
@ -23,6 +23,7 @@ mod strategy {
|
|||||||
mod dragon;
|
mod dragon;
|
||||||
mod grisu;
|
mod grisu;
|
||||||
}
|
}
|
||||||
|
mod random;
|
||||||
|
|
||||||
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
|
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
|
||||||
match decode(v).1 {
|
match decode(v).1 {
|
||||||
|
@ -8,12 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags:--test
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
|
|
||||||
#![feature(rustc_private, flt2dec)]
|
|
||||||
|
|
||||||
extern crate core;
|
|
||||||
extern crate rand;
|
|
||||||
|
|
||||||
use std::i16;
|
use std::i16;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -24,8 +19,9 @@ use core::num::flt2dec::strategy::grisu::format_exact_opt;
|
|||||||
use core::num::flt2dec::strategy::grisu::format_shortest_opt;
|
use core::num::flt2dec::strategy::grisu::format_shortest_opt;
|
||||||
use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
|
use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded};
|
||||||
|
|
||||||
use rand::{Rand, XorShiftRng};
|
use rand::{self, Rand, XorShiftRng};
|
||||||
use rand::distributions::{IndependentSample, Range};
|
use rand::distributions::{IndependentSample, Range};
|
||||||
|
|
||||||
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
|
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
|
||||||
match decode(v).1 {
|
match decode(v).1 {
|
||||||
FullDecoded::Finite(decoded) => decoded,
|
FullDecoded::Finite(decoded) => decoded,
|
||||||
@ -161,3 +157,4 @@ fn exact_f64_random_equivalence_test() {
|
|||||||
|d, buf| fallback(d, buf, i16::MIN), k, 1_000);
|
|d, buf| fallback(d, buf, i16::MIN), k, 1_000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
use core::result::Result::{Ok, Err};
|
use core::result::Result::{Ok, Err};
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_position() {
|
fn test_position() {
|
||||||
let b = [1, 2, 3, 5, 5];
|
let b = [1, 2, 3, 5, 5];
|
||||||
@ -481,3 +480,73 @@ fn test_rotate_right() {
|
|||||||
assert_eq!(a[(i + 42) % N], i);
|
assert_eq!(a[(i + 42) % N], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
fn sort_unstable() {
|
||||||
|
use core::cmp::Ordering::{Equal, Greater, Less};
|
||||||
|
use core::slice::heapsort;
|
||||||
|
use rand::{Rng, XorShiftRng};
|
||||||
|
|
||||||
|
let mut v = [0; 600];
|
||||||
|
let mut tmp = [0; 600];
|
||||||
|
let mut rng = XorShiftRng::new_unseeded();
|
||||||
|
|
||||||
|
for len in (2..25).chain(500..510) {
|
||||||
|
let v = &mut v[0..len];
|
||||||
|
let tmp = &mut tmp[0..len];
|
||||||
|
|
||||||
|
for &modulus in &[5, 10, 100, 1000] {
|
||||||
|
for _ in 0..100 {
|
||||||
|
for i in 0..len {
|
||||||
|
v[i] = rng.gen::<i32>() % modulus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort in default order.
|
||||||
|
tmp.copy_from_slice(v);
|
||||||
|
tmp.sort_unstable();
|
||||||
|
assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
|
||||||
|
|
||||||
|
// Sort in ascending order.
|
||||||
|
tmp.copy_from_slice(v);
|
||||||
|
tmp.sort_unstable_by(|a, b| a.cmp(b));
|
||||||
|
assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
|
||||||
|
|
||||||
|
// Sort in descending order.
|
||||||
|
tmp.copy_from_slice(v);
|
||||||
|
tmp.sort_unstable_by(|a, b| b.cmp(a));
|
||||||
|
assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
|
||||||
|
|
||||||
|
// Test heapsort using `<` operator.
|
||||||
|
tmp.copy_from_slice(v);
|
||||||
|
heapsort(tmp, |a, b| a < b);
|
||||||
|
assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
|
||||||
|
|
||||||
|
// Test heapsort using `>` operator.
|
||||||
|
tmp.copy_from_slice(v);
|
||||||
|
heapsort(tmp, |a, b| a > b);
|
||||||
|
assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort using a completely random comparison function.
|
||||||
|
// This will reorder the elements *somehow*, but won't panic.
|
||||||
|
for i in 0..v.len() {
|
||||||
|
v[i] = i as i32;
|
||||||
|
}
|
||||||
|
v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
|
||||||
|
v.sort_unstable();
|
||||||
|
for i in 0..v.len() {
|
||||||
|
assert_eq!(v[i], i as i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should not panic.
|
||||||
|
[0i32; 0].sort_unstable();
|
||||||
|
[(); 10].sort_unstable();
|
||||||
|
[(); 100].sort_unstable();
|
||||||
|
|
||||||
|
let mut v = [0xDEADBEEFu64];
|
||||||
|
v.sort_unstable();
|
||||||
|
assert!(v == [0xDEADBEEF]);
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ std_unicode = { path = "../libstd_unicode" }
|
|||||||
unwind = { path = "../libunwind" }
|
unwind = { path = "../libunwind" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.3"
|
rand = "0.4"
|
||||||
|
|
||||||
[target.x86_64-apple-darwin.dependencies]
|
[target.x86_64-apple-darwin.dependencies]
|
||||||
rustc_asan = { path = "../librustc_asan" }
|
rustc_asan = { path = "../librustc_asan" }
|
||||||
|
@ -8,10 +8,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: --test
|
|
||||||
|
|
||||||
#![feature(rustc_private, std_panic)]
|
|
||||||
|
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
use std::env::*;
|
use std::env::*;
|
@ -1,101 +0,0 @@
|
|||||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
#![feature(rustc_private, std_panic)]
|
|
||||||
|
|
||||||
extern crate rand;
|
|
||||||
|
|
||||||
use rand::{thread_rng, Rng};
|
|
||||||
use std::panic::{self, AssertUnwindSafe};
|
|
||||||
|
|
||||||
use std::collections::BinaryHeap;
|
|
||||||
use std::cmp;
|
|
||||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
|
||||||
|
|
||||||
static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
|
|
||||||
|
|
||||||
// old binaryheap failed this test
|
|
||||||
//
|
|
||||||
// Integrity means that all elements are present after a comparison panics,
|
|
||||||
// even if the order may not be correct.
|
|
||||||
//
|
|
||||||
// Destructors must be called exactly once per element.
|
|
||||||
fn test_integrity() {
|
|
||||||
#[derive(Eq, PartialEq, Ord, Clone, Debug)]
|
|
||||||
struct PanicOrd<T>(T, bool);
|
|
||||||
|
|
||||||
impl<T> Drop for PanicOrd<T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// update global drop count
|
|
||||||
DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialOrd> PartialOrd for PanicOrd<T> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
||||||
if self.1 || other.1 {
|
|
||||||
panic!("Panicking comparison");
|
|
||||||
}
|
|
||||||
self.0.partial_cmp(&other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
const DATASZ: usize = 32;
|
|
||||||
const NTEST: usize = 10;
|
|
||||||
|
|
||||||
// don't use 0 in the data -- we want to catch the zeroed-out case.
|
|
||||||
let data = (1..DATASZ + 1).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// since it's a fuzzy test, run several tries.
|
|
||||||
for _ in 0..NTEST {
|
|
||||||
for i in 1..DATASZ + 1 {
|
|
||||||
DROP_COUNTER.store(0, Ordering::SeqCst);
|
|
||||||
|
|
||||||
let mut panic_ords: Vec<_> = data.iter()
|
|
||||||
.filter(|&&x| x != i)
|
|
||||||
.map(|&x| PanicOrd(x, false))
|
|
||||||
.collect();
|
|
||||||
let panic_item = PanicOrd(i, true);
|
|
||||||
|
|
||||||
// heapify the sane items
|
|
||||||
rng.shuffle(&mut panic_ords);
|
|
||||||
let mut heap = BinaryHeap::from(panic_ords);
|
|
||||||
let inner_data;
|
|
||||||
|
|
||||||
{
|
|
||||||
// push the panicking item to the heap and catch the panic
|
|
||||||
let thread_result = {
|
|
||||||
let mut heap_ref = AssertUnwindSafe(&mut heap);
|
|
||||||
panic::catch_unwind(move || {
|
|
||||||
heap_ref.push(panic_item);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
assert!(thread_result.is_err());
|
|
||||||
|
|
||||||
// Assert no elements were dropped
|
|
||||||
let drops = DROP_COUNTER.load(Ordering::SeqCst);
|
|
||||||
assert!(drops == 0, "Must not drop items. drops={}", drops);
|
|
||||||
inner_data = heap.clone().into_vec();
|
|
||||||
drop(heap);
|
|
||||||
}
|
|
||||||
let drops = DROP_COUNTER.load(Ordering::SeqCst);
|
|
||||||
assert_eq!(drops, DATASZ);
|
|
||||||
|
|
||||||
let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::<Vec<_>>();
|
|
||||||
data_sorted.sort();
|
|
||||||
assert_eq!(data_sorted, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
test_integrity();
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
|||||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
#![feature(rustc_private, sort_internals)]
|
|
||||||
|
|
||||||
extern crate core;
|
|
||||||
extern crate rand;
|
|
||||||
|
|
||||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
|
||||||
use core::slice::heapsort;
|
|
||||||
|
|
||||||
use rand::{Rng, XorShiftRng};
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut v = [0; 600];
|
|
||||||
let mut tmp = [0; 600];
|
|
||||||
let mut rng = XorShiftRng::new_unseeded();
|
|
||||||
|
|
||||||
for len in (2..25).chain(500..510) {
|
|
||||||
let v = &mut v[0..len];
|
|
||||||
let tmp = &mut tmp[0..len];
|
|
||||||
|
|
||||||
for &modulus in &[5, 10, 100, 1000] {
|
|
||||||
for _ in 0..100 {
|
|
||||||
for i in 0..len {
|
|
||||||
v[i] = rng.gen::<i32>() % modulus;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort in default order.
|
|
||||||
tmp.copy_from_slice(v);
|
|
||||||
tmp.sort_unstable();
|
|
||||||
assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
|
|
||||||
|
|
||||||
// Sort in ascending order.
|
|
||||||
tmp.copy_from_slice(v);
|
|
||||||
tmp.sort_unstable_by(|a, b| a.cmp(b));
|
|
||||||
assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
|
|
||||||
|
|
||||||
// Sort in descending order.
|
|
||||||
tmp.copy_from_slice(v);
|
|
||||||
tmp.sort_unstable_by(|a, b| b.cmp(a));
|
|
||||||
assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
|
|
||||||
|
|
||||||
// Test heapsort using `<` operator.
|
|
||||||
tmp.copy_from_slice(v);
|
|
||||||
heapsort(tmp, |a, b| a < b);
|
|
||||||
assert!(tmp.windows(2).all(|w| w[0] <= w[1]));
|
|
||||||
|
|
||||||
// Test heapsort using `>` operator.
|
|
||||||
tmp.copy_from_slice(v);
|
|
||||||
heapsort(tmp, |a, b| a > b);
|
|
||||||
assert!(tmp.windows(2).all(|w| w[0] >= w[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort using a completely random comparison function.
|
|
||||||
// This will reorder the elements *somehow*, but won't panic.
|
|
||||||
for i in 0..v.len() {
|
|
||||||
v[i] = i as i32;
|
|
||||||
}
|
|
||||||
v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap());
|
|
||||||
v.sort_unstable();
|
|
||||||
for i in 0..v.len() {
|
|
||||||
assert_eq!(v[i], i as i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should not panic.
|
|
||||||
[0i32; 0].sort_unstable();
|
|
||||||
[(); 10].sort_unstable();
|
|
||||||
[(); 100].sort_unstable();
|
|
||||||
|
|
||||||
let mut v = [0xDEADBEEFu64];
|
|
||||||
v.sort_unstable();
|
|
||||||
assert!(v == [0xDEADBEEF]);
|
|
||||||
}
|
|
@ -1,181 +0,0 @@
|
|||||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
// ignore-emscripten no threads support
|
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
|
||||||
#![feature(sort_unstable)]
|
|
||||||
|
|
||||||
extern crate rand;
|
|
||||||
|
|
||||||
use rand::{thread_rng, Rng};
|
|
||||||
use std::cell::Cell;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::panic;
|
|
||||||
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize};
|
|
||||||
use std::sync::atomic::Ordering::Relaxed;
|
|
||||||
use std::thread;
|
|
||||||
|
|
||||||
const MAX_LEN: usize = 80;
|
|
||||||
|
|
||||||
static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
|
|
||||||
// FIXME #5244: AtomicUsize is not Copy.
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
|
|
||||||
];
|
|
||||||
|
|
||||||
static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT;
|
|
||||||
|
|
||||||
#[derive(Clone, Eq)]
|
|
||||||
struct DropCounter {
|
|
||||||
x: u32,
|
|
||||||
id: usize,
|
|
||||||
version: Cell<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for DropCounter {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.partial_cmp(other) == Some(Ordering::Equal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for DropCounter {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
self.version.set(self.version.get() + 1);
|
|
||||||
other.version.set(other.version.get() + 1);
|
|
||||||
VERSIONS.fetch_add(2, Relaxed);
|
|
||||||
self.x.partial_cmp(&other.x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for DropCounter {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
self.partial_cmp(other).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for DropCounter {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
DROP_COUNTS[self.id].fetch_add(1, Relaxed);
|
|
||||||
VERSIONS.fetch_sub(self.version.get(), Relaxed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test {
|
|
||||||
($input:ident, $func:ident) => {
|
|
||||||
let len = $input.len();
|
|
||||||
|
|
||||||
// Work out the total number of comparisons required to sort
|
|
||||||
// this array...
|
|
||||||
let mut count = 0usize;
|
|
||||||
$input.to_owned().$func(|a, b| { count += 1; a.cmp(b) });
|
|
||||||
|
|
||||||
// ... and then panic on each and every single one.
|
|
||||||
for panic_countdown in 0..count {
|
|
||||||
// Refresh the counters.
|
|
||||||
VERSIONS.store(0, Relaxed);
|
|
||||||
for i in 0..len {
|
|
||||||
DROP_COUNTS[i].store(0, Relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
let v = $input.to_owned();
|
|
||||||
let _ = thread::spawn(move || {
|
|
||||||
let mut v = v;
|
|
||||||
let mut panic_countdown = panic_countdown;
|
|
||||||
v.$func(|a, b| {
|
|
||||||
if panic_countdown == 0 {
|
|
||||||
SILENCE_PANIC.with(|s| s.set(true));
|
|
||||||
panic!();
|
|
||||||
}
|
|
||||||
panic_countdown -= 1;
|
|
||||||
a.cmp(b)
|
|
||||||
})
|
|
||||||
}).join();
|
|
||||||
|
|
||||||
// Check that the number of things dropped is exactly
|
|
||||||
// what we expect (i.e. the contents of `v`).
|
|
||||||
for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
|
|
||||||
let count = c.load(Relaxed);
|
|
||||||
assert!(count == 1,
|
|
||||||
"found drop count == {} for i == {}, len == {}",
|
|
||||||
count, i, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the most recent versions of values were dropped.
|
|
||||||
assert_eq!(VERSIONS.load(Relaxed), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let prev = panic::take_hook();
|
|
||||||
panic::set_hook(Box::new(move |info| {
|
|
||||||
if !SILENCE_PANIC.with(|s| s.get()) {
|
|
||||||
prev(info);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
|
|
||||||
for len in (1..20).chain(70..MAX_LEN) {
|
|
||||||
for &modulus in &[5, 20, 50] {
|
|
||||||
for &has_runs in &[false, true] {
|
|
||||||
let mut input = (0..len)
|
|
||||||
.map(|id| {
|
|
||||||
DropCounter {
|
|
||||||
x: rng.next_u32() % modulus,
|
|
||||||
id: id,
|
|
||||||
version: Cell::new(0),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if has_runs {
|
|
||||||
for c in &mut input {
|
|
||||||
c.x = c.id as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
for _ in 0..5 {
|
|
||||||
let a = rng.gen::<usize>() % len;
|
|
||||||
let b = rng.gen::<usize>() % len;
|
|
||||||
if a < b {
|
|
||||||
input[a..b].reverse();
|
|
||||||
} else {
|
|
||||||
input.swap(a, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test!(input, sort_by);
|
|
||||||
test!(input, sort_unstable_by);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +1 @@
|
|||||||
Subproject commit 1d6dfea44f97199d5d5c177c7dadcde393eaff9a
|
Subproject commit 5f83bb4044f32b60d06717c609610f67411fc671
|
@ -91,6 +91,7 @@ static WHITELIST: &'static [Crate] = &[
|
|||||||
Crate("redox_termios"),
|
Crate("redox_termios"),
|
||||||
Crate("regex"),
|
Crate("regex"),
|
||||||
Crate("regex-syntax"),
|
Crate("regex-syntax"),
|
||||||
|
Crate("remove_dir_all"),
|
||||||
Crate("rustc-demangle"),
|
Crate("rustc-demangle"),
|
||||||
Crate("smallvec"),
|
Crate("smallvec"),
|
||||||
Crate("stable_deref_trait"),
|
Crate("stable_deref_trait"),
|
||||||
@ -99,6 +100,7 @@ static WHITELIST: &'static [Crate] = &[
|
|||||||
Crate("terminon"),
|
Crate("terminon"),
|
||||||
Crate("termion"),
|
Crate("termion"),
|
||||||
Crate("thread_local"),
|
Crate("thread_local"),
|
||||||
|
Crate("ucd-util"),
|
||||||
Crate("unicode-width"),
|
Crate("unicode-width"),
|
||||||
Crate("unreachable"),
|
Crate("unreachable"),
|
||||||
Crate("utf8-ranges"),
|
Crate("utf8-ranges"),
|
||||||
|
Loading…
Reference in New Issue
Block a user