##// END OF EJS Templates
match: strengthen visit_children_set invariant, Recursive means "all files"...
Arseniy Alekseyev -
r52464:74230abb stable
parent child Browse files
Show More
@@ -2146,7 +2146,11 b' mod tests {'
2146 2146 visit_children_set: &'a VisitChildrenSet,
2147 2147 }
2148 2148
2149 fn holds(matching: &Tree, vcs: &VisitChildrenSet) -> bool {
2149 fn holds(
2150 matching: &Tree,
2151 not_matching: &Tree,
2152 vcs: &VisitChildrenSet,
2153 ) -> bool {
2150 2154 match vcs {
2151 2155 VisitChildrenSet::Empty => matching.is_empty(),
2152 2156 VisitChildrenSet::This => {
@@ -2154,14 +2158,11 b' mod tests {'
2154 2158 true
2155 2159 }
2156 2160 VisitChildrenSet::Recursive => {
2157 // `Recursive` does not come with any correctness
2158 // obligations.
2159 // It instructs the caller to stop calling
2160 // `visit_children_set` for all
2161 // descendants, so may have negative performance
2162 // implications, but we're not testing against that
2163 // here.
2164 true
2161 // `Recursive` requires that *everything* in the
2162 // subtree matches. This
2163 // requirement is relied on for example in
2164 // DifferenceMatcher implementation.
2165 not_matching.is_empty()
2165 2166 }
2166 2167 VisitChildrenSet::Set(allowed_children) => {
2167 2168 // `allowed_children` does not distinguish between
@@ -2186,9 +2187,10 b' mod tests {'
2186 2187 matcher: &M,
2187 2188 path: &HgPath,
2188 2189 matching: &Tree,
2190 not_matching: &Tree,
2189 2191 visit_children_set: &VisitChildrenSet,
2190 2192 ) {
2191 if !holds(matching, visit_children_set) {
2193 if !holds(matching, not_matching, visit_children_set) {
2192 2194 panic!(
2193 2195 "{:#?}",
2194 2196 Error {
@@ -2223,34 +2225,52 b' mod tests {'
2223 2225 self.files.is_empty() && self.dirs.is_empty()
2224 2226 }
2225 2227
2228 fn make(
2229 files: BTreeSet<HgPathBuf>,
2230 dirs: BTreeMap<HgPathBuf, Tree>,
2231 ) -> Self {
2232 Self {
2233 files,
2234 dirs: dirs
2235 .into_iter()
2236 .filter(|(_k, v)| (!(v.is_empty())))
2237 .collect(),
2238 }
2239 }
2240
2226 2241 fn filter_and_check<M: Matcher + Debug>(
2227 2242 &self,
2228 2243 m: &M,
2229 2244 path: &HgPath,
2230 ) -> Self {
2231 let files: BTreeSet<HgPathBuf> = self
2232 .files
2233 .iter()
2234 .filter(|v| m.matches(&path.join(v)))
2235 .map(|f| f.to_owned())
2236 .collect();
2237 let dirs: BTreeMap<HgPathBuf, Tree> = self
2245 ) -> (Self, Self) {
2246 let (files1, files2): (BTreeSet<HgPathBuf>, BTreeSet<HgPathBuf>) =
2247 self.files
2248 .iter()
2249 .map(|v| v.to_owned())
2250 .partition(|v| m.matches(&path.join(v)));
2251 let (dirs1, dirs2): (
2252 BTreeMap<HgPathBuf, Tree>,
2253 BTreeMap<HgPathBuf, Tree>,
2254 ) = self
2238 2255 .dirs
2239 2256 .iter()
2240 .filter_map(|(k, v)| {
2257 .map(|(k, v)| {
2241 2258 let path = path.join(k);
2242 let v = v.filter_and_check(m, &path);
2243 if v.is_empty() {
2244 None
2245 } else {
2246 Some((k.to_owned(), v))
2247 }
2259 let (t1, t2) = v.filter_and_check(m, &path);
2260 ((k.clone(), t1), (k.clone(), t2))
2248 2261 })
2249 .collect();
2250 let matching = Self { files, dirs };
2262 .unzip();
2263 let matching = Self::make(files1, dirs1);
2264 let not_matching = Self::make(files2, dirs2);
2251 2265 let vcs = m.visit_children_set(path);
2252 invariants::visit_children_set::check(m, path, &matching, &vcs);
2253 matching
2266 invariants::visit_children_set::check(
2267 m,
2268 path,
2269 &matching,
2270 &not_matching,
2271 &vcs,
2272 );
2273 (matching, not_matching)
2254 2274 }
2255 2275
2256 2276 fn check_matcher<M: Matcher + Debug>(
@@ -2259,11 +2279,11 b' mod tests {'
2259 2279 expect_count: usize,
2260 2280 ) {
2261 2281 let res = self.filter_and_check(m, &HgPathBuf::new());
2262 if expect_count != res.len() {
2282 if expect_count != res.0.len() {
2263 2283 eprintln!(
2264 2284 "warning: expected {} matches, got {} for {:#?}",
2265 2285 expect_count,
2266 res.len(),
2286 res.0.len(),
2267 2287 m
2268 2288 );
2269 2289 }
General Comments 0
You need to be logged in to leave comments. Login now