43
44
from systemimage.config import config
44
45
from systemimage.download import DuplicateDestinationError
45
46
from systemimage.gpg import Context, SignatureError
46
from systemimage.state import State
47
from systemimage.helpers import calculate_signature
48
from systemimage.state import ChecksumError, State
47
49
from systemimage.testing.demo import DemoDevice
48
50
from systemimage.testing.helpers import (
49
51
ServerTestBase, configuration, copy, data_path, get_index,
1549
1553
['http://localhost:8980/3/4/5.txt.asc',
1550
1554
'http://localhost:8980/5/6/5.txt.asc',
1558
class TestMiscellaneous(ServerTestBase):
1559
"""Test a few additional things for full code coverage."""
1561
INDEX_FILE = 'index_13.json'
1562
CHANNEL_FILE = 'channels_06.json'
1567
def test_checksum_error(self):
1568
# _download_files() verifies the checksums of all the downloaded
1569
# files. If any of them fail, you get an exception.
1570
self._setup_server_keyrings()
1572
state.run_until('download_files')
1573
# It's tricky to cause a checksum error. We can't corrupt the local
1574
# downloaded copy of the data file because _download_files() doesn't
1575
# give us a good hook into the post-download, pre-checksum logic. We
1576
# can't corrupt the server file because the lower-level downloading
1577
# logic will complain. Instead, we mock the calculate_signature()
1578
# function to produce a broken checksum for one of the files.
1579
real_signature = None
1580
def broken_calc(fp, hash_class=None):
1581
nonlocal real_signature
1582
signature = calculate_signature(fp, hash_class)
1583
if os.path.basename(fp.name) == '6.txt':
1584
real_signature = signature
1585
return BAD_SIGNATURE
1587
with patch('systemimage.state.calculate_signature', broken_calc):
1588
with self.assertRaises(ChecksumError) as cm:
1589
state.run_thru('download_files')
1590
self.assertEqual(os.path.basename(cm.exception.destination), '6.txt')
1591
self.assertEqual(cm.exception.got, BAD_SIGNATURE)
1592
self.assertIsNotNone(real_signature)
1593
self.assertEqual(cm.exception.expected, real_signature)
1596
def test_get_blacklist_2_finds_no_blacklist(self):
1597
# Getting the blacklist can fail even the second time. That's fine,
1598
# but output gets logged.
1599
self._setup_server_keyrings()
1601
# we want get_blacklist_1 to fail with a SignatureError so that it
1602
# will try to get the master key and then attempt a refetch of the
1603
# blacklist. Let's just corrupt the original blacklist file.
1604
blacklist = os.path.join(self._serverdir, 'gpg', 'blacklist.tar.xz')
1605
with open(blacklist, 'ba+') as fp:
1607
state.run_until('get_blacklist_2')
1608
# Now we delete the blacklist file from the server, so as to trigger
1609
# the expected log message.
1610
os.remove(blacklist)
1611
with patch('systemimage.state.log.info') as capture:
1612
state.run_thru('get_blacklist_2')
1613
self.assertEqual(capture.call_args,
1614
call('No blacklist found on second attempt'))
1615
# Even though there's no blacklist file, everything still gets
1616
# downloaded correctly.
1617
state.run_until('reboot')
1618
path = os.path.join(config.updater.cache_partition, 'ubuntu_command')
1619
with open(path, 'r', encoding='utf-8') as fp:
1621
self.assertMultiLineEqual(command, """\
1622
load_keyring image-master.tar.xz image-master.tar.xz.asc
1623
load_keyring image-signing.tar.xz image-signing.tar.xz.asc
1624
load_keyring device-signing.tar.xz device-signing.tar.xz.asc
1627
update 6.txt 6.txt.asc
1628
update 7.txt 7.txt.asc
1629
update 5.txt 5.txt.asc