Sprinkle some "no cover" pragmas over the code base

Add some "no cover" to some unrecoverable exceptions
(e.g. misconfiguration) or base-class methods that are not intended to
be invoked.

Signed-off-by: Niels Thykier <niels@thykier.net>
This commit is contained in:
Niels Thykier 2016-11-13 08:49:46 +00:00
parent 54fd517062
commit 20c2b87833
6 changed files with 42 additions and 44 deletions

View File

@ -408,10 +408,10 @@ class Britney(object):
check_fields=check_fields, check_field_name=check_field_name): check_fields=check_fields, check_field_name=check_field_name):
bad = [] bad = []
for f in check_fields: for f in check_fields:
if pkg_entry1[f] != pkg_entry2[f]: if pkg_entry1[f] != pkg_entry2[f]: # pragma: no cover
bad.append((f, pkg_entry1[f], pkg_entry2[f])) bad.append((f, pkg_entry1[f], pkg_entry2[f]))
if bad: if bad: # pragma: no cover
self.log("Mismatch found %s %s %s differs" % ( self.log("Mismatch found %s %s %s differs" % (
package, pkg_entry1.version, parch), type="E") package, pkg_entry1.version, parch), type="E")
for f, v1, v2 in bad: for f, v1, v2 in bad:
@ -454,11 +454,11 @@ class Britney(object):
(self.options, self.args) = parser.parse_args() (self.options, self.args) = parser.parse_args()
# integrity checks # integrity checks
if self.options.nuninst_cache and self.options.print_uninst: if self.options.nuninst_cache and self.options.print_uninst: # pragma: no cover
self.log("nuninst_cache and print_uninst are mutually exclusive!", type="E") self.log("nuninst_cache and print_uninst are mutually exclusive!", type="E")
sys.exit(1) sys.exit(1)
# if the configuration file exists, then read it and set the additional options # if the configuration file exists, then read it and set the additional options
elif not os.path.isfile(self.options.config): elif not os.path.isfile(self.options.config): # pragma: no cover
self.log("Unable to read the configuration file (%s), exiting!" % self.options.config, type="E") self.log("Unable to read the configuration file (%s), exiting!" % self.options.config, type="E")
sys.exit(1) sys.exit(1)
@ -488,7 +488,7 @@ class Britney(object):
suite_path = getattr(self.options, suite) suite_path = getattr(self.options, suite)
self.suite_info[suite] = SuiteInfo(name=suite, path=suite_path, excuses_suffix=suffix) self.suite_info[suite] = SuiteInfo(name=suite, path=suite_path, excuses_suffix=suffix)
else: else:
if suite in {'testing', 'unstable'}: if suite in {'testing', 'unstable'}: # pragma: no cover
self.log("Mandatory configuration %s is not set in the config" % suite.upper(), type='E') self.log("Mandatory configuration %s is not set in the config" % suite.upper(), type='E')
sys.exit(1) sys.exit(1)
self.log("Optional suite %s is not defined (config option: %s) " % (suite, suite.upper())) self.log("Optional suite %s is not defined (config option: %s) " % (suite, suite.upper()))
@ -508,7 +508,7 @@ class Britney(object):
else: else:
self.options.components = None self.options.components = None
if self.options.control_files and self.options.components: if self.options.control_files and self.options.components: # pragma: no cover
# We cannot regenerate the control files correctly when reading from an # We cannot regenerate the control files correctly when reading from an
# actual mirror (we don't which package goes in what component etc.). # actual mirror (we don't which package goes in what component etc.).
self.log("Cannot use --control-files with mirror-layout (components)!", type="E") self.log("Cannot use --control-files with mirror-layout (components)!", type="E")
@ -526,7 +526,7 @@ class Britney(object):
# Sort the architecture list # Sort the architecture list
allarches = sorted(self.options.architectures.split()) allarches = sorted(self.options.architectures.split())
else: else:
if not release_file: if not release_file: # pragma: no cover
self.log("No configured architectures and there is no release file for testing", type="E") self.log("No configured architectures and there is no release file for testing", type="E")
self.log("Please check if there is a \"Release\" file in %s" % self.suite_info['testing'].path, type="E") self.log("Please check if there is a \"Release\" file in %s" % self.suite_info['testing'].path, type="E")
self.log("or if the config file contains a non-empty \"ARCHITECTURES\" field", type="E") self.log("or if the config file contains a non-empty \"ARCHITECTURES\" field", type="E")
@ -585,7 +585,7 @@ class Britney(object):
while step(): while step():
no += 1 no += 1
pkg_name = get_field('Package', None) pkg_name = get_field('Package', None)
if pkg_name is None: if pkg_name is None: # pragma: no cover
raise ValueError("Missing Package field in paragraph %d (file %s)" % (no, faux_packages_file)) raise ValueError("Missing Package field in paragraph %d (file %s)" % (no, faux_packages_file))
pkg_name = sys.intern(pkg_name) pkg_name = sys.intern(pkg_name)
version = sys.intern(get_field('Version', '1.0-1')) version = sys.intern(get_field('Version', '1.0-1'))
@ -656,18 +656,18 @@ class Britney(object):
while step(): while step():
no += 1 no += 1
pkg_name = get_field('Fake-Package-Name', None) pkg_name = get_field('Fake-Package-Name', None)
if pkg_name is None: if pkg_name is None: # pragma: no cover
raise ValueError("Missing Fake-Package-Name field in paragraph %d (file %s)" % (no, constraints_file)) raise ValueError("Missing Fake-Package-Name field in paragraph %d (file %s)" % (no, constraints_file))
pkg_name = sys.intern(pkg_name) pkg_name = sys.intern(pkg_name)
def mandatory_field(x): def mandatory_field(x):
v = get_field(x, None) v = get_field(x, None)
if v is None: if v is None: # pragma: no cover
raise ValueError("Missing %s field for %s (file %s)" % (x, pkg_name, constraints_file)) raise ValueError("Missing %s field for %s (file %s)" % (x, pkg_name, constraints_file))
return v return v
constraint = mandatory_field('Constraint') constraint = mandatory_field('Constraint')
if constraint not in {'present-and-installable'}: if constraint not in {'present-and-installable'}: # pragma: no cover
raise ValueError("Unsupported constraint %s for %s (file %s)" % (constraint, pkg_name, constraints_file)) raise ValueError("Unsupported constraint %s for %s (file %s)" % (constraint, pkg_name, constraints_file))
self.log(" - constraint %s" % pkg_name, type='I') self.log(" - constraint %s" % pkg_name, type='I')
@ -690,17 +690,17 @@ class Britney(object):
deps.append(s[0]) deps.append(s[0])
else: else:
pkg, arch_res = s pkg, arch_res = s
if not (arch_res.startswith('[') and arch_res.endswith(']')): if not (arch_res.startswith('[') and arch_res.endswith(']')): # pragma: no cover
raise ValueError("Invalid arch-restriction on %s - should be [arch1 arch2] (for %s file %s)" raise ValueError("Invalid arch-restriction on %s - should be [arch1 arch2] (for %s file %s)"
% (pkg, pkg_name, constraints_file)) % (pkg, pkg_name, constraints_file))
arch_res = arch_res[1:-1].split() arch_res = arch_res[1:-1].split()
if not arch_res: if not arch_res: # pragma: no cover
msg = "Empty arch-restriction for %s: Uses comma or negation (for %s file %s)" msg = "Empty arch-restriction for %s: Uses comma or negation (for %s file %s)"
raise ValueError(msg % (pkg, pkg_name, constraints_file)) raise ValueError(msg % (pkg, pkg_name, constraints_file))
for a in arch_res: for a in arch_res:
if a == arch: if a == arch:
deps.append(pkg) deps.append(pkg)
elif ',' in a or '!' in a: elif ',' in a or '!' in a: # pragma: no cover
msg = "Invalid arch-restriction for %s: Uses comma or negation (for %s file %s)" msg = "Invalid arch-restriction for %s: Uses comma or negation (for %s file %s)"
raise ValueError(msg % (pkg, pkg_name, constraints_file)) raise ValueError(msg % (pkg, pkg_name, constraints_file))
pkg_id = BinaryPackageId(pkg_name, faux_version, arch) pkg_id = BinaryPackageId(pkg_name, faux_version, arch)
@ -877,13 +877,13 @@ class Britney(object):
parts = apt_pkg.parse_depends(provides_raw, False) parts = apt_pkg.parse_depends(provides_raw, False)
nprov = [] nprov = []
for or_clause in parts: for or_clause in parts:
if len(or_clause) != 1: if len(or_clause) != 1: # pragma: no cover
msg = "Ignoring invalid provides in %s: Alternatives [%s]" % (str(pkg_id), str(or_clause)) msg = "Ignoring invalid provides in %s: Alternatives [%s]" % (str(pkg_id), str(or_clause))
self.log(msg, type='W') self.log(msg, type='W')
continue continue
for part in or_clause: for part in or_clause:
provided, provided_version, op = part provided, provided_version, op = part
if op != '' and op != '=': if op != '' and op != '=': # pragma: no cover
msg = "Ignoring invalid provides in %s: %s (%s %s)" % (str(pkg_id), provided, op, provided_version) msg = "Ignoring invalid provides in %s: %s (%s %s)" % (str(pkg_id), provided, op, provided_version)
self.log(msg, type='W') self.log(msg, type='W')
continue continue
@ -2645,7 +2645,7 @@ class Britney(object):
cached_nuninst = self.nuninst_orig cached_nuninst = self.nuninst_orig
self._inst_tester.compute_testing_installability() self._inst_tester.compute_testing_installability()
computed_nuninst = self.get_nuninst(build=True) computed_nuninst = self.get_nuninst(build=True)
if cached_nuninst != computed_nuninst: if cached_nuninst != computed_nuninst: # pragma: no cover
only_on_break_archs = True only_on_break_archs = True
self.log("==================== NUNINST OUT OF SYNC =========================", type="E") self.log("==================== NUNINST OUT OF SYNC =========================", type="E")
for arch in self.options.architectures: for arch in self.options.architectures:

