def test_all():
    logging.basicConfig(level=logging.DEBUG)
    _logger = logging.getLogger(os.path.basename(__file__))

    s0 = set()

    v0 = Objects.VolumeObject()
    v1 = Objects.VolumeObject()

    s0.add(v0)
    s0.add(v1)

    _logger.debug("len(s0) = %r" % len(s0))
    assert len(s0) == 2

    f0 = Objects.FileObject()
    f1 = Objects.FileObject()
    f0.volume_object = v0
    f1.volume_object = v0

    s1 = set()
    s1.add(f0.volume_object)
    s1.add(f1.volume_object)
    _logger.debug("len(s1) = %r" % len(s1))
    assert len(s1) == 1
Example #2
0
def test_disk_image_in_file_system():
    dobj = Objects.DFXMLObject(version="1.2.0")

    vobj = Objects.VolumeObject()
    vobj.ftype_str = "iso9660"
    dobj.append(vobj)

    fobj_vobj = Objects.FileObject()
    fobj_vobj.sha512 = TEST_HASH_1
    vobj.append(fobj_vobj)

    diobj = Objects.DiskImageObject()
    vobj.append(diobj)

    fobj_diobj = Objects.FileObject()
    fobj_diobj.alloc_inode = False
    fobj_diobj.alloc_name = False
    fobj_diobj.sha512 = TEST_HASH_2
    diobj.append(fobj_diobj)

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        vobj_reconst = dobj_reconst.volumes[0]
        diobj_reconst = vobj_reconst.disk_images[0]
        assert vobj_reconst.files[0].sha512 == TEST_HASH_1
        assert diobj_reconst.files[0].sha512 == TEST_HASH_2
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
Example #3
0
def test_volume_error_roundtrip_with_file():
    dobj = Objects.DFXMLObject(version="1.2.0")
    vobj = Objects.VolumeObject()
    dobj.append(vobj)

    vobj.error = ERROR_STRING_V

    assert vobj.error == ERROR_STRING_V

    fobj = Objects.FileObject()
    vobj.append(fobj)

    fobj.error = ERROR_STRING_F

    assert fobj.error == ERROR_STRING_F
    assert vobj.error == ERROR_STRING_V

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        vobj_reconst = dobj_reconst.volumes[0]
        fobj_reconst = vobj_reconst.files[0]
        assert vobj_reconst.error == ERROR_STRING_V
        assert fobj_reconst.error == ERROR_STRING_F
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
Example #4
0
def test_hfsplus_in_hfs():
    dobj = Objects.DFXMLObject(version="1.2.0")
    vobj_outer = Objects.VolumeObject()
    vobj_outer.ftype_str = "hfs"
    dobj.append(vobj_outer)

    vobj_inner = Objects.VolumeObject()
    vobj_inner.ftype_str = "hfsplus"
    vobj_outer.append(vobj_inner)

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        vobj_outer_reconst = dobj_reconst.volumes[0]
        vobj_inner_reconst = vobj_outer_reconst.volumes[0]
        assert isinstance(vobj_inner_reconst, Objects.VolumeObject)
        assert vobj_outer_reconst.ftype_str == "hfs"
        assert vobj_inner_reconst.ftype_str == "hfsplus"
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
Example #5
0
def test_empty_object():
    dobj = Objects.DFXMLObject(version="1.2.0")
    vobj = Objects.VolumeObject()
    dobj.append(vobj)

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        vobj_reconst = dobj_reconst.volumes[0]
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
def test_all():
    dobj = Objects.DFXMLObject(version="1.2.0")

    # Make objects for simple appends.
    diobj_0 = Objects.DiskImageObject()
    psobj_0 = Objects.PartitionSystemObject()
    pobj_0 = Objects.PartitionObject()
    vobj_0 = Objects.VolumeObject()
    vobj_0.ftype_str = "hfs"
    fobj_0 = Objects.FileObject()

    # Make objects for more exotic appends.
    psobj_1 = Objects.PartitionSystemObject()
    vobj_1 = Objects.VolumeObject()
    vobj_1.ftype_str = "hfsplus"
    fobj_dobj_1 = Objects.FileObject()
    fobj_dobj_1.alloc_inode = False
    fobj_dobj_1.alloc_name = False
    fobj_psobj_1 = Objects.FileObject()
    fobj_psobj_1.alloc_inode = False
    fobj_psobj_1.alloc_name = False
    fobj_pobj_1 = Objects.FileObject()
    fobj_pobj_1.alloc_inode = False
    fobj_pobj_1.alloc_name = False

    # Do simple appends.
    dobj.append(diobj_0)
    diobj_0.append(psobj_0)
    psobj_0.append(pobj_0)
    pobj_0.append(vobj_0)
    vobj_0.append(fobj_0)

    # Do more exotic appends.
    pobj_0.append(psobj_1)
    vobj_0.append(vobj_1)
    dobj.append(fobj_dobj_1)
    psobj_0.append(fobj_psobj_1)
    pobj_0.append(fobj_pobj_1)
