diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2017-06-27 17:33:43 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-07-06 14:38:14 +0100 |
commit | 76f149e3845ecae9e07a428c8be422019dcec9b1 (patch) | |
tree | 4bc312d7bc9954b6dbd92ad0fcc1168acc32bca1 /scripts/lib | |
parent | 17266ae2dd2c5a22c7af84427b0ca11de481c21d (diff) | |
download | poky-76f149e3845ecae9e07a428c8be422019dcec9b1.tar.gz |
yocto-compat-layer.py: make signature check code reusable
This moves the main content of test_signature into a helper
function. It can be reused by arbitrary tests that need to do
a before/after signature comparison. Long-term this might even
be useful in oeqa itself.
(From OE-Core rev: ecc9a1f9ceec9996aeb2c602846d51277de0b4a5)
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib')
-rw-r--r-- | scripts/lib/compatlayer/__init__.py | 66 | ||||
-rw-r--r-- | scripts/lib/compatlayer/cases/common.py | 62 |
2 files changed, 70 insertions, 58 deletions
diff --git a/scripts/lib/compatlayer/__init__.py b/scripts/lib/compatlayer/__init__.py index 451e1de950..7197e850e4 100644 --- a/scripts/lib/compatlayer/__init__.py +++ b/scripts/lib/compatlayer/__init__.py | |||
@@ -324,3 +324,69 @@ def get_depgraph(targets=['world'], failsafe=False): | |||
324 | if depgraph is None: | 324 | if depgraph is None: |
325 | raise RuntimeError('Could not retrieve the depgraph.') | 325 | raise RuntimeError('Could not retrieve the depgraph.') |
326 | return depgraph | 326 | return depgraph |
327 | |||
328 | def compare_signatures(old_sigs, curr_sigs): | ||
329 | ''' | ||
330 | Compares the result of two get_signatures() calls. Returns None if no | ||
331 | problems found, otherwise a string that can be used as additional | ||
332 | explanation in self.fail(). | ||
333 | ''' | ||
334 | # task -> (old signature, new signature) | ||
335 | sig_diff = {} | ||
336 | for task in old_sigs: | ||
337 | if task in curr_sigs and \ | ||
338 | old_sigs[task] != curr_sigs[task]: | ||
339 | sig_diff[task] = (old_sigs[task], curr_sigs[task]) | ||
340 | |||
341 | if not sig_diff: | ||
342 | return None | ||
343 | |||
344 | # Beware, depgraph uses task=<pn>.<taskname> whereas get_signatures() | ||
345 | # uses <pn>:<taskname>. Need to convert sometimes. The output follows | ||
346 | # the convention from get_signatures() because that seems closer to | ||
347 | # normal bitbake output. | ||
348 | def sig2graph(task): | ||
349 | pn, taskname = task.rsplit(':', 1) | ||
350 | return pn + '.' + taskname | ||
351 | def graph2sig(task): | ||
352 | pn, taskname = task.rsplit('.', 1) | ||
353 | return pn + ':' + taskname | ||
354 | depgraph = get_depgraph(failsafe=True) | ||
355 | depends = depgraph['tdepends'] | ||
356 | |||
357 | # If a task A has a changed signature, but none of its | ||
358 | # dependencies, then we need to report it because it is | ||
359 | # the one which introduces a change. Any task depending on | ||
360 | # A (directly or indirectly) will also have a changed | ||
361 | # signature, but we don't need to report it. It might have | ||
362 | # its own changes, which will become apparent once the | ||
363 | # issues that we do report are fixed and the test gets run | ||
364 | # again. | ||
365 | sig_diff_filtered = [] | ||
366 | for task, (old_sig, new_sig) in sig_diff.items(): | ||
367 | deps_tainted = False | ||
368 | for dep in depends.get(sig2graph(task), ()): | ||
369 | if graph2sig(dep) in sig_diff: | ||
370 | deps_tainted = True | ||
371 | break | ||
372 | if not deps_tainted: | ||
373 | sig_diff_filtered.append((task, old_sig, new_sig)) | ||
374 | |||
375 | msg = [] | ||
376 | msg.append('%d signatures changed, initial differences (first hash before, second after):' % | ||
377 | len(sig_diff)) | ||
378 | for diff in sorted(sig_diff_filtered): | ||
379 | recipe, taskname = diff[0].rsplit(':', 1) | ||
380 | cmd = 'bitbake-diffsigs --task %s %s --signature %s %s' % \ | ||
381 | (recipe, taskname, diff[1], diff[2]) | ||
382 | msg.append(' %s: %s -> %s' % diff) | ||
383 | msg.append(' %s' % cmd) | ||
384 | try: | ||
385 | output = check_command('Determining signature difference failed.', | ||
386 | cmd).decode('utf-8') | ||
387 | except RuntimeError as error: | ||
388 | output = str(error) | ||
389 | if output: | ||
390 | msg.extend([' ' + line for line in output.splitlines()]) | ||
391 | msg.append('') | ||
392 | return '\n'.join(msg) | ||
diff --git a/scripts/lib/compatlayer/cases/common.py b/scripts/lib/compatlayer/cases/common.py index 4c8a5439ec..55e8ba4c51 100644 --- a/scripts/lib/compatlayer/cases/common.py +++ b/scripts/lib/compatlayer/cases/common.py | |||
@@ -4,7 +4,7 @@ | |||
4 | import glob | 4 | import glob |
5 | import os | 5 | import os |
6 | import unittest | 6 | import unittest |
7 | from compatlayer import get_signatures, LayerType, check_command, get_depgraph | 7 | from compatlayer import get_signatures, LayerType, check_command, get_depgraph, compare_signatures |
8 | from compatlayer.case import OECompatLayerTestCase | 8 | from compatlayer.case import OECompatLayerTestCase |
9 | 9 | ||
10 | class CommonCompatLayer(OECompatLayerTestCase): | 10 | class CommonCompatLayer(OECompatLayerTestCase): |
@@ -47,61 +47,7 @@ class CommonCompatLayer(OECompatLayerTestCase): | |||
47 | raise unittest.SkipTest("Not testing for signature changes in a software layer %s." \ | 47 | raise unittest.SkipTest("Not testing for signature changes in a software layer %s." \ |
48 | % self.tc.layer['name']) | 48 | % self.tc.layer['name']) |
49 | 49 | ||
50 | # task -> (old signature, new signature) | ||
51 | sig_diff = {} | ||
52 | curr_sigs, _ = get_signatures(self.td['builddir'], failsafe=True) | 50 | curr_sigs, _ = get_signatures(self.td['builddir'], failsafe=True) |
53 | for task in self.td['sigs']: | 51 | msg = compare_signatures(self.td['sigs'], curr_sigs) |
54 | if task in curr_sigs and \ | 52 | if msg is not None: |
55 | self.td['sigs'][task] != curr_sigs[task]: | 53 | self.fail('Adding layer %s changed signatures.\n%s' % (self.tc.layer['name'], msg)) |
56 | sig_diff[task] = (self.td['sigs'][task], curr_sigs[task]) | ||
57 | |||
58 | if sig_diff: | ||
59 | # Beware, depgraph uses task=<pn>.<taskname> whereas get_signatures() | ||
60 | # uses <pn>:<taskname>. Need to convert sometimes. The output follows | ||
61 | # the convention from get_signatures() because that seems closer to | ||
62 | # normal bitbake output. | ||
63 | def sig2graph(task): | ||
64 | pn, taskname = task.rsplit(':', 1) | ||
65 | return pn + '.' + taskname | ||
66 | def graph2sig(task): | ||
67 | pn, taskname = task.rsplit('.', 1) | ||
68 | return pn + ':' + taskname | ||
69 | depgraph = get_depgraph(failsafe=True) | ||
70 | depends = depgraph['tdepends'] | ||
71 | |||
72 | # If a task A has a changed signature, but none of its | ||
73 | # dependencies, then we need to report it because it is | ||
74 | # the one which introduces a change. Any task depending on | ||
75 | # A (directly or indirectly) will also have a changed | ||
76 | # signature, but we don't need to report it. It might have | ||
77 | # its own changes, which will become apparent once the | ||
78 | # issues that we do report are fixed and the test gets run | ||
79 | # again. | ||
80 | sig_diff_filtered = [] | ||
81 | for task, (old_sig, new_sig) in sig_diff.items(): | ||
82 | deps_tainted = False | ||
83 | for dep in depends.get(sig2graph(task), ()): | ||
84 | if graph2sig(dep) in sig_diff: | ||
85 | deps_tainted = True | ||
86 | break | ||
87 | if not deps_tainted: | ||
88 | sig_diff_filtered.append((task, old_sig, new_sig)) | ||
89 | |||
90 | msg = [] | ||
91 | msg.append('Layer %s changed %d signatures, initial differences (first hash without, second with layer):' % | ||
92 | (self.tc.layer['name'], len(sig_diff))) | ||
93 | for diff in sorted(sig_diff_filtered): | ||
94 | recipe, taskname = diff[0].rsplit(':', 1) | ||
95 | cmd = 'bitbake-diffsigs --task %s %s --signature %s %s' % \ | ||
96 | (recipe, taskname, diff[1], diff[2]) | ||
97 | msg.append(' %s: %s -> %s' % diff) | ||
98 | msg.append(' %s' % cmd) | ||
99 | try: | ||
100 | output = check_command('Determining signature difference failed.', | ||
101 | cmd).decode('utf-8') | ||
102 | except RuntimeError as error: | ||
103 | output = str(error) | ||
104 | if output: | ||
105 | msg.extend([' ' + line for line in output.splitlines()]) | ||
106 | msg.append('') | ||
107 | self.fail('\n'.join(msg)) | ||