summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2017-06-27 17:33:43 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-07-06 14:38:14 +0100
commit76f149e3845ecae9e07a428c8be422019dcec9b1 (patch)
tree4bc312d7bc9954b6dbd92ad0fcc1168acc32bca1 /scripts
parent17266ae2dd2c5a22c7af84427b0ca11de481c21d (diff)
downloadpoky-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')
-rw-r--r--scripts/lib/compatlayer/__init__.py66
-rw-r--r--scripts/lib/compatlayer/cases/common.py62
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
328def 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 @@
4import glob 4import glob
5import os 5import os
6import unittest 6import unittest
7from compatlayer import get_signatures, LayerType, check_command, get_depgraph 7from compatlayer import get_signatures, LayerType, check_command, get_depgraph, compare_signatures
8from compatlayer.case import OECompatLayerTestCase 8from compatlayer.case import OECompatLayerTestCase
9 9
10class CommonCompatLayer(OECompatLayerTestCase): 10class 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))