Example #7
0
def test_all():
    logging.basicConfig(level=logging.DEBUG)
    _logger = logging.getLogger(os.path.basename(__file__))

    v0 = Objects.VolumeObject()

    v0.sector_size = 512
    v0.block_size = 4096
    v0.partition_offset = 32256
    v0.ftype = -1
    assert v0.ftype == -1
    v0.ftype_str = 1
    v0.block_count = 100000
    v0.allocated_only = False
    v0.first_block = 0
    v0.last_block = v0.block_count

    _logger.debug(repr(v0))
    v1 = eval("Objects." + repr(v0))

    e0 = v0.to_Element()
    _logger.debug("e0 = %r" % e0)

    v2 = Objects.VolumeObject()
    v2.populate_from_Element(e0)

    v1.block_size = 512
    v2.partition_offset = v0.partition_offset + v0.block_count*v0.block_size

    d01 = v0.compare_to_other(v1)
    d02 = v0.compare_to_other(v2)

    _logger.debug("d01 = %r" % d01)
    assert d01 == set(["block_size"])

    _logger.debug("d02 = %r" % d02)
    assert d02 == set(["partition_offset"])
Example #8
0
def test_volume_error_roundtrip_with_file_and_extns():
    dobj = Objects.DFXMLObject(version="1.2.0")
    vobj = Objects.VolumeObject()
    dobj.append(vobj)

    ET.register_namespace("testextra", XMLNS_TEST_EXTRA)

    vobj.error = ERROR_STRING_V

    # Dummy up a non-DFXML namespace element.  This should be appendable.
    e = ET.Element("{%s}extra_element" % XMLNS_TEST_EXTRA)
    e.text = "Extra content"
    vobj.externals.append(e)

    # Dummy up a non-DFXML namespace 'error' element.  This should be appendable.
    e = ET.Element("{%s}error" % XMLNS_TEST_EXTRA)
    e.text = "Extra error"
    vobj.externals.append(e)

    assert vobj.error == ERROR_STRING_V

    fobj = Objects.FileObject()
    vobj.append(fobj)

    fobj.error = ERROR_STRING_F

    assert fobj.error == ERROR_STRING_F
    assert vobj.error == ERROR_STRING_V

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        vobj_reconst = dobj_reconst.volumes[0]
        fobj_reconst = vobj_reconst.files[0]
        assert vobj_reconst.error == ERROR_STRING_V
        assert fobj_reconst.error == ERROR_STRING_F
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
Example #9
0
def test_error_after_file_system():
    #TODO Bump version when feature branch merged into schema.
    dobj = Objects.DFXMLObject(version="1.2.0+")
    diobj = Objects.DiskImageObject()
    dobj.append(diobj)

    diobj.error = ERROR_1

    vobj = Objects.VolumeObject()
    vobj.error = ERROR_2
    diobj.append(vobj)

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        diobj_reconst = dobj_reconst.disk_images[0]
        vobj_reconst = diobj_reconst.volumes[0]
        assert diobj_reconst.error == ERROR_1
        assert vobj_reconst.error == ERROR_2
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
Example #10
0
def _test_file_in_non_fs_levels_deep(include_disk_image,
                                     include_partition_system,
                                     include_partition, include_file_system):
    """
    This test follows a simple, vertical storage layer stack, but adds a file at each layer.
    """
    dobj = Objects.DFXMLObject(version="1.2.0")

    # Add file to top-level document.
    fobj_dobj = Objects.FileObject()
    fobj_dobj.alloc_inode = False
    fobj_dobj.alloc_name = False
    fobj_dobj.sha512 = TEST_HASH_1
    dobj.append(fobj_dobj)

    appender_stack = [dobj]

    if include_disk_image:
        # Add disk image to top-level document.
        diobj = Objects.DiskImageObject()
        appender_stack[-1].append(diobj)
        appender_stack.append(diobj)

        # Add file to disk image.
        fobj_diobj = Objects.FileObject()
        fobj_diobj.alloc_inode = False
        fobj_diobj.alloc_name = False
        fobj_diobj.sha512 = TEST_HASH_2
        diobj.append(fobj_diobj)

    if include_partition_system:
        # Add partition system to disk image.
        psobj = Objects.PartitionSystemObject()
        appender_stack[-1].append(psobj)
        appender_stack.append(psobj)

        # Add file to partition system.
        fobj_psobj = Objects.FileObject()
        fobj_psobj.alloc_inode = False
        fobj_psobj.alloc_name = False
        fobj_psobj.sha512 = TEST_HASH_3
        psobj.append(fobj_psobj)

    if include_partition:
        # Add partition to partition system, but not disk image.
        if not (include_disk_image and not include_partition_system):
            pobj = Objects.PartitionObject()
            appender_stack[-1].append(pobj)
            appender_stack.append(pobj)

            # Add file to partition.
            fobj_pobj = Objects.FileObject()
            fobj_pobj.alloc_inode = False
            fobj_pobj.alloc_name = False
            fobj_pobj.sha512 = TEST_HASH_4
            pobj.append(fobj_pobj)

    if include_file_system:
        # Add file system to anything but a partition system.
        if not (include_partition_system and not include_partition):
            vobj = Objects.VolumeObject()
            appender_stack[-1].append(vobj)
            appender_stack.append(vobj)

            # Add file to file system.
            fobj_vobj = Objects.FileObject()
            fobj_vobj.sha512 = TEST_HASH_5
            vobj.append(fobj_vobj)

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        container_stack = [dobj_reconst]
        assert dobj_reconst.files[0].sha512 == TEST_HASH_1

        if include_disk_image:
            diobj_reconst = container_stack[-1].disk_images[0]
            container_stack.append(diobj_reconst)
            assert diobj_reconst.files[0].sha512 == TEST_HASH_2

        if include_partition_system:
            psobj_reconst = container_stack[-1].partition_systems[0]
            container_stack.append(psobj_reconst)
            assert psobj_reconst.files[0].sha512 == TEST_HASH_3

        if include_partition:
            if not (include_disk_image and not include_partition_system):
                pobj_reconst = container_stack[-1].partitions[0]
                container_stack.append(pobj_reconst)
                assert pobj_reconst.files[0].sha512 == TEST_HASH_4

        if include_file_system:
            if not (include_partition_system and not include_partition):
                vobj_reconst = container_stack[-1].volumes[0]
                assert vobj_reconst.files[0].sha512 == TEST_HASH_5
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
Example #11
0
def _test_file_in_non_fs_levels_flat(include_disk_image,
                                     include_partition_system,
                                     include_partition, include_file_system):
    """
    This test follows a simple, horizontal storage layer stack (every container attached to top document object), and adds a file for each container.
    """
    dobj = Objects.DFXMLObject(version="1.2.0")

    # Add file to top-level document.
    fobj_dobj = Objects.FileObject()
    fobj_dobj.alloc_inode = False
    fobj_dobj.alloc_name = False
    fobj_dobj.sha512 = TEST_HASH_1
    dobj.append(fobj_dobj)

    if include_disk_image:
        # Add disk image.
        diobj = Objects.DiskImageObject()
        dobj.append(diobj)

        # Add file to disk image.
        fobj_diobj = Objects.FileObject()
        fobj_diobj.alloc_inode = False
        fobj_diobj.alloc_name = False
        fobj_diobj.sha512 = TEST_HASH_2
        diobj.append(fobj_diobj)

    if include_partition_system:
        # Add partition system.
        psobj = Objects.PartitionSystemObject()
        dobj.append(psobj)

        # Add file to partition system.
        fobj_psobj = Objects.FileObject()
        fobj_psobj.alloc_inode = False
        fobj_psobj.alloc_name = False
        fobj_psobj.sha512 = TEST_HASH_3
        psobj.append(fobj_psobj)

    if include_partition:
        # Add partition.
        pobj = Objects.PartitionObject()
        dobj.append(pobj)

        # Add file to partition.
        fobj_pobj = Objects.FileObject()
        fobj_pobj.alloc_inode = False
        fobj_pobj.alloc_name = False
        fobj_pobj.sha512 = TEST_HASH_4
        pobj.append(fobj_pobj)

    if include_file_system:
        # Add file system.
        vobj = Objects.VolumeObject()
        dobj.append(vobj)

        # Add file to file system.
        fobj_vobj = Objects.FileObject()
        fobj_vobj.sha512 = TEST_HASH_5
        vobj.append(fobj_vobj)

    # Do file I/O round trip.
    (tmp_filename, dobj_reconst) = libtest.file_round_trip_dfxmlobject(dobj)
    try:
        assert dobj_reconst.files[0].sha512 == TEST_HASH_1

        if include_disk_image:
            diobj_reconst = dobj_reconst.disk_images[0]
            assert diobj_reconst.files[0].sha512 == TEST_HASH_2

        if include_partition_system:
            psobj_reconst = dobj_reconst.partition_systems[0]
            assert psobj_reconst.files[0].sha512 == TEST_HASH_3

        if include_partition:
            pobj_reconst = dobj_reconst.partitions[0]
            assert pobj_reconst.files[0].sha512 == TEST_HASH_4

        if include_file_system:
            vobj_reconst = dobj_reconst.volumes[0]
            assert vobj_reconst.files[0].sha512 == TEST_HASH_5
    except:
        _logger.debug("tmp_filename = %r." % tmp_filename)
        raise
    os.remove(tmp_filename)
