##// END OF EJS Templates
rust-discovery: optionally don't randomize at all, for tests...
Georges Racinet -
r42968:4e7bd618 default
parent child Browse files
Show More
@@ -92,11 +92,19 b' def _updatesample(revs, heads, sample, p'
92 92 dist.setdefault(p, d + 1)
93 93 visit.append(p)
94 94
95 def _limitsample(sample, desiredlen):
96 """return a random subset of sample of at most desiredlen item"""
97 if len(sample) > desiredlen:
98 sample = set(random.sample(sample, desiredlen))
99 return sample
95 def _limitsample(sample, desiredlen, randomize=True):
96 """return a random subset of sample of at most desiredlen item.
97
98 If randomize is False, though, a deterministic subset is returned.
99 This is meant for integration tests.
100 """
101 if len(sample) <= desiredlen:
102 return sample
103 if randomize:
104 return set(random.sample(sample, desiredlen))
105 sample = list(sample)
106 sample.sort()
107 return set(sample[:desiredlen])
100 108
101 109 class partialdiscovery(object):
102 110 """an object representing ongoing discovery
@@ -110,7 +118,7 b' class partialdiscovery(object):'
110 118 (all tracked revisions are known locally)
111 119 """
112 120
113 def __init__(self, repo, targetheads, respectsize):
121 def __init__(self, repo, targetheads, respectsize, randomize=True):
114 122 self._repo = repo
115 123 self._targetheads = targetheads
116 124 self._common = repo.changelog.incrementalmissingrevs()
@@ -118,6 +126,7 b' class partialdiscovery(object):'
118 126 self.missing = set()
119 127 self._childrenmap = None
120 128 self._respectsize = respectsize
129 self.randomize = randomize
121 130
122 131 def addcommons(self, commons):
123 132 """register nodes known as common"""
@@ -222,7 +231,7 b' class partialdiscovery(object):'
222 231 sample = set(self._repo.revs('heads(%ld)', revs))
223 232
224 233 if len(sample) >= size:
225 return _limitsample(sample, size)
234 return _limitsample(sample, size, randomize=self.randomize)
226 235
227 236 _updatesample(None, headrevs, sample, self._parentsgetter(),
228 237 quicksamplesize=size)
@@ -249,10 +258,15 b' class partialdiscovery(object):'
249 258 if not self._respectsize:
250 259 size = max(size, min(len(revsroots), len(revsheads)))
251 260
252 sample = _limitsample(sample, size)
261 sample = _limitsample(sample, size, randomize=self.randomize)
253 262 if len(sample) < size:
254 263 more = size - len(sample)
255 sample.update(random.sample(list(revs - sample), more))
264 takefrom = list(revs - sample)
265 if self.randomize:
266 sample.update(random.sample(takefrom, more))
267 else:
268 takefrom.sort()
269 sample.update(takefrom[:more])
256 270 return sample
257 271
258 272 def findcommonheads(ui, local, remote,
@@ -31,6 +31,7 b' pub struct PartialDiscovery<G: Graph + C'
31 31 missing: HashSet<Revision>,
32 32 rng: Rng,
33 33 respect_size: bool,
34 randomize: bool,
34 35 }
35 36
36 37 pub struct DiscoveryStats {
@@ -151,14 +152,26 b' impl<G: Graph + Clone> PartialDiscovery<'
151 152 /// will interpret the size argument requested by the caller. If it's
152 153 /// `false`, they are allowed to produce a sample whose size is more
153 154 /// appropriate to the situation (typically bigger).
155 ///
156 /// The `randomize` boolean affects sampling, and specifically how
157 /// limiting or last-minute expanding is been done:
158 ///
159 /// If `true`, both will perform random picking from `self.undecided`.
160 /// This is currently the best for actual discoveries.
161 ///
162 /// If `false`, a reproductible picking strategy is performed. This is
163 /// useful for integration tests.
154 164 pub fn new(
155 165 graph: G,
156 166 target_heads: Vec<Revision>,
157 167 respect_size: bool,
168 randomize: bool,
158 169 ) -> Self {
159 170 let mut seed: [u8; 16] = [0; 16];
160 thread_rng().fill_bytes(&mut seed);
161 Self::new_with_seed(graph, target_heads, seed, respect_size)
171 if randomize {
172 thread_rng().fill_bytes(&mut seed);
173 }
174 Self::new_with_seed(graph, target_heads, seed, respect_size, randomize)
162 175 }
163 176
164 177 pub fn new_with_seed(
@@ -166,6 +179,7 b' impl<G: Graph + Clone> PartialDiscovery<'
166 179 target_heads: Vec<Revision>,
167 180 seed: [u8; 16],
168 181 respect_size: bool,
182 randomize: bool,
169 183 ) -> Self {
170 184 PartialDiscovery {
171 185 undecided: None,
@@ -176,6 +190,7 b' impl<G: Graph + Clone> PartialDiscovery<'
176 190 missing: HashSet::new(),
177 191 rng: Rng::from_seed(seed),
178 192 respect_size: respect_size,
193 randomize: randomize,
179 194 }
180 195 }
181 196
@@ -186,6 +201,11 b' impl<G: Graph + Clone> PartialDiscovery<'
186 201 mut sample: Vec<Revision>,
187 202 size: usize,
188 203 ) -> Vec<Revision> {
204 if !self.randomize {
205 sample.sort();
206 sample.truncate(size);
207 return sample;
208 }
189 209 let sample_len = sample.len();
190 210 if sample_len <= size {
191 211 return sample;
@@ -436,13 +456,15 b' mod tests {'
436 456
437 457 /// A PartialDiscovery as for pushing all the heads of `SampleGraph`
438 458 ///
439 /// To avoid actual randomness in tests, we give it a fixed random seed.
459 /// To avoid actual randomness in these tests, we give it a fixed
460 /// random seed, but by default we'll test the random version.
440 461 fn full_disco() -> PartialDiscovery<SampleGraph> {
441 462 PartialDiscovery::new_with_seed(
442 463 SampleGraph,
443 464 vec![10, 11, 12, 13],
444 465 [0; 16],
445 466 true,
467 true,
446 468 )
447 469 }
448 470
@@ -450,7 +472,13 b' mod tests {'
450 472 ///
451 473 /// To avoid actual randomness in tests, we give it a fixed random seed.
452 474 fn disco12() -> PartialDiscovery<SampleGraph> {
453 PartialDiscovery::new_with_seed(SampleGraph, vec![12], [0; 16], true)
475 PartialDiscovery::new_with_seed(
476 SampleGraph,
477 vec![12],
478 [0; 16],
479 true,
480 true,
481 )
454 482 }
455 483
456 484 fn sorted_undecided(
@@ -535,6 +563,16 b' mod tests {'
535 563 }
536 564
537 565 #[test]
566 fn test_limit_sample_no_random() {
567 let mut disco = full_disco();
568 disco.randomize = false;
569 assert_eq!(
570 disco.limit_sample(vec![1, 8, 13, 5, 7, 3], 4),
571 vec![1, 3, 5, 7]
572 );
573 }
574
575 #[test]
538 576 fn test_quick_sample_enough_undecided_heads() -> Result<(), GraphError> {
539 577 let mut disco = full_disco();
540 578 disco.undecided = Some((1..=13).collect());
@@ -36,7 +36,8 b' py_class!(pub class PartialDiscovery |py'
36 36 _cls,
37 37 repo: PyObject,
38 38 targetheads: PyObject,
39 respectsize: bool
39 respectsize: bool,
40 randomize: bool = true
40 41 ) -> PyResult<PartialDiscovery> {
41 42 let index = repo.getattr(py, "changelog")?.getattr(py, "index")?;
42 43 Self::create_instance(
@@ -44,7 +45,8 b' py_class!(pub class PartialDiscovery |py'
44 45 RefCell::new(Box::new(CorePartialDiscovery::new(
45 46 Index::new(py, index)?,
46 47 rev_pyiter_collect(py, &targetheads)?,
47 respectsize
48 respectsize,
49 randomize,
48 50 )))
49 51 )
50 52 }
@@ -103,6 +103,9 b' class rustdiscoverytest(unittest.TestCas'
103 103 self.assertTrue(disco.iscomplete())
104 104 self.assertEqual(disco.commonheads(), {1})
105 105
106 def testinitnorandom(self):
107 PartialDiscovery(self.repo(), [3], True, randomize=False)
108
106 109 if __name__ == '__main__':
107 110 import silenttestrunner
108 111 silenttestrunner.main(__name__)
General Comments 0
You need to be logged in to leave comments. Login now