View File

@ -156,7 +156,7 @@ class InstallabilityTesterBuilder(object):
Note, this method is optimised to be called at most once per Note, this method is optimised to be called at most once per
binary. binary.
""" """
if binary not in self._package_table: if binary not in self._package_table: # pragma: no cover
raise ValueError("Binary %s/%s/%s does not exist" % binary) raise ValueError("Binary %s/%s/%s does not exist" % binary)
rel = _RelationBuilder(self, binary) rel = _RelationBuilder(self, binary)
yield rel yield rel
@ -231,7 +231,7 @@ class InstallabilityTesterBuilder(object):
# #
# At the same time, intern the rdep sets # At the same time, intern the rdep sets
for pkg in reverse_package_table: for pkg in reverse_package_table:
if pkg not in package_table: if pkg not in package_table: # pragma: no cover
raise RuntimeError("%s/%s/%s referenced but not added!" % pkg) raise RuntimeError("%s/%s/%s referenced but not added!" % pkg)
deps, con = package_table[pkg] deps, con = package_table[pkg]
rdeps, rcon, rdep_relations = reverse_package_table[pkg] rdeps, rcon, rdep_relations = reverse_package_table[pkg]

View File

@ -63,7 +63,7 @@ class InstallabilitySolver(InstallabilityTester):
going_in = set() going_in = set()
debug_solver = 0 debug_solver = 0
try: try: # pragma: no cover
debug_solver = int(os.environ.get('BRITNEY_DEBUG', '0')) debug_solver = int(os.environ.get('BRITNEY_DEBUG', '0'))
except: except:
pass pass
@ -80,7 +80,7 @@ class InstallabilitySolver(InstallabilityTester):
for r in rms: for r in rms:
ptable[r] = key ptable[r] = key
if debug_solver > 1: if debug_solver > 1: # pragma: no cover
self._dump_groups(groups) self._dump_groups(groups)
# This large loop will add ordering constrains on each "item" # This large loop will add ordering constrains on each "item"
@ -107,7 +107,7 @@ class InstallabilitySolver(InstallabilityTester):
if other == key: if other == key:
# "Self-conflicts" => ignore # "Self-conflicts" => ignore
continue continue
if debug_solver and other not in order[key]['before']: if debug_solver and other not in order[key]['before']: # pragma: no cover
print("N: Conflict induced order: %s before %s" % (key, other)) print("N: Conflict induced order: %s before %s" % (key, other))
order[key]['before'].add(other) order[key]['before'].add(other)
order[other]['after'].add(key) order[other]['after'].add(key)
@ -126,7 +126,7 @@ class InstallabilitySolver(InstallabilityTester):
if other == key: if other == key:
# "Self-dependency" => ignore # "Self-dependency" => ignore
continue continue
if debug_solver and other not in order[key]['after']: if debug_solver and other not in order[key]['after']: # pragma: no cover
print("N: Removal induced order: %s before %s" % (key, other)) print("N: Removal induced order: %s before %s" % (key, other))
order[key]['after'].add(other) order[key]['after'].add(other)
order[other]['before'].add(key) order[other]['before'].add(key)
@ -163,13 +163,13 @@ class InstallabilitySolver(InstallabilityTester):
other_rms.add(other) other_rms.add(other)
for other in (other_adds - other_rms): for other in (other_adds - other_rms):
if debug_solver and other != key and other not in order[key]['after']: if debug_solver and other != key and other not in order[key]['after']: # pragma: no cover
print("N: Dependency induced order (add): %s before %s" % (key, other)) print("N: Dependency induced order (add): %s before %s" % (key, other))
order[key]['after'].add(other) order[key]['after'].add(other)
order[other]['before'].add(key) order[other]['before'].add(key)
for other in (other_rms - other_adds): for other in (other_rms - other_adds):
if debug_solver and other != key and other not in order[key]['before']: if debug_solver and other != key and other not in order[key]['before']: # pragma: no cover
print("N: Dependency induced order (remove): %s before %s" % (key, other)) print("N: Dependency induced order (remove): %s before %s" % (key, other))
order[key]['before'].add(other) order[key]['before'].add(other)
order[other]['after'].add(key) order[other]['after'].add(key)
@ -209,7 +209,7 @@ class InstallabilitySolver(InstallabilityTester):
so_after.update(order[n]['after']) so_after.update(order[n]['after'])
merged[n] = scc_id merged[n] = scc_id
del order[n] del order[n]
if debug_solver: if debug_solver: # pragma: no cover
print("N: SCC: %s -- %s" % (scc_id, str(sorted(com)))) print("N: SCC: %s -- %s" % (scc_id, str(sorted(com))))
for com in comps: for com in comps:
@ -223,32 +223,31 @@ class InstallabilitySolver(InstallabilityTester):
order[node]['before'] = nbefore order[node]['before'] = nbefore
order[node]['after'] = nafter order[node]['after'] = nafter
if debug_solver: # pragma: no cover
if debug_solver:
print("N: -- PARTIAL ORDER --") print("N: -- PARTIAL ORDER --")
initial_round = [] initial_round = []
for com in sorted(order): for com in sorted(order):
if debug_solver and order[com]['before']: if debug_solver and order[com]['before']: # pragma: no cover
print("N: %s <= %s" % (com, str(sorted(order[com]['before'])))) print("N: %s <= %s" % (com, str(sorted(order[com]['before']))))
if not order[com]['after']: if not order[com]['after']:
# This component can be scheduled immediately, add it # This component can be scheduled immediately, add it
# to the queue # to the queue
initial_round.append(com) initial_round.append(com)
elif debug_solver: elif debug_solver: # pragma: no cover
print("N: %s >= %s" % (com, str(sorted(order[com]['after'])))) print("N: %s >= %s" % (com, str(sorted(order[com]['after']))))
queue.extend(sorted(initial_round, key=len)) queue.extend(sorted(initial_round, key=len))
del initial_round del initial_round
if debug_solver: if debug_solver: # pragma: no cover
print("N: -- END PARTIAL ORDER --") print("N: -- END PARTIAL ORDER --")
print("N: -- LINEARIZED ORDER --") print("N: -- LINEARIZED ORDER --")
for cur in iter_except(queue.popleft, IndexError): for cur in iter_except(queue.popleft, IndexError):
if order[cur]['after'] <= emitted and cur not in emitted: if order[cur]['after'] <= emitted and cur not in emitted:
# This item is ready to be emitted right now # This item is ready to be emitted right now
if debug_solver: if debug_solver: # pragma: no cover
print("N: %s -- %s" % (cur, sorted(scc[cur]))) print("N: %s -- %s" % (cur, sorted(scc[cur])))
emitted.add(cur) emitted.add(cur)
result.append([key2item[x] for x in scc[cur]]) result.append([key2item[x] for x in scc[cur]])
@ -259,12 +258,11 @@ class InstallabilitySolver(InstallabilityTester):
# - else, it will be dropped and re-added later. # - else, it will be dropped and re-added later.
queue.extend(sorted(order[cur]['before'] - emitted, key=len)) queue.extend(sorted(order[cur]['before'] - emitted, key=len))
if debug_solver: if debug_solver: # pragma: no cover
print("N: -- END LINEARIZED ORDER --") print("N: -- END LINEARIZED ORDER --")
return result return result
def _compute_scc(self, order, ptable): def _compute_scc(self, order, ptable):
""" """
Tarjan's algorithm and topological sorting implementation in Python Tarjan's algorithm and topological sorting implementation in Python
@ -306,7 +304,7 @@ class InstallabilitySolver(InstallabilityTester):
return result return result
def _dump_groups(self, groups): def _dump_groups(self, groups): # pragma: no cover
print("N: === Groups ===") print("N: === Groups ===")
for (item, adds, rms) in groups: for (item, adds, rms) in groups:
print("N: %s => A: %s, R: %s" % (str(item), str(adds), str(rms))) print("N: %s => A: %s, R: %s" % (str(item), str(adds), str(rms)))