Example #12
0
def main():
    dobj = Objects.DFXMLObject(version="1.2.0")
    dobj.program = sys.argv[0]
    dobj.program_version = __version__
    dobj.command_line = " ".join(sys.argv)
    dobj.dc["type"] = "Example"
    dobj.add_creator_library("Python", ".".join(map(str, sys.version_info[0:3]))) #A bit of a bend, but gets the major version information out.
    dobj.add_creator_library("Objects.py", Objects.__version__)
    dobj.add_creator_library("dfxml.py", Objects.dfxml.__version__)

    vobj = Objects.VolumeObject()
    dobj.append(vobj)

    vobj.ftype_str = "examplefs"

    # Define file system position.
    vobj.byte_runs = Objects.ByteRuns()
    vbr = Objects.ByteRun()
    vobj.byte_runs.append(vbr)
    vbr.img_offset = FILE_SYSTEM_START
    vbr.len = DISK_IMAGE_SIZE - FILE_SYSTEM_START

    fobj_specs = [
      (
        "first_sector.bin",
        [
          (0, 512)
        ]
      ),
      (
        "first_four_kilobytes.bin",
        [
          (0, 4000)
        ]
      ),
      (
        "contiguous_before_bad_region.dat",
        [
          (FILE_SYSTEM_START + 4096*1, 4096)
        ]
      ),
      (
        "contiguous_around_bad_region_left_edge.dat",
        [
          (DAMAGE_REGION_START - 4096, 8192)
        ]
      ),
      (
        "contiguous_in_bad_region.dat",
        [
          (DAMAGE_REGION_START + 4096*1, 4096)
        ]
      ),
      (
        "contiguous_around_bad_region_right_edge.dat",
        [
          (GOOD_REGION_START - 4096*1, 8192)
        ]
      ),
      (
        "contiguous_after_bad_region.dat",
        [
          (GOOD_REGION_START + 4096*2, 4096)
        ]
      ),
      (
        "fragmented_all_before_bad_region.dat",
        [
          (FILE_SYSTEM_START + 4096*10, 4096),
          (FILE_SYSTEM_START + 4096*20, 4096),
          (FILE_SYSTEM_START + 4096*30, 4096)
        ]
      ),
      (
        "fragmented_all_after_bad_region.dat",
        [
          (GOOD_REGION_START + 4096*10, 4096),
          (GOOD_REGION_START + 4096*20, 4096),
          (GOOD_REGION_START + 4096*30, 4096)
        ]
      ),
      (
        "fragmented_all_inside_bad_region.dat",
        [
          (DAMAGE_REGION_START + 4096*10, 4096),
          (DAMAGE_REGION_START + 4096*20, 4096),
          (DAMAGE_REGION_START + 4096*30, 4096)
        ]
      ),
      (
        "fragmented_beginning_inside_bad_region.dat",
        [
          (DAMAGE_REGION_START + 4096*40, 4096),
          (GOOD_REGION_START + 4096*40, 4096)
        ]
      ),
      (
        "fragmented_middle_inside_bad_region.dat",
        [
          (FILE_SYSTEM_START + 4096*50, 4096),
          (DAMAGE_REGION_START + 4096*50, 4096),
          (GOOD_REGION_START + 4096*50, 4096)
        ]
      ),
      (
        "fragmented_end_inside_bad_region.dat",
        [
          (FILE_SYSTEM_START + 4096*60, 4096),
          (DAMAGE_REGION_START + 4096*60, 4096)
        ]
      ),
      (
        "after_disk_image_end.dat",
        [
          (DISK_IMAGE_SIZE + 4096*1000, 4096)
        ]
      ),
      (
        "fragmented_partially_recoverable_directory",
        [
          (FILE_SYSTEM_START + 4096*170, 4096),
          (DAMAGE_REGION_START + 4096*170, 4096),
          (GOOD_REGION_START + 4096*170, 4096),
        ]
      ),
      (
        "fragmented_partially_recoverable_directory/child_file_1",
        [
          (FILE_SYSTEM_START + 4096*180, 4096)
        ]
      ),
      (
        "fragmented_partially_recoverable_directory/child_file_2",
        [
          (FILE_SYSTEM_START + 4096*190, 4096)
        ]
      ),
      (
        "fragmented_partially_recoverable_directory/child_file_3",
        [
          (FILE_SYSTEM_START + 4096*200, 4096)
        ]
      ),
      (
        "fragmented_partially_recoverable_directory/child_file_4",
        [
          (FILE_SYSTEM_START + 4096*210, 4096)
        ]
      ),
      (
        "fragmented_partially_recoverable_directory/child_file_9",
        [
          (GOOD_REGION_START + 4096*180, 4096)
        ]
      )
    ]
    for fobj_spec in fobj_specs:
        fobj = Objects.FileObject()
        vobj.append(fobj)

        fobj.filename = fobj_spec[0]
        fobj.alloc = True
        # Naming convention for this sample - the .bin files are virtual files that reference a region outside of the file system.
        if fobj.filename == "fragmented_partially_recoverable_directory":
            fobj.name_type = "d"
        elif fobj.filename.endswith(".bin"):
            fobj.name_type = "v"
        else:
            fobj.name_type = "r"

        fobj.data_brs = Objects.ByteRuns()
        for interval in fobj_spec[1]:
            br = Objects.ByteRun()
            fobj.data_brs.append(br)
            br.img_offset = interval[0]
            br.len = interval[1]
        fobj.filesize = sum([br.len for br in fobj.data_brs])

    dobj.print_dfxml()
