def test_bad_partition_role(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: with-the-punches """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'Bad role: with-the-punches')
def test_custom_without_fs_type(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: custom """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'fs-type is required')
def test_invalid_fs_type_for_custom(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: custom fs-type: zfs """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'Invalid fs-type: zfs')
def test_explicit_type_for_esp(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: ESP type: XX """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'Invalid explicit type id: XX')
def test_explicit_fs_type_for_raw(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: raw fs-type: ext4 """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual( str(cm.exception), 'No fs-type allowed for raw partitions: ext4')
def test_raw_destination(self): # With fs-type 'raw', no file destination is allowed. stream = StringIO("""\ partition-scheme: MBR partitions: - role: raw files: - source: a/b/c dest: e/f/g """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'No dest allowed')
def test_raw_too_many_default_offsets(self): # With fs-type 'raw' only one file is allowed to have a default offset. stream = StringIO("""\ partition-scheme: MBR partitions: - role: raw files: - source: a/b/c - source: d/e/f """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'Only one default offset allowed')
def test_offsets_not_allowed_for_fs_type(self): # With an explicit fs-type, only source/dest are allowed. stream = StringIO("""\ partition-scheme: MBR partitions: - role: custom fs-type: ext4 files: - source: a/b/c offset: 1M """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'offset not allowed')
def test_missing_dest_for_fs_type(self): # With an explicit fs-type, only source/dest are required. stream = StringIO("""\ partition-scheme: MBR partitions: - role: custom fs-type: ext4 files: - source: a/b/c - source: d/e/f dest: g/h/i """) with self.assertRaises(ValueError) as cm: parse(stream) self.assertEqual(str(cm.exception), 'dest required for source: a/b/c')
def test_multiple_volumes_with_bootloader(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 100 second-image: schema: gpt structure: - type: 00000000-0000-0000-0000-0000feedface size: 200 third-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deafbead size: 300 """) self.assertEqual(len(gadget_spec.volumes), 3) self.assertEqual({ 'first-image': None, 'second-image': None, 'third-image': BootLoader.uboot, }, {key: gadget_spec.volumes[key].bootloader for key in gadget_spec.volumes} )
def test_parse(self): # Parse an image.yaml into a partitioning role instance. stream = StringIO("""\ partition-scheme: MBR partitions: - role: ESP size: 50M files: - source: grubx64.efi.signed dest: EFI/boot/grubx64.efi - source: shim.efi.signed dest: EFI/boot/bootx64.efi - source: grub.cfg dest: EFI/boot/grub.cfg """) image_spec = parse(stream) self.assertEqual(image_spec.scheme, 'MBR') self.assertEqual(len(image_spec.partitions), 1) partition = image_spec.partitions[0] self.assertIsNone(partition.name) self.assertEqual(partition.role, 'ESP') self.assertIsNone(partition.guid) self.assertEqual(partition.type_id, 'EF') self.assertIsNone(partition.offset) self.assertEqual(partition.size, MiB(50)) self.assertEqual(partition.fs_type, 'vfat') self.assertEqual(partition.files, [ ('grubx64.efi.signed', 'EFI/boot/grubx64.efi'), ('shim.efi.signed', 'EFI/boot/bootx64.efi'), ('grub.cfg', 'EFI/boot/grub.cfg'), ])
def test_content_a_multiple(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M filesystem: ext4 content: - source: subdir1/ target: 1/ - source: subdir2/ target: 2/ """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(len(partition0.content), 2) content0 = partition0.content[0] self.assertEqual(content0.source, 'subdir1/') self.assertEqual(content0.target, '1/') content1 = partition0.content[1] self.assertEqual(content1.source, 'subdir2/') self.assertEqual(content1.target, '2/')
def test_content_spec_b_multiple(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M content: - image: foo1.img - image: foo2.img offset: 2112 """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(len(partition0.content), 2) content0 = partition0.content[0] self.assertEqual(content0.image, 'foo1.img') self.assertIsNone(content0.offset) self.assertIsNone(content0.offset_write) self.assertIsNone(content0.size) content1 = partition0.content[1] self.assertEqual(content1.image, 'foo2.img') self.assertEqual(content1.offset, 2112) self.assertIsNone(content1.offset_write) self.assertIsNone(content1.size)
def test_minimal(self): gadget_spec = parse("""\ volumes: first-image: bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M """) self.assertEqual(gadget_spec.device_tree_origin, 'gadget') self.assertIsNone(gadget_spec.device_tree) self.assertEqual(gadget_spec.volumes.keys(), {'first-image'}) volume0 = gadget_spec.volumes['first-image'] self.assertEqual(volume0.schema, VolumeSchema.gpt) self.assertEqual(volume0.bootloader, BootLoader.uboot) self.assertIsNone(volume0.id) self.assertEqual(len(volume0.structures), 1) structure0 = volume0.structures[0] self.assertIsNone(structure0.name) self.assertEqual(structure0.offset, MiB(1)) self.assertIsNone(structure0.offset_write) self.assertEqual(structure0.size, MiB(400)) self.assertEqual( structure0.type, UUID(hex='00000000-0000-0000-0000-0000deadbeef')) self.assertIsNone(structure0.id) self.assertEqual(structure0.filesystem, FileSystemType.none) self.assertIsNone(structure0.filesystem_label) self.assertEqual(len(structure0.content), 0)
def test_raw_mbr(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: raw """) image_spec = parse(stream) self.assertEqual(image_spec.partitions[0].type_id, 'DA')
def test_custom_with_fs_type(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: custom fs-type: ext4 """) image_spec = parse(stream) self.assertEqual(image_spec.partitions[0].fs_type, 'ext4') self.assertEqual(image_spec.partitions[0].type_id, '83')
def test_custom_mbr_type_id(self): stream = StringIO("""\ partition-scheme: GPT partitions: - role: custom fs-type: ext4 """) image_spec = parse(stream) self.assertEqual(image_spec.partitions[0].type_id, '0FC63DAF-8483-4772-8E79-3D69D8477DE4')
def test_raw_gpt(self): stream = StringIO("""\ partition-scheme: GPT partitions: - role: raw """) image_spec = parse(stream) self.assertEqual( image_spec.partitions[0].type_id, '21686148-6449-6E6F-744E-656564454649')
def test_partition_offset_units(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: custom fs-type: ext4 offset: 1M """) image_spec = parse(stream) self.assertEqual(len(image_spec.partitions), 1) self.assertEqual(image_spec.partitions[0].offset, MiB(1))
def test_missing_schema(self): gadget_spec = parse("""\ volumes: first-image: bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M """) volume0 = gadget_spec.volumes['first-image'] self.assertEqual(volume0.schema, VolumeSchema.gpt)
def test_grub(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: grub structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M """) volume0 = gadget_spec.volumes['first-image'] self.assertEqual(volume0.bootloader, BootLoader.grub)
def test_2hex_volume_id(self): gadget_spec = parse("""\ volumes: first-image: bootloader: u-boot id: 80 structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M """) volume0 = gadget_spec.volumes['first-image'] self.assertEqual(volume0.id, '80')
def test_mbr_schema(self): gadget_spec = parse("""\ volumes: first-image: schema: mbr bootloader: u-boot structure: - type: ef size: 400M """) volume0 = gadget_spec.volumes['first-image'] self.assertEqual(volume0.schema, VolumeSchema.mbr)
def test_volume_filesystem_default_none(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(partition0.filesystem, FileSystemType.none)
def test_size_offset_suffix(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 3M """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(partition0.size, MiB(3))
def test_mbr_structure(self): gadget_spec = parse("""\ volumes: first-image: bootloader: u-boot structure: - type: mbr size: 400M """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(partition0.type, 'mbr') self.assertEqual(partition0.filesystem, FileSystemType.none)
def test_volume_offset(self): gadget_spec = parse("""\ volumes: first-image: bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M offset: 2112 """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(partition0.offset, 2112)
def test_volume_offset_write_relative(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M offset-write: some_label+2112 """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(partition0.offset_write, ('some_label', 2112))
def test_volume_name(self): gadget_spec = parse("""\ volumes: first-image: bootloader: u-boot structure: - name: my volume type: 00000000-0000-0000-0000-0000deadbeef size: 400M """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(partition0.name, 'my volume') self.assertEqual(partition0.filesystem_label, 'my volume')
def test_implicit_gpt_with_hybrid_type(self): gadget_spec = parse("""\ volumes: first-image: bootloader: u-boot structure: - type: 80,00000000-0000-0000-0000-0000deadbeef size: 400M """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual( partition0.type, ('80', UUID(hex='00000000-0000-0000-0000-0000deadbeef')))
def extract(snap_path): # pragma: no cover """Extract the image.yml file from a path to a .snap. :param snap_path: File system path to a .snap. :type snap_path: str :return: The dictionary represented by the meta/image.yaml file contained in the snap. :rtype: dict """ with TemporaryDirectory() as destination: unpack_dir = os.path.join(destination, 'unpack') run(['unsquashfs', '-d', unpack_dir, snap_path], stderr=PIPE, stdout=PIPE) image_yaml = os.path.join(unpack_dir, 'meta', 'image.yaml') return parse(image_yaml)
def test_volume_id(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M id: 00000000-0000-0000-0000-0000deadbeef """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual( partition0.id, UUID(hex='00000000-0000-0000-0000-0000deadbeef'))
def test_device_tree(self): gadget_spec = parse("""\ device-tree-origin: kernel device-tree: dtree volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M """) self.assertEqual(gadget_spec.device_tree_origin, 'kernel') self.assertEqual(gadget_spec.device_tree, 'dtree') self.assertEqual(gadget_spec.volumes.keys(), {'first-image'})
def test_mbr_with_hybrid_type(self): gadget_spec = parse("""\ volumes: first-image: schema: mbr bootloader: u-boot structure: - type: ef,00000000-0000-0000-0000-0000deadbeef size: 400M """) volume0 = gadget_spec.volumes['first-image'] self.assertEqual(volume0.schema, VolumeSchema.mbr) partition0 = volume0.structures[0] self.assertEqual( partition0.type, ('EF', UUID(hex='00000000-0000-0000-0000-0000deadbeef')))
def extract(snap_path): # pragma: nocover """Extract the gadget.yml file from a path to a .snap. :param snap_path: File system path to a .snap. :type snap_path: str :return: The dictionary represented by the meta/gadget.yaml file contained in the snap. :rtype: dict """ with TemporaryDirectory() as destination: gadget_dir = os.path.join(destination, 'gadget') run(['unsquashfs', '-d', gadget_dir, snap_path], stderr=PIPE, stdout=PIPE) gadget_yaml = os.path.join(gadget_dir, 'meta', 'gadget.yaml') return parse(gadget_yaml)
def test_raw_offsets(self): stream = StringIO("""\ partition-scheme: MBR partitions: - role: raw files: - source: a/b/c offset: 1M - source: d/e/f - source: g/h/i offset: 1024 """) image_spec = parse(stream) self.assertEqual(len(image_spec.partitions), 1) self.assertEqual(image_spec.partitions[0].files, [ # This are file sources and offsets. ('a/b/c', MiB(1)), ('d/e/f', 0), ('g/h/i', 1024), ])
def test_content_spec_b_offset_write_label(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M content: - image: foo.img offset-write: label+2112 """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(len(partition0.content), 1) content0 = partition0.content[0] self.assertEqual(content0.image, 'foo.img') self.assertIsNone(content0.offset) self.assertEqual(content0.offset_write, ('label', 2112)) self.assertIsNone(content0.size)
def test_content_spec_b_size_suffix(self): gadget_spec = parse("""\ volumes: first-image: schema: gpt bootloader: u-boot structure: - type: 00000000-0000-0000-0000-0000deadbeef size: 400M content: - image: foo.img size: 1M """) volume0 = gadget_spec.volumes['first-image'] partition0 = volume0.structures[0] self.assertEqual(len(partition0.content), 1) content0 = partition0.content[0] self.assertEqual(content0.image, 'foo.img') self.assertIsNone(content0.offset) self.assertIsNone(content0.offset_write) self.assertEqual(content0.size, MiB(1))
def test_bad_scheme(self): with self.assertRaises(ValueError) as cm: parse(StringIO('partition-scheme: XXX\n')) self.assertEqual(str(cm.exception), 'XXX')