View File

@ -168,7 +168,7 @@ class InstallabilityTester(object):
:param pkg_id The id of the package :param pkg_id The id of the package
""" """
if pkg_id not in self._universe: if pkg_id not in self._universe: # pragma: no cover
raise KeyError(str(pkg_id)) raise KeyError(str(pkg_id))
if pkg_id in self._broken: if pkg_id in self._broken:
@ -197,7 +197,7 @@ class InstallabilityTester(object):
KeyError. KeyError.
""" """
if pkg_id not in self._universe: if pkg_id not in self._universe: # pragma: no cover
raise KeyError(str(pkg_id)) raise KeyError(str(pkg_id))
self._cache_broken.discard(pkg_id) self._cache_broken.discard(pkg_id)
@ -231,7 +231,7 @@ class InstallabilityTester(object):
self._stats.is_installable_calls += 1 self._stats.is_installable_calls += 1
if pkg_id not in self._universe: if pkg_id not in self._universe: # pragma: no cover
raise KeyError(str(pkg_id)) raise KeyError(str(pkg_id))
if pkg_id not in self._testing or pkg_id in self._broken: if pkg_id not in self._testing or pkg_id in self._broken:

View File

@ -69,14 +69,14 @@ class BasePolicy(object):
if self.options.verbose or type in ("E", "W"): if self.options.verbose or type in ("E", "W"):
print("%s: [%s] - %s" % (type, time.asctime(), msg)) print("%s: [%s] - %s" % (type, time.asctime(), msg))
def register_hints(self, hint_parser): def register_hints(self, hint_parser): # pragma: no cover
"""Register new hints that this policy accepts """Register new hints that this policy accepts
:param hint_parser: An instance of HintParser (see HintParser.register_hint_type) :param hint_parser: An instance of HintParser (see HintParser.register_hint_type)
""" """
pass pass
def initialise(self, britney): def initialise(self, britney): # pragma: no cover
"""Called once to make the policy initialise any data structures """Called once to make the policy initialise any data structures
This is useful for e.g. parsing files or other "heavy do-once" work. This is useful for e.g. parsing files or other "heavy do-once" work.
@ -85,7 +85,7 @@ class BasePolicy(object):
""" """
pass pass
def save_state(self, britney): def save_state(self, britney): # pragma: no cover
"""Called once at the end of the run to make the policy save any persistent data """Called once at the end of the run to make the policy save any persistent data
Note this will *not* be called for "dry-runs" as such runs should not change Note this will *not* be called for "dry-runs" as such runs should not change
@ -103,7 +103,7 @@ class BasePolicy(object):
return self.apply_policy_impl(pinfo, suite, source_name, source_data_tdist, source_data_srcdist, excuse) return self.apply_policy_impl(pinfo, suite, source_name, source_data_tdist, source_data_srcdist, excuse)
@abstractmethod @abstractmethod
def apply_policy_impl(self, policy_info, suite, source_name, source_data_tdist, source_data_srcdist, excuse): def apply_policy_impl(self, policy_info, suite, source_name, source_data_tdist, source_data_srcdist, excuse): # pragma: no cover
"""Apply a policy on a given source migration """Apply a policy on a given source migration
Britney will call this method on a given source package, when Britney will call this method on a given source package, when
@ -208,7 +208,7 @@ class AgePolicy(BasePolicy):
def __init__(self, options, suite_info, mindays): def __init__(self, options, suite_info, mindays):
super().__init__('age', options, suite_info, {'unstable'}) super().__init__('age', options, suite_info, {'unstable'})
self._min_days = mindays self._min_days = mindays
if options.default_urgency not in mindays: if options.default_urgency not in mindays: # pragma: no cover
raise ValueError("Missing age-requirement for default urgency (MINDAYS_%s)" % options.default_urgency) raise ValueError("Missing age-requirement for default urgency (MINDAYS_%s)" % options.default_urgency)
self._min_days_default = mindays[options.default_urgency] self._min_days_default = mindays[options.default_urgency]
# britney's "day" begins at 3pm # britney's "day" begins at 3pm

View File

@ -675,6 +675,6 @@ def read_release_file(suite_dir):
with open(release_file) as fd: with open(release_file) as fd:
tag_file = iter(apt_pkg.TagFile(fd)) tag_file = iter(apt_pkg.TagFile(fd))
result = next(tag_file) result = next(tag_file)
if next(tag_file, None) is not None: if next(tag_file, None) is not None: # pragma: no cover
raise TypeError("%s has more than one paragraph" % release_file) raise TypeError("%s has more than one paragraph" % release_file)
return result return result