Example #13
0
def main():
    d = Objects.DFXMLObject(version="1.2.0")

    d.program = sys.argv[0]
    d.program_version = __version__
    d.command_line = " ".join(sys.argv)
    d.dc["type"] = "File system walk concatentation"
    d.add_creator_library("Python", ".".join(
        map(str, sys.version_info[0:3]
            )))  #A bit of a bend, but gets the major version information out.
    d.add_creator_library("Objects.py", Objects.__version__)
    d.add_creator_library("dfxml.py", Objects.dfxml.__version__)

    _offsets_and_pxml_paths = []
    for (lxfno, lxf) in enumerate(args.labeled_xml_file):
        lxf_parts = lxf.split(":")
        if len(lxf_parts) != 2 or not lxf_parts[0].isdigit():
            raise ValueError(
                "Malformed argument in labeled_xml_file.  Expecting space-delimited list of '<number>:<path>'.  This entry doesn't work: %r."
                % lxf)
        offset = int(lxf_parts[0])
        path = lxf_parts[1]
        _offsets_and_pxml_paths.append((offset, path))
    offsets_and_pxml_paths = sorted(_offsets_and_pxml_paths)

    for (pxml_path_index, (offset,
                           pxml_path)) in enumerate(offsets_and_pxml_paths):
        _logger.debug("Running on path %r." % pxml_path)
        pdo = Objects.parse(pxml_path)

        building_volume = None
        #Fetch or build volume we'll append
        if len(pdo.volumes) > 1:
            raise ValueError(
                "An input DFXML document has multiple volumes; this script assumes each input document only has one.  The document here has %d: %r."
                % (len(pdo.volumes), pxml_path))
        elif len(pdo.volumes) == 0:
            v = Objects.VolumeObject()
            building_volume = True
        else:
            v = pdo.volumes[0]
            building_volume = False

        v.partition_offset = offset

        #Accumulate namespaces
        for (prefix, url) in pdo.iter_namespaces():
            d.add_namespace(prefix, url)

        for obj in pdo:
            #Force-update image offsets in byte runs
            for brs_prop in ["data_brs", "name_brs", "inode_brs"]:
                if hasattr(obj, brs_prop):
                    brs = getattr(obj, brs_prop)
                    if brs is None:
                        continue
                    for br in brs:
                        if not br.fs_offset is None:
                            br.img_offset = br.fs_offset + offset
            #For files, set partition identifier and attach to partition
            if isinstance(obj, Objects.FileObject):
                obj.partition = pxml_path_index + 1
                if building_volume:
                    v.append(obj)

        #Collect the constructed and/or updated volume
        d.append(v)

    d.print_dfxml()
