summaryrefslogtreecommitdiffstats
path: root/vendor/memchr/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/memchr/src/tests')
-rw-r--r--vendor/memchr/src/tests/memchr/iter.rs230
-rw-r--r--vendor/memchr/src/tests/memchr/memchr.rs134
-rw-r--r--vendor/memchr/src/tests/memchr/mod.rs7
-rw-r--r--vendor/memchr/src/tests/memchr/simple.rs23
-rw-r--r--vendor/memchr/src/tests/memchr/testdata.rs351
-rw-r--r--vendor/memchr/src/tests/mod.rs15
-rw-r--r--vendor/memchr/src/tests/x86_64-soft_float.json15
7 files changed, 775 insertions, 0 deletions
diff --git a/vendor/memchr/src/tests/memchr/iter.rs b/vendor/memchr/src/tests/memchr/iter.rs
new file mode 100644
index 000000000..80ea5c279
--- /dev/null
+++ b/vendor/memchr/src/tests/memchr/iter.rs
@@ -0,0 +1,230 @@
+use quickcheck::quickcheck;
+
+use crate::{tests::memchr::testdata::memchr_tests, Memchr, Memchr2, Memchr3};
+
+#[test]
+fn memchr1_iter() {
+ for test in memchr_tests() {
+ test.iter_one(false, Memchr::new);
+ }
+}
+
+#[test]
+fn memchr2_iter() {
+ for test in memchr_tests() {
+ test.iter_two(false, Memchr2::new);
+ }
+}
+
+#[test]
+fn memchr3_iter() {
+ for test in memchr_tests() {
+ test.iter_three(false, Memchr3::new);
+ }
+}
+
+#[test]
+fn memrchr1_iter() {
+ for test in memchr_tests() {
+ test.iter_one(true, |n1, corpus| Memchr::new(n1, corpus).rev());
+ }
+}
+
+#[test]
+fn memrchr2_iter() {
+ for test in memchr_tests() {
+ test.iter_two(true, |n1, n2, corpus| {
+ Memchr2::new(n1, n2, corpus).rev()
+ })
+ }
+}
+
+#[test]
+fn memrchr3_iter() {
+ for test in memchr_tests() {
+ test.iter_three(true, |n1, n2, n3, corpus| {
+ Memchr3::new(n1, n2, n3, corpus).rev()
+ })
+ }
+}
+
+quickcheck! {
+ fn qc_memchr_double_ended_iter(
+ needle: u8, data: Vec<u8>, take_side: Vec<bool>
+ ) -> bool {
+ // make nonempty
+ let mut take_side = take_side;
+ if take_side.is_empty() { take_side.push(true) };
+
+ let iter = Memchr::new(needle, &data);
+ let all_found = double_ended_take(
+ iter, take_side.iter().cycle().cloned());
+
+ all_found.iter().cloned().eq(positions1(needle, &data))
+ }
+
+ fn qc_memchr2_double_ended_iter(
+ needle1: u8, needle2: u8, data: Vec<u8>, take_side: Vec<bool>
+ ) -> bool {
+ // make nonempty
+ let mut take_side = take_side;
+ if take_side.is_empty() { take_side.push(true) };
+
+ let iter = Memchr2::new(needle1, needle2, &data);
+ let all_found = double_ended_take(
+ iter, take_side.iter().cycle().cloned());
+
+ all_found.iter().cloned().eq(positions2(needle1, needle2, &data))
+ }
+
+ fn qc_memchr3_double_ended_iter(
+ needle1: u8, needle2: u8, needle3: u8,
+ data: Vec<u8>, take_side: Vec<bool>
+ ) -> bool {
+ // make nonempty
+ let mut take_side = take_side;
+ if take_side.is_empty() { take_side.push(true) };
+
+ let iter = Memchr3::new(needle1, needle2, needle3, &data);
+ let all_found = double_ended_take(
+ iter, take_side.iter().cycle().cloned());
+
+ all_found
+ .iter()
+ .cloned()
+ .eq(positions3(needle1, needle2, needle3, &data))
+ }
+
+ fn qc_memchr1_iter(data: Vec<u8>) -> bool {
+ let needle = 0;
+ let answer = positions1(needle, &data);
+ answer.eq(Memchr::new(needle, &data))
+ }
+
+ fn qc_memchr1_rev_iter(data: Vec<u8>) -> bool {
+ let needle = 0;
+ let answer = positions1(needle, &data);
+ answer.rev().eq(Memchr::new(needle, &data).rev())
+ }
+
+ fn qc_memchr2_iter(data: Vec<u8>) -> bool {
+ let needle1 = 0;
+ let needle2 = 1;
+ let answer = positions2(needle1, needle2, &data);
+ answer.eq(Memchr2::new(needle1, needle2, &data))
+ }
+
+ fn qc_memchr2_rev_iter(data: Vec<u8>) -> bool {
+ let needle1 = 0;
+ let needle2 = 1;
+ let answer = positions2(needle1, needle2, &data);
+ answer.rev().eq(Memchr2::new(needle1, needle2, &data).rev())
+ }
+
+ fn qc_memchr3_iter(data: Vec<u8>) -> bool {
+ let needle1 = 0;
+ let needle2 = 1;
+ let needle3 = 2;
+ let answer = positions3(needle1, needle2, needle3, &data);
+ answer.eq(Memchr3::new(needle1, needle2, needle3, &data))
+ }
+
+ fn qc_memchr3_rev_iter(data: Vec<u8>) -> bool {
+ let needle1 = 0;
+ let needle2 = 1;
+ let needle3 = 2;
+ let answer = positions3(needle1, needle2, needle3, &data);
+ answer.rev().eq(Memchr3::new(needle1, needle2, needle3, &data).rev())
+ }
+
+ fn qc_memchr1_iter_size_hint(data: Vec<u8>) -> bool {
+ // test that the size hint is within reasonable bounds
+ let needle = 0;
+ let mut iter = Memchr::new(needle, &data);
+ let mut real_count = data
+ .iter()
+ .filter(|&&elt| elt == needle)
+ .count();
+
+ while let Some(index) = iter.next() {
+ real_count -= 1;
+ let (lower, upper) = iter.size_hint();
+ assert!(lower <= real_count);
+ assert!(upper.unwrap() >= real_count);
+ assert!(upper.unwrap() <= data.len() - index);
+ }
+ true
+ }
+}
+
+// take items from a DEI, taking front for each true and back for each false.
+// Return a vector with the concatenation of the fronts and the reverse of the
+// backs.
+fn double_ended_take<I, J>(mut iter: I, take_side: J) -> Vec<I::Item>
+where
+ I: DoubleEndedIterator,
+ J: Iterator<Item = bool>,
+{
+ let mut found_front = Vec::new();
+ let mut found_back = Vec::new();
+
+ for take_front in take_side {
+ if take_front {
+ if let Some(pos) = iter.next() {
+ found_front.push(pos);
+ } else {
+ break;
+ }
+ } else {
+ if let Some(pos) = iter.next_back() {
+ found_back.push(pos);
+ } else {
+ break;
+ }
+ };
+ }
+
+ let mut all_found = found_front;
+ all_found.extend(found_back.into_iter().rev());
+ all_found
+}
+
+// return an iterator of the 0-based indices of haystack that match the needle
+fn positions1<'a>(
+ n1: u8,
+ haystack: &'a [u8],
+) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
+ let it = haystack
+ .iter()
+ .enumerate()
+ .filter(move |&(_, &b)| b == n1)
+ .map(|t| t.0);
+ Box::new(it)
+}
+
+fn positions2<'a>(
+ n1: u8,
+ n2: u8,
+ haystack: &'a [u8],
+) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
+ let it = haystack
+ .iter()
+ .enumerate()
+ .filter(move |&(_, &b)| b == n1 || b == n2)
+ .map(|t| t.0);
+ Box::new(it)
+}
+
+fn positions3<'a>(
+ n1: u8,
+ n2: u8,
+ n3: u8,
+ haystack: &'a [u8],
+) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
+ let it = haystack
+ .iter()
+ .enumerate()
+ .filter(move |&(_, &b)| b == n1 || b == n2 || b == n3)
+ .map(|t| t.0);
+ Box::new(it)
+}
diff --git a/vendor/memchr/src/tests/memchr/memchr.rs b/vendor/memchr/src/tests/memchr/memchr.rs
new file mode 100644
index 000000000..ac955ed68
--- /dev/null
+++ b/vendor/memchr/src/tests/memchr/memchr.rs
@@ -0,0 +1,134 @@
+use quickcheck::quickcheck;
+
+use crate::{
+ memchr,
+ memchr::{fallback, naive},
+ memchr2, memchr3, memrchr, memrchr2, memrchr3,
+ tests::memchr::testdata::memchr_tests,
+};
+
+#[test]
+fn memchr1_find() {
+ for test in memchr_tests() {
+ test.one(false, memchr);
+ }
+}
+
+#[test]
+fn memchr1_fallback_find() {
+ for test in memchr_tests() {
+ test.one(false, fallback::memchr);
+ }
+}
+
+#[test]
+fn memchr2_find() {
+ for test in memchr_tests() {
+ test.two(false, memchr2);
+ }
+}
+
+#[test]
+fn memchr2_fallback_find() {
+ for test in memchr_tests() {
+ test.two(false, fallback::memchr2);
+ }
+}
+
+#[test]
+fn memchr3_find() {
+ for test in memchr_tests() {
+ test.three(false, memchr3);
+ }
+}
+
+#[test]
+fn memchr3_fallback_find() {
+ for test in memchr_tests() {
+ test.three(false, fallback::memchr3);
+ }
+}
+
+#[test]
+fn memrchr1_find() {
+ for test in memchr_tests() {
+ test.one(true, memrchr);
+ }
+}
+
+#[test]
+fn memrchr1_fallback_find() {
+ for test in memchr_tests() {
+ test.one(true, fallback::memrchr);
+ }
+}
+
+#[test]
+fn memrchr2_find() {
+ for test in memchr_tests() {
+ test.two(true, memrchr2);
+ }
+}
+
+#[test]
+fn memrchr2_fallback_find() {
+ for test in memchr_tests() {
+ test.two(true, fallback::memrchr2);
+ }
+}
+
+#[test]
+fn memrchr3_find() {
+ for test in memchr_tests() {
+ test.three(true, memrchr3);
+ }
+}
+
+#[test]
+fn memrchr3_fallback_find() {
+ for test in memchr_tests() {
+ test.three(true, fallback::memrchr3);
+ }
+}
+
+quickcheck! {
+ fn qc_memchr1_matches_naive(n1: u8, corpus: Vec<u8>) -> bool {
+ memchr(n1, &corpus) == naive::memchr(n1, &corpus)
+ }
+}
+
+quickcheck! {
+ fn qc_memchr2_matches_naive(n1: u8, n2: u8, corpus: Vec<u8>) -> bool {
+ memchr2(n1, n2, &corpus) == naive::memchr2(n1, n2, &corpus)
+ }
+}
+
+quickcheck! {
+ fn qc_memchr3_matches_naive(
+ n1: u8, n2: u8, n3: u8,
+ corpus: Vec<u8>
+ ) -> bool {
+ memchr3(n1, n2, n3, &corpus) == naive::memchr3(n1, n2, n3, &corpus)
+ }
+}
+
+quickcheck! {
+ fn qc_memrchr1_matches_naive(n1: u8, corpus: Vec<u8>) -> bool {
+ memrchr(n1, &corpus) == naive::memrchr(n1, &corpus)
+ }
+}
+
+quickcheck! {
+ fn qc_memrchr2_matches_naive(n1: u8, n2: u8, corpus: Vec<u8>) -> bool {
+ memrchr2(n1, n2, &corpus) == naive::memrchr2(n1, n2, &corpus)
+ }
+}
+
+quickcheck! {
+ fn qc_memrchr3_matches_naive(
+ n1: u8, n2: u8, n3: u8,
+ corpus: Vec<u8>
+ ) -> bool {
+ memrchr3(n1, n2, n3, &corpus) == naive::memrchr3(n1, n2, n3, &corpus)
+ }
+}
diff --git a/vendor/memchr/src/tests/memchr/mod.rs b/vendor/memchr/src/tests/memchr/mod.rs
new file mode 100644
index 000000000..79f94ab56
--- /dev/null
+++ b/vendor/memchr/src/tests/memchr/mod.rs
@@ -0,0 +1,7 @@
+#[cfg(all(feature = "std", not(miri)))]
+mod iter;
+#[cfg(all(feature = "std", not(miri)))]
+mod memchr;
+mod simple;
+#[cfg(all(feature = "std", not(miri)))]
+mod testdata;
diff --git a/vendor/memchr/src/tests/memchr/simple.rs b/vendor/memchr/src/tests/memchr/simple.rs
new file mode 100644
index 000000000..bed5b4863
--- /dev/null
+++ b/vendor/memchr/src/tests/memchr/simple.rs
@@ -0,0 +1,23 @@
+// Simple tests using MIRI. These are intended only to be a simple exercise of
+// memchr when tests are run under miri. These are mostly necessary because the
+// other tests are far more extensive and take too long to run under miri.
+//
+// These tests are also run when the 'std' feature is not enabled.
+
+use crate::{memchr, memchr2, memchr3, memrchr, memrchr2, memrchr3};
+
+#[test]
+fn simple() {
+ assert_eq!(memchr(b'a', b"abcda"), Some(0));
+ assert_eq!(memchr(b'z', b"abcda"), None);
+ assert_eq!(memchr2(b'a', b'z', b"abcda"), Some(0));
+ assert_eq!(memchr2(b'z', b'y', b"abcda"), None);
+ assert_eq!(memchr3(b'a', b'z', b'b', b"abcda"), Some(0));
+ assert_eq!(memchr3(b'z', b'y', b'x', b"abcda"), None);
+ assert_eq!(memrchr(b'a', b"abcda"), Some(4));
+ assert_eq!(memrchr(b'z', b"abcda"), None);
+ assert_eq!(memrchr2(b'a', b'z', b"abcda"), Some(4));
+ assert_eq!(memrchr2(b'z', b'y', b"abcda"), None);
+ assert_eq!(memrchr3(b'a', b'z', b'b', b"abcda"), Some(4));
+ assert_eq!(memrchr3(b'z', b'y', b'x', b"abcda"), None);
+}
diff --git a/vendor/memchr/src/tests/memchr/testdata.rs b/vendor/memchr/src/tests/memchr/testdata.rs
new file mode 100644
index 000000000..6dda5246f
--- /dev/null
+++ b/vendor/memchr/src/tests/memchr/testdata.rs
@@ -0,0 +1,351 @@
+use std::iter::repeat;
+
+/// Create a sequence of tests that should be run by memchr implementations.
+pub fn memchr_tests() -> Vec<MemchrTest> {
+ let mut tests = Vec::new();
+ for statict in MEMCHR_TESTS {
+ assert!(!statict.corpus.contains("%"), "% is not allowed in corpora");
+ assert!(!statict.corpus.contains("#"), "# is not allowed in corpora");
+ assert!(!statict.needles.contains(&b'%'), "% is an invalid needle");
+ assert!(!statict.needles.contains(&b'#'), "# is an invalid needle");
+
+ let t = MemchrTest {
+ corpus: statict.corpus.to_string(),
+ needles: statict.needles.to_vec(),
+ positions: statict.positions.to_vec(),
+ };
+ tests.push(t.clone());
+ tests.extend(t.expand());
+ }
+ tests
+}
+
+/// A set of tests for memchr-like functions.
+///
+/// These tests mostly try to cover the short string cases. We cover the longer
+/// string cases via the benchmarks (which are tests themselves), via
+/// quickcheck tests and via automatic expansion of each test case (by
+/// increasing the corpus size). Finally, we cover different alignment cases
+/// in the tests by varying the starting point of the slice.
+const MEMCHR_TESTS: &[MemchrTestStatic] = &[
+ // one needle (applied to memchr + memchr2 + memchr3)
+ MemchrTestStatic { corpus: "a", needles: &[b'a'], positions: &[0] },
+ MemchrTestStatic { corpus: "aa", needles: &[b'a'], positions: &[0, 1] },
+ MemchrTestStatic {
+ corpus: "aaa",
+ needles: &[b'a'],
+ positions: &[0, 1, 2],
+ },
+ MemchrTestStatic { corpus: "", needles: &[b'a'], positions: &[] },
+ MemchrTestStatic { corpus: "z", needles: &[b'a'], positions: &[] },
+ MemchrTestStatic { corpus: "zz", needles: &[b'a'], positions: &[] },
+ MemchrTestStatic { corpus: "zza", needles: &[b'a'], positions: &[2] },
+ MemchrTestStatic { corpus: "zaza", needles: &[b'a'], positions: &[1, 3] },
+ MemchrTestStatic { corpus: "zzza", needles: &[b'a'], positions: &[3] },
+ MemchrTestStatic { corpus: "\x00a", needles: &[b'a'], positions: &[1] },
+ MemchrTestStatic { corpus: "\x00", needles: &[b'\x00'], positions: &[0] },
+ MemchrTestStatic {
+ corpus: "\x00\x00",
+ needles: &[b'\x00'],
+ positions: &[0, 1],
+ },
+ MemchrTestStatic {
+ corpus: "\x00a\x00",
+ needles: &[b'\x00'],
+ positions: &[0, 2],
+ },
+ MemchrTestStatic {
+ corpus: "zzzzzzzzzzzzzzzza",
+ needles: &[b'a'],
+ positions: &[16],
+ },
+ MemchrTestStatic {
+ corpus: "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzza",
+ needles: &[b'a'],
+ positions: &[32],
+ },
+ // two needles (applied to memchr2 + memchr3)
+ MemchrTestStatic {
+ corpus: "az",
+ needles: &[b'a', b'z'],
+ positions: &[0, 1],
+ },
+ MemchrTestStatic {
+ corpus: "az",
+ needles: &[b'a', b'z'],
+ positions: &[0, 1],
+ },
+ MemchrTestStatic { corpus: "az", needles: &[b'x', b'y'], positions: &[] },
+ MemchrTestStatic { corpus: "az", needles: &[b'a', b'y'], positions: &[0] },
+ MemchrTestStatic { corpus: "az", needles: &[b'x', b'z'], positions: &[1] },
+ MemchrTestStatic {
+ corpus: "yyyyaz",
+ needles: &[b'a', b'z'],
+ positions: &[4, 5],
+ },
+ MemchrTestStatic {
+ corpus: "yyyyaz",
+ needles: &[b'z', b'a'],
+ positions: &[4, 5],
+ },
+ // three needles (applied to memchr3)
+ MemchrTestStatic {
+ corpus: "xyz",
+ needles: &[b'x', b'y', b'z'],
+ positions: &[0, 1, 2],
+ },
+ MemchrTestStatic {
+ corpus: "zxy",
+ needles: &[b'x', b'y', b'z'],
+ positions: &[0, 1, 2],
+ },
+ MemchrTestStatic {
+ corpus: "zxy",
+ needles: &[b'x', b'a', b'z'],
+ positions: &[0, 1],
+ },
+ MemchrTestStatic {
+ corpus: "zxy",
+ needles: &[b't', b'a', b'z'],
+ positions: &[0],
+ },
+ MemchrTestStatic {
+ corpus: "yxz",
+ needles: &[b't', b'a', b'z'],
+ positions: &[2],
+ },
+];
+
+/// A description of a test on a memchr like function.
+#[derive(Clone, Debug)]
+pub struct MemchrTest {
+ /// The thing to search. We use `&str` instead of `&[u8]` because they
+ /// are nicer to write in tests, and we don't miss much since memchr
+ /// doesn't care about UTF-8.
+ ///
+ /// Corpora cannot contain either '%' or '#'. We use these bytes when
+ /// expanding test cases into many test cases, and we assume they are not
+ /// used. If they are used, `memchr_tests` will panic.
+ corpus: String,
+ /// The needles to search for. This is intended to be an "alternation" of
+ /// needles. The number of needles may cause this test to be skipped for
+ /// some memchr variants. For example, a test with 2 needles cannot be used
+ /// to test `memchr`, but can be used to test `memchr2` and `memchr3`.
+ /// However, a test with only 1 needle can be used to test all of `memchr`,
+ /// `memchr2` and `memchr3`. We achieve this by filling in the needles with
+ /// bytes that we never used in the corpus (such as '#').
+ needles: Vec<u8>,
+ /// The positions expected to match for all of the needles.
+ positions: Vec<usize>,
+}
+
+/// Like MemchrTest, but easier to define as a constant.
+#[derive(Clone, Debug)]
+pub struct MemchrTestStatic {
+ corpus: &'static str,
+ needles: &'static [u8],
+ positions: &'static [usize],
+}
+
+impl MemchrTest {
+ pub fn one<F: Fn(u8, &[u8]) -> Option<usize>>(&self, reverse: bool, f: F) {
+ let needles = match self.needles(1) {
+ None => return,
+ Some(needles) => needles,
+ };
+ // We test different alignments here. Since some implementations use
+ // AVX2, which can read 32 bytes at a time, we test at least that.
+ // Moreover, with loop unrolling, we sometimes process 64 (sse2) or 128
+ // (avx) bytes at a time, so we include that in our offsets as well.
+ //
+ // You might think this would cause most needles to not be found, but
+ // we actually expand our tests to include corpus sizes all the way up
+ // to >500 bytes, so we should exercise most branches.
+ for align in 0..130 {
+ let corpus = self.corpus(align);
+ assert_eq!(
+ self.positions(align, reverse).get(0).cloned(),
+ f(needles[0], corpus.as_bytes()),
+ "search for {:?} failed in: {:?} (len: {}, alignment: {})",
+ needles[0] as char,
+ corpus,
+ corpus.len(),
+ align
+ );
+ }
+ }
+
+ pub fn two<F: Fn(u8, u8, &[u8]) -> Option<usize>>(
+ &self,
+ reverse: bool,
+ f: F,
+ ) {
+ let needles = match self.needles(2) {
+ None => return,
+ Some(needles) => needles,
+ };
+ for align in 0..130 {
+ let corpus = self.corpus(align);
+ assert_eq!(
+ self.positions(align, reverse).get(0).cloned(),
+ f(needles[0], needles[1], corpus.as_bytes()),
+ "search for {:?}|{:?} failed in: {:?} \
+ (len: {}, alignment: {})",
+ needles[0] as char,
+ needles[1] as char,
+ corpus,
+ corpus.len(),
+ align
+ );
+ }
+ }
+
+ pub fn three<F: Fn(u8, u8, u8, &[u8]) -> Option<usize>>(
+ &self,
+ reverse: bool,
+ f: F,
+ ) {
+ let needles = match self.needles(3) {
+ None => return,
+ Some(needles) => needles,
+ };
+ for align in 0..130 {
+ let corpus = self.corpus(align);
+ assert_eq!(
+ self.positions(align, reverse).get(0).cloned(),
+ f(needles[0], needles[1], needles[2], corpus.as_bytes()),
+ "search for {:?}|{:?}|{:?} failed in: {:?} \
+ (len: {}, alignment: {})",
+ needles[0] as char,
+ needles[1] as char,
+ needles[2] as char,
+ corpus,
+ corpus.len(),
+ align
+ );
+ }
+ }
+
+ pub fn iter_one<'a, I, F>(&'a self, reverse: bool, f: F)
+ where
+ F: FnOnce(u8, &'a [u8]) -> I,
+ I: Iterator<Item = usize>,
+ {
+ if let Some(ns) = self.needles(1) {
+ self.iter(reverse, f(ns[0], self.corpus.as_bytes()));
+ }
+ }
+
+ pub fn iter_two<'a, I, F>(&'a self, reverse: bool, f: F)
+ where
+ F: FnOnce(u8, u8, &'a [u8]) -> I,
+ I: Iterator<Item = usize>,
+ {
+ if let Some(ns) = self.needles(2) {
+ self.iter(reverse, f(ns[0], ns[1], self.corpus.as_bytes()));
+ }
+ }
+
+ pub fn iter_three<'a, I, F>(&'a self, reverse: bool, f: F)
+ where
+ F: FnOnce(u8, u8, u8, &'a [u8]) -> I,
+ I: Iterator<Item = usize>,
+ {
+ if let Some(ns) = self.needles(3) {
+ self.iter(reverse, f(ns[0], ns[1], ns[2], self.corpus.as_bytes()));
+ }
+ }
+
+ /// Test that the positions yielded by the given iterator match the
+ /// positions in this test. If reverse is true, then reverse the positions
+ /// before comparing them.
+ fn iter<I: Iterator<Item = usize>>(&self, reverse: bool, it: I) {
+ assert_eq!(
+ self.positions(0, reverse),
+ it.collect::<Vec<usize>>(),
+ r"search for {:?} failed in: {:?}",
+ self.needles.iter().map(|&b| b as char).collect::<Vec<char>>(),
+ self.corpus
+ );
+ }
+
+ /// Expand this test into many variations of the same test.
+ ///
+ /// In particular, this will generate more tests with larger corpus sizes.
+ /// The expected positions are updated to maintain the integrity of the
+ /// test.
+ ///
+ /// This is important in testing a memchr implementation, because there are
+ /// often different cases depending on the length of the corpus.
+ ///
+ /// Note that we extend the corpus by adding `%` bytes, which we
+ /// don't otherwise use as a needle.
+ fn expand(&self) -> Vec<MemchrTest> {
+ let mut more = Vec::new();
+
+ // Add bytes to the start of the corpus.
+ for i in 1..515 {
+ let mut t = self.clone();
+ let mut new_corpus: String = repeat('%').take(i).collect();
+ new_corpus.push_str(&t.corpus);
+ t.corpus = new_corpus;
+ t.positions = t.positions.into_iter().map(|p| p + i).collect();
+ more.push(t);
+ }
+ // Add bytes to the end of the corpus.
+ for i in 1..515 {
+ let mut t = self.clone();
+ let padding: String = repeat('%').take(i).collect();
+ t.corpus.push_str(&padding);
+ more.push(t);
+ }
+
+ more
+ }
+
+ /// Return the corpus at the given alignment.
+ ///
+ /// If the alignment exceeds the length of the corpus, then this returns
+ /// an empty slice.
+ fn corpus(&self, align: usize) -> &str {
+ self.corpus.get(align..).unwrap_or("")
+ }
+
+ /// Return exactly `count` needles from this test. If this test has less
+ /// than `count` needles, then add `#` until the number of needles
+ /// matches `count`. If this test has more than `count` needles, then
+ /// return `None` (because there is no way to use this test data for a
+ /// search using fewer needles).
+ fn needles(&self, count: usize) -> Option<Vec<u8>> {
+ if self.needles.len() > count {
+ return None;
+ }
+
+ let mut needles = self.needles.to_vec();
+ for _ in needles.len()..count {
+ // we assume # is never used in tests.
+ needles.push(b'#');
+ }
+ Some(needles)
+ }
+
+ /// Return the positions in this test, reversed if `reverse` is true.
+ ///
+ /// If alignment is given, then all positions greater than or equal to that
+ /// alignment are offset by the alignment. Positions less than the
+ /// alignment are dropped.
+ fn positions(&self, align: usize, reverse: bool) -> Vec<usize> {
+ let positions = if reverse {
+ let mut positions = self.positions.to_vec();
+ positions.reverse();
+ positions
+ } else {
+ self.positions.to_vec()
+ };
+ positions
+ .into_iter()
+ .filter(|&p| p >= align)
+ .map(|p| p - align)
+ .collect()
+ }
+}
diff --git a/vendor/memchr/src/tests/mod.rs b/vendor/memchr/src/tests/mod.rs
new file mode 100644
index 000000000..f4d406cd1
--- /dev/null
+++ b/vendor/memchr/src/tests/mod.rs
@@ -0,0 +1,15 @@
+mod memchr;
+
+// For debugging, particularly in CI, print out the byte order of the current
+// target.
+#[cfg(all(feature = "std", target_endian = "little"))]
+#[test]
+fn byte_order() {
+ eprintln!("LITTLE ENDIAN");
+}
+
+#[cfg(all(feature = "std", target_endian = "big"))]
+#[test]
+fn byte_order() {
+ eprintln!("BIG ENDIAN");
+}
diff --git a/vendor/memchr/src/tests/x86_64-soft_float.json b/vendor/memchr/src/tests/x86_64-soft_float.json
new file mode 100644
index 000000000..b77649ef9
--- /dev/null
+++ b/vendor/memchr/src/tests/x86_64-soft_float.json
@@ -0,0 +1,15 @@
+{
+ "llvm-target": "x86_64-unknown-none",
+ "target-endian": "little",
+ "target-pointer-width": "64",
+ "target-c-int-width": "32",
+ "os": "none",
+ "arch": "x86_64",
+ "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
+ "linker-flavor": "ld.lld",
+ "linker": "rust-lld",
+ "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
+ "executables": true,
+ "disable-redzone": true,
+ "panic-strategy": "abort"
+}