Mercurial > public > mercurial-scm > hg
comparison tests/test-verify-repo-operations.py @ 28257:7ff725db2fdf
testing: test multiple repositories with Hypothesis
This expands the Hypothesis based stateful testing so that
rather than having a single repository under test, Hypothesis
manages a family of repositories. Some of these are freshly
created, some are clones of others.
author | David R. MacIver <david@drmaciver.com> |
---|---|
date | Fri, 26 Feb 2016 17:24:14 +0000 |
parents | 55325bdf6c13 |
children | fc7ee50a0d65 |
comparison
equal
deleted
inserted
replaced
28256:55325bdf6c13 | 28257:7ff725db2fdf |
---|---|
106 except subprocess.CalledProcessError as e: | 106 except subprocess.CalledProcessError as e: |
107 if not any(a in e.output for a in args): | 107 if not any(a in e.output for a in args): |
108 note(e.output) | 108 note(e.output) |
109 raise | 109 raise |
110 | 110 |
111 reponames = st.text("abcdefghijklmnopqrstuvwxyz01234556789", min_size=1).map( | |
112 lambda s: s.encode('ascii') | |
113 ) | |
114 | |
111 class verifyingstatemachine(RuleBasedStateMachine): | 115 class verifyingstatemachine(RuleBasedStateMachine): |
112 """This defines the set of acceptable operations on a Mercurial repository | 116 """This defines the set of acceptable operations on a Mercurial repository |
113 using Hypothesis's RuleBasedStateMachine. | 117 using Hypothesis's RuleBasedStateMachine. |
114 | 118 |
115 The general concept is that we manage multiple repositories inside a | 119 The general concept is that we manage multiple repositories inside a |
129 http://hypothesis.readthedocs.org/en/release/stateful.html for more | 133 http://hypothesis.readthedocs.org/en/release/stateful.html for more |
130 details.""" | 134 details.""" |
131 | 135 |
132 # A bundle is a reusable collection of previously generated data which may | 136 # A bundle is a reusable collection of previously generated data which may |
133 # be provided as arguments to future operations. | 137 # be provided as arguments to future operations. |
138 repos = Bundle('repos') | |
134 paths = Bundle('paths') | 139 paths = Bundle('paths') |
135 contents = Bundle('contents') | 140 contents = Bundle('contents') |
136 branches = Bundle('branches') | 141 branches = Bundle('branches') |
137 committimes = Bundle('committimes') | 142 committimes = Bundle('committimes') |
138 | 143 |
139 def __init__(self): | 144 def __init__(self): |
140 super(verifyingstatemachine, self).__init__() | 145 super(verifyingstatemachine, self).__init__() |
141 self.repodir = os.path.join(testtmp, "repo") | 146 self.repodir = os.path.join(testtmp, "repos") |
142 if os.path.exists(self.repodir): | 147 if os.path.exists(self.repodir): |
143 shutil.rmtree(self.repodir) | 148 shutil.rmtree(self.repodir) |
144 os.chdir(testtmp) | 149 os.chdir(testtmp) |
145 self.log = [] | 150 self.log = [] |
146 self.failed = False | 151 self.failed = False |
147 | 152 |
148 self.mkdirp("repo") | 153 self.mkdirp("repos") |
149 self.cd("repo") | 154 self.cd("repos") |
155 self.mkdirp("repo1") | |
156 self.cd("repo1") | |
150 self.hg("init") | 157 self.hg("init") |
151 | 158 |
152 def teardown(self): | 159 def teardown(self): |
153 """On teardown we clean up after ourselves as usual, but we also | 160 """On teardown we clean up after ourselves as usual, but we also |
154 do some additional testing: We generate a .t file based on our test | 161 do some additional testing: We generate a .t file based on our test |
354 when.strftime('%Y-%m-%d %H:%M:%S %z'),)) | 361 when.strftime('%Y-%m-%d %H:%M:%S %z'),)) |
355 | 362 |
356 with acceptableerrors(*errors): | 363 with acceptableerrors(*errors): |
357 self.hg(*command) | 364 self.hg(*command) |
358 | 365 |
366 # Section: Repository management | |
367 @property | |
368 def currentrepo(self): | |
369 return os.path.basename(os.getcwd()) | |
370 | |
371 @rule( | |
372 target=repos, | |
373 source=repos, | |
374 name=reponames, | |
375 ) | |
376 def clone(self, source, name): | |
377 if not os.path.exists(os.path.join("..", name)): | |
378 self.cd("..") | |
379 self.hg("clone", source, name) | |
380 self.cd(name) | |
381 return name | |
382 | |
383 @rule( | |
384 target=repos, | |
385 name=reponames, | |
386 ) | |
387 def fresh(self, name): | |
388 if not os.path.exists(os.path.join("..", name)): | |
389 self.cd("..") | |
390 self.mkdirp(name) | |
391 self.cd(name) | |
392 self.hg("init") | |
393 return name | |
394 | |
395 @rule(name=repos) | |
396 def switch(self, name): | |
397 self.cd(os.path.join("..", name)) | |
398 assert self.currentrepo == name | |
399 assert os.path.exists(".hg") | |
400 | |
401 @rule(target=repos) | |
402 def origin(self): | |
403 return "repo1" | |
404 | |
405 @rule() | |
406 def pull(self, repo=repos): | |
407 with acceptableerrors( | |
408 "repository default not found", | |
409 "repository is unrelated", | |
410 ): | |
411 self.hg("pull") | |
412 | |
413 @rule(newbranch=st.booleans()) | |
414 def push(self, newbranch): | |
415 with acceptableerrors( | |
416 "default repository not configured", | |
417 "no changes found", | |
418 ): | |
419 if newbranch: | |
420 self.hg("push", "--new-branch") | |
421 else: | |
422 with acceptableerrors( | |
423 "creates new branches" | |
424 ): | |
425 self.hg("push") | |
426 | |
359 # Section: Simple side effect free "check" operations | 427 # Section: Simple side effect free "check" operations |
360 @rule() | 428 @rule() |
361 def log(self): | 429 def log(self): |
362 self.hg("log") | 430 self.hg("log") |
363 | 431 |