def test_all():
    _logger = logging.getLogger(os.path.basename(__file__))
    logging.basicConfig(level=logging.DEBUG)

    XMLNS_TEST_CLAMSCAN = "file:///opt/local/bin/clamscan"
    XMLNS_TEST_UNREGGED = "file:///dev/random"

    ET.register_namespace("clam", XMLNS_TEST_CLAMSCAN)

    vo = Objects.VolumeObject()

    #Try and fail to add a non-Element to the list.
    failed = None
    _logger.debug("Before:  " + repr(vo.externals))
    try:
        vo.externals.append(1)
        failed = False
    except TypeError:
        failed = True
    except:
        failed = True
        raise
    _logger.debug("After:  " + repr(vo.externals))
    assert failed
    failed = None

    #Dummy up a non-DFXML namespace element.  This should be appendable.
    e = ET.Element("{%s}scan_results" % XMLNS_TEST_CLAMSCAN)
    e.text = "Clean file system"
    vo.externals.append(e)

    #Dummy up a DFXML namespace element.  This should not be appendable (the schema specifies other namespaces).
    e = ET.Element("{%s}filename" % Objects.dfxml.XMLNS_DFXML)
    e.text = "Superfluous name"
    _logger.debug("Before:  " + repr(vo.externals))
    try:
        vo.externals.append(e)
        failed = False
    except ValueError:
        failed = True
    except:
        failed = True
        raise
    _logger.debug("After:  " + repr(vo.externals))
    assert failed
    failed = None

    #Add an element with the colon prefix style
    e = ET.Element("clam:version")
    e.text = "20140101"
    vo.externals.append(e)

    #Add an element that doesn't have an ET-registered namespace prefix.
    e = ET.Element("{%s}test2" % XMLNS_TEST_UNREGGED)
    e.text = "yes"
    vo.externals.append(e)

    #Test serialization
    s = Objects._ET_tostring(vo.to_Element(
    ))  #TODO Maybe this should be more than an internal function.
    _logger.debug(s)
    if s.find("scan_results") == -1:
        raise ValueError(
            "Serialization did not output other-namespace element 'scan_results'."
        )
    if s.find("clam:version") == -1:
        raise ValueError(
            "Serialization did not output prefixed element 'clam:version'.")
    if s.find("test2") == -1:
        raise ValueError(
            "Serialization did not output unregistered-prefix element 'test2'."
        )

    #Test de-serialization
    vor = Objects.VolumeObject()
    x = ET.XML(s)
    vor.populate_from_Element(x)
    _logger.debug("De-serialized: %r." % vor.externals)
    assert len(vor.externals) == 3