Added unit test to show bug in intersection

This commit is contained in:
Paul Masurel
2018-02-12 11:45:15 +09:00
parent c4125bda59
commit e95c49e749
3 changed files with 60 additions and 32 deletions

View File

@@ -25,4 +25,3 @@ impl Drop for DirectoryLock {
}
}
}

View File

@@ -34,6 +34,9 @@ pub trait DocSet {
/// More specifically, if the docset is already positionned on the target
/// skipping will advance to the next position and return SkipResult::Overstep.
///
/// If `.skip_next()` oversteps, then the docset must be positionned correctly
/// on an existing document. In other words, `.doc()` should return the first document
/// greater than `DocId`.
fn skip_next(&mut self, target: DocId) -> SkipResult {
if !self.advance() {
return SkipResult::End;

View File

@@ -32,37 +32,6 @@ impl<TDocSet: DocSet> IntersectionDocSet<TDocSet> {
}
impl<TDocSet: DocSet> DocSet for IntersectionDocSet<TDocSet> {
/// Returns the minimum `.size_hint()` of the intersected docsets.
fn size_hint(&self) -> u32 {
self.docsets
.iter()
.map(|docset| docset.size_hint())
.min()
.unwrap() // safe as docsets cannot be empty.
}
fn skip_next(&mut self, mut target: DocId) -> SkipResult {
let mut overstep = false;
for docset in &mut self.docsets {
match docset.skip_next(target) {
SkipResult::End => {
return SkipResult::End;
}
SkipResult::OverStep => {
overstep = true;
target = docset.doc();
}
SkipResult::Reached => {}
}
}
if overstep {
SkipResult::OverStep
} else {
SkipResult::Reached
}
}
#[allow(never_loop)]
fn advance(&mut self) -> bool {
if self.finished {
@@ -102,13 +71,53 @@ impl<TDocSet: DocSet> DocSet for IntersectionDocSet<TDocSet> {
}
}
fn skip_next(&mut self, mut target: DocId) -> SkipResult {
// We optimize skipping by skipping every single member
// of the intersection to target.
// TODO fix BUG...
// what if we overstep on the second member of the intersection?
// The first member is not necessarily correct.
let mut overstep = false;
for docset in &mut self.docsets {
match docset.skip_next(target) {
SkipResult::End => {
return SkipResult::End;
}
SkipResult::OverStep => {
overstep = true;
// update the target
// for the remaining members of the intersection.
target = docset.doc();
}
SkipResult::Reached => {
}
}
}
self.doc = target;
if overstep {
SkipResult::OverStep
} else {
SkipResult::Reached
}
}
fn doc(&self) -> DocId {
self.doc
}
fn size_hint(&self) -> u32 {
self.docsets
.iter()
.map(|docset| docset.size_hint())
.min()
.unwrap_or(0u32)
}
}
#[cfg(test)]
mod tests {
use postings::SkipResult;
use postings::{DocSet, IntersectionDocSet, VecPostings};
@@ -144,6 +153,23 @@ mod tests {
assert_eq!(intersection.doc(), 0);
}
#[test]
fn test_intersection_skip() {
let left = VecPostings::from(vec![4]);
let right = VecPostings::from(vec![2, 5]);
let mut intersection = IntersectionDocSet::from(vec![left, right]);
assert_eq!(intersection.skip_next(4), SkipResult::End);
}
#[test]
fn test_intersection_skip_2() {
let left = VecPostings::from(vec![0, 1, 2, 4]);
let right = VecPostings::from(vec![2, 5]);
let mut intersection = IntersectionDocSet::from(vec![left, right]);
assert_eq!(intersection.skip_next(2), SkipResult::Reached);
assert_eq!(intersection.doc(), 2);
}
#[test]
fn test_intersection_empty() {
let a = VecPostings::from(vec![1, 3]);