示例#1
0
 def test_validate_item_collection(self):
     sv = SchemaValidator()
     ic_1 = ItemCollection([])
     sv.validate_object(ic_1)
     sv.validate_dict(self.IC_DICT, STACObjectType.ITEMCOLLECTION)
     ic_2 = ItemCollection.from_file(self.IC_URI)
     ic_val_dict = ic_2.to_dict()
     ic_val_dict['features'] = 'not an array'
     with self.assertRaises(STACValidationError):
         sv.validate_dict(ic_val_dict, STACObjectType.ITEMCOLLECTION)
示例#2
0
 def test_validate_item_collection(self):
     sv = SchemaValidator()
     ic_1 = ItemCollection([])
     sv.validate_object(ic_1)
     sv.validate_dict(self.IC_DICT, ItemCollection)
     ic_2 = ItemCollection.from_file(self.IC_URI)
     ic_val_dict = ic_2.to_dict()
     ic_val_dict['features'] = 'not an array'
     with self.assertRaises(ValidationError):
         print('[Validation error expected] - ', end='')
         sv.validate_dict(ic_val_dict, ItemCollection)
示例#3
0
    def test_validate_single_file(self):
        sv = SchemaValidator()
        sf_from_file = SingleFileSTAC.from_file(self.EXAMPLE_SINGLE_FILE)

        with TemporaryDirectory() as tmp_dir:
            tmp_uri = join(tmp_dir, 'test-single-file-val.json')
            sf_from_file.save(tmp_uri)
            with open(tmp_uri) as f:
                val_dict = json.load(f)
        sv.validate_dict(val_dict, STACObjectType.ITEMCOLLECTION)

        val_dict['search']['endpoint'] = 1
        with self.assertRaises(STACValidationError):
            sv.validate_dict(val_dict, STACObjectType.ITEMCOLLECTION)
示例#4
0
    def test_validate_label(self):
        sv = SchemaValidator()
        with open(self.label_example_1_uri) as f:
            label_example_1_dict = json.load(f)
        sv.validate_dict(label_example_1_dict, LabelItem)

        with TemporaryDirectory() as tmp_dir:
            cat_dir = os.path.join(tmp_dir, 'catalog')
            catalog = TestCases.test_case_1()
            label_item = LabelItem.from_dict(label_example_1_dict)
            catalog.add_item(label_item)
            catalog.normalize_and_save(cat_dir,
                                       catalog_type=CatalogType.SELF_CONTAINED)

            cat_read = Catalog.from_file(os.path.join(cat_dir, 'catalog.json'))
            label_item_read = cat_read.get_item("label-example-1-label-item")
            sv = SchemaValidator()
            sv.validate_object(label_item_read)
示例#5
0
    def test_validate_eo(self):
        sv = SchemaValidator()
        self.assertIsNone(sv.validate_dict(self.eo_dict, EOItem))

        with open(self.URI_2) as f:
            eo_dict_2 = json.load(f)
        with self.assertRaises(ValidationError):
            print('[Validation error expected] - ', end='')
            sv.validate_dict(eo_dict_2, EOItem)

        with TemporaryDirectory() as tmp_dir:
            cat_dir = os.path.join(tmp_dir, 'catalog')
            catalog = TestCases.test_case_1()
            eo_item = EOItem.from_dict(self.eo_dict)
            catalog.add_item(eo_item)
            catalog.normalize_and_save(cat_dir, catalog_type=CatalogType.ABSOLUTE_PUBLISHED)

            cat_read = Catalog.from_file(os.path.join(cat_dir, 'catalog.json'))
            eo_item_read = cat_read.get_item("LC08_L1TP_107018_20181001_20181001_01_RT")
            sv = SchemaValidator()
            sv.validate_object(eo_item_read)
            sv.validate_dict(eo_item_read.to_dict(), EOItem)
示例#6
0
    def test_validate_single_file(self):
        sv = SchemaValidator()
        sv.validate_dict(self.EXAMPLE_SF_DICT, SingleFileSTAC)
        sf_from_file = SingleFileSTAC.from_file(self.EXAMPLE_SINGLE_FILE)
        sv.validate_object(sf_from_file)

        with TemporaryDirectory() as tmp_dir:
            tmp_uri = join(tmp_dir, 'test-single-file-val.json')
            sf_from_file.save(tmp_uri)
            with open(tmp_uri) as f:
                val_dict = json.load(f)
        sv.validate_dict(val_dict, SingleFileSTAC)

        val_dict['search']['endpoint'] = 1
        with self.assertRaises(ValidationError):
            print('[Validation error expected] - ', end='')
            sv.validate_dict(val_dict, SingleFileSTAC)
示例#7
0
class STACWritingTest(unittest.TestCase):
    """Tests writing STACs, using JSON Schema validation,
    and ensure that links are correctly set to relative or absolute.
    """
    def setUp(self):
        self.schema_validator = SchemaValidator()

    def validate_catalog(self, catalog):
        self.schema_validator.validate_object(catalog, print_on_error=True)
        validated_count = 1

        for child in catalog.get_children():
            validated_count += self.validate_catalog(child)

        for item in catalog.get_items():
            self.schema_validator.validate_object(item, print_on_error=True)
            validated_count += 1

        return validated_count

    def validate_file(self, path, object_type):
        d = STAC_IO.read_json(path)
        return self.schema_validator.validate_dict(d, object_type, print_on_error=True)

    def validate_link_types(self, root_href, catalog_type):
        def validate_item_link_type(href, link_type, should_include_self):
            item_dict = STAC_IO.read_json(href)
            item = STACObject.from_file(href)
            for link in item.get_links():
                if not link.rel == 'self':
                    self.assertEqual(link.link_type, link_type)

            rels = set([link['rel'] for link in item_dict['links']])
            self.assertEqual('self' in rels, should_include_self)

        def validate_catalog_link_type(href, link_type, should_include_self):
            cat_dict = STAC_IO.read_json(href)
            cat = STACObject.from_file(href)
            for link in cat.get_links():
                if not link.rel == 'self':
                    self.assertEqual(link.link_type, link_type)

            rels = set([link['rel'] for link in cat_dict['links']])
            self.assertEqual('self' in rels, should_include_self)

            for child_link in cat.get_child_links():
                child_href = make_absolute_href(child_link.target, href)
                validate_catalog_link_type(child_href, link_type,
                                           catalog_type == CatalogType.ABSOLUTE_PUBLISHED)

            for item_link in cat.get_item_links():
                item_href = make_absolute_href(item_link.target, href)
                validate_item_link_type(item_href, link_type,
                                        catalog_type == CatalogType.ABSOLUTE_PUBLISHED)

        link_type = LinkType.RELATIVE
        if catalog_type == CatalogType.ABSOLUTE_PUBLISHED:
            link_type = LinkType.ABSOLUTE

        root_should_include_href = catalog_type in [
            CatalogType.ABSOLUTE_PUBLISHED, CatalogType.RELATIVE_PUBLISHED
        ]

        validate_catalog_link_type(root_href, link_type, root_should_include_href)

    def do_test(self, catalog, catalog_type):
        with TemporaryDirectory() as tmp_dir:
            catalog.normalize_hrefs(tmp_dir)
            self.validate_catalog(catalog)

            catalog.save(catalog_type=catalog_type)

            root_href = catalog.get_self_href()
            self.validate_link_types(root_href, catalog_type)

            for parent, children, items in catalog.walk():
                if issubclass(type(parent), Collection):
                    stac_object_type = STACObjectType.COLLECTION
                else:
                    stac_object_type = STACObjectType.CATALOG
                self.validate_file(parent.get_self_href(), stac_object_type)

                for item in items:
                    self.validate_file(item.get_self_href(), STACObjectType.ITEM)

    def test_testcases(self):
        for catalog in TestCases.all_test_catalogs():
            catalog = catalog.full_copy()
            for catalog_type in [
                    CatalogType.ABSOLUTE_PUBLISHED, CatalogType.RELATIVE_PUBLISHED,
                    CatalogType.SELF_CONTAINED
            ]:
                with self.subTest(title='Catalog {} [{}]'.format(catalog.id, catalog_type)):
                    self.do_test(catalog, catalog_type)
示例#8
0
class EOTest(unittest.TestCase):
    def setUp(self):
        self.validator = SchemaValidator()
        self.maxDiff = None
        self.URI_1 = TestCases.get_path(
            'data-files/eo/eo-landsat-example.json')
        self.URI_2 = TestCases.get_path(
            'data-files/eo/eo-landsat-example-INVALID.json')
        self.eoi = Item.from_file(self.URI_1)
        with open(self.URI_1) as f:
            self.eo_dict = json.load(f)

    def test_to_from_dict(self):
        test_to_from_dict(self, Item, self.eo_dict)

    def test_from_file(self):
        self.assertEqual(len(self.eoi.ext.eo.bands), 11)
        for b in self.eoi.ext.eo.bands:
            self.assertIsInstance(b, Band)
        self.assertEqual(len(self.eoi.links), 3)

        href = ('https://odu9mlf7d6.execute-api.us-east-1.amazonaws.com/stage/'
                'stac/search?id=LC08_L1TP_107018_20181001_20181001_01_RT')
        self.assertEqual(self.eoi.get_self_href(), href)

    def test_from_item(self):
        i = Item.from_file(self.URI_1)
        with self.assertRaises(AttributeError):
            getattr(i, 'bands')
        self.assertTrue('eo:bands' in i.properties.keys())
        eo_ext = i.ext.eo
        self.assertIsNotNone(getattr(eo_ext, 'bands'))

    def test_read_eo_item_owns_asset(self):
        item = Item.from_file(self.URI_1)
        assert len(item.assets) > 0
        for asset_key in item.assets:
            self.assertEqual(item.assets[asset_key].owner, item)

    def test_validate_eo(self):
        self.validator.validate_dict(self.eo_dict, STACObjectType.ITEM)

        with open(self.URI_2) as f:
            eo_dict_2 = json.load(f)

        try:
            self.validator.validate_dict(eo_dict_2, STACObjectType.ITEM)
        except STACValidationError as e:
            self.assertTrue('extension eo' in str(e))

        with TemporaryDirectory() as tmp_dir:
            cat_dir = os.path.join(tmp_dir, 'catalog')
            catalog = TestCases.test_case_1()
            eo_item = Item.from_dict(self.eo_dict)
            catalog.add_item(eo_item)
            catalog.normalize_and_save(
                cat_dir, catalog_type=CatalogType.ABSOLUTE_PUBLISHED)

            cat_read = Catalog.from_file(os.path.join(cat_dir, 'catalog.json'))
            eo_item_read = cat_read.get_item(
                "LC08_L1TP_107018_20181001_20181001_01_RT")
            self.assertTrue(eo_item_read.ext.implements('eo'))
            self.validator.validate_object(eo_item_read)

    def test_gsd(self):
        eo_item = pystac.read_file(
            TestCases.get_path('data-files/eo/eo-landsat-example.json'))

        # Get
        self.assertIn("eo:gsd", eo_item.properties)
        eo_gsd = eo_item.ext.eo.gsd
        self.assertEqual(eo_gsd, eo_item.properties['eo:gsd'])

        # Set
        eo_item.ext.eo.gsd = eo_gsd + 100
        self.assertEqual(eo_gsd + 100, eo_item.properties['eo:gsd'])
        self.validator.validate_object(eo_item)

    def test_bands(self):
        eo_item = pystac.read_file(
            TestCases.get_path('data-files/eo/eo-landsat-example.json'))

        # Get
        self.assertIn("eo:bands", eo_item.properties)
        bands = eo_item.ext.eo.bands
        self.assertEqual(list(map(lambda x: x.name, bands)), [
            'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'B11'
        ])
        for band in bands:
            self.assertIsInstance(band.common_name, str)
            self.assertIn(type(band.center_wavelength), [float, int])
            self.assertIn(type(band.full_width_half_max), [float, int])
            self.assertIs(None, band.description)

        # Ensure modifying the bands make changes on the item.
        bands_dict = {band.name: band for band in bands}
        bands_dict['B1'].description = "Band 1"

        self.assertTrue(
            [x for x in eo_item.properties['eo:bands']
             if x['name'] == 'B1'][0]['description'] == "Band 1")

        # Set
        new_bands = [
            Band.create(name="red", description=Band.band_description("red")),
            Band.create(name="green",
                        description=Band.band_description("green")),
            Band.create(name="blue",
                        description=Band.band_description("blue")),
        ]

        eo_item.ext.eo.bands = new_bands
        self.assertEqual('Common name: red, Range: 0.6 to 0.7',
                         eo_item.properties['eo:bands'][0]['description'])
        self.validator.validate_object(eo_item)

    def test_get_asset_bands(self):
        eo_item = pystac.read_file(
            TestCases.get_path('data-files/eo/eo-landsat-example.json'))

        b1_asset = eo_item.assets['B1']
        asset_bands = eo_item.ext.eo.get_asset_bands(b1_asset)
        self.assertIsNot(None, asset_bands)
        self.assertEqual(len(asset_bands), 1)
        self.assertEqual(asset_bands[0].name, 'B1')

        index_asset = eo_item.assets['index']
        asset_bands = eo_item.ext.eo.get_asset_bands(index_asset)
        self.assertIs(None, asset_bands)

    def test_set_asset_bands(self):
        eo_item = pystac.read_file(
            TestCases.get_path('data-files/eo/eo-landsat-example.json'))

        b1_asset = eo_item.assets['B1']
        eo_item.ext.eo.set_asset_bands(b1_asset, ['B2'])

        eo_item_mod = Item.from_dict(eo_item.to_dict())
        b1_asset_mod = eo_item_mod.assets['B1']
        asset_bands = eo_item_mod.ext.eo.get_asset_bands(b1_asset_mod)
        self.assertIsNot(None, asset_bands)
        self.assertEqual(len(asset_bands), 1)
        self.assertEqual(asset_bands[0].name, 'B2')

        self.validator.validate_object(eo_item)

        # Check setting with invalid keys

        with self.assertRaises(KeyError):
            eo_item.ext.eo.set_asset_bands(b1_asset, ['BAD_KEY', 'BAD_KEY_2'])

        # Check adding a new asset
        asset = pystac.Asset(href="some/path.tif",
                             media_type=pystac.MediaType.GEOTIFF)
        eo_item.ext.eo.set_asset_bands(asset,
                                       [b.name for b in eo_item.ext.eo.bands])
        eo_item.add_asset("test", asset)

        self.assertEqual(eo_item.assets["test"].properties["eo:bands"],
                         list(range(0, len(eo_item.ext.eo.bands))))

    def test_read_pre_09_fields_into_common_metadata(self):
        eo_item = pystac.read_file(
            TestCases.get_path('data-files/examples/0.8.1/item-spec/examples/'
                               'landsat8-sample.json'))

        self.assertEqual(eo_item.common_metadata.platform, "landsat-8")
        self.assertEqual(eo_item.common_metadata.instruments, ["oli_tirs"])
示例#9
0
class LabelTest(unittest.TestCase):
    def setUp(self):
        self.validator = SchemaValidator()
        self.maxDiff = None
        self.label_example_1_uri = TestCases.get_path(
            'data-files/label/label-example-1.json')
        self.label_example_2_uri = TestCases.get_path(
            'data-files/label/label-example-2.json')

    def test_to_from_dict(self):
        with open(self.label_example_1_uri) as f:
            label_example_1_dict = json.load(f)

        test_to_from_dict(self, Item, label_example_1_dict)

    def test_from_file(self):
        label_example_1 = Item.from_file(self.label_example_1_uri)

        self.assertEqual(
            len(label_example_1.ext.label.label_overviews[0].counts), 2)
        self.validator.validate_object(label_example_1)

        label_example_2 = Item.from_file(self.label_example_2_uri)
        self.assertEqual(
            len(label_example_2.ext.label.label_overviews[0].counts), 2)

        # TODO: Validate for 1.0 as schema was fixed.
        # In 0.9.0 the properties are required (but need to be null for raster labels)
        # self.validator.validate_object(label_example_2)

    def test_from_file_pre_081(self):
        d = STAC_IO.read_json(self.label_example_1_uri)

        d['stac_version'] = '0.8.0-rc1'
        d['properties']['label:property'] = d['properties']['label:properties']
        d['properties'].pop('label:properties')
        d['properties']['label:overview'] = d['properties']['label:overviews']
        d['properties'].pop('label:overviews')
        d['properties']['label:method'] = d['properties']['label:methods']
        d['properties'].pop('label:methods')
        d['properties']['label:task'] = d['properties']['label:tasks']
        d['properties'].pop('label:tasks')
        label_example_1 = STAC_IO.stac_object_from_dict(d)

        self.assertEqual(len(label_example_1.ext.label.label_tasks), 2)

    def test_get_sources(self):
        cat = TestCases.test_case_1()

        items = cat.get_all_items()
        item_ids = set([i.id for i in items])

        for li in items:
            if li.ext.implements('label'):
                sources = li.ext.label.get_sources()
                self.assertEqual(len(sources), 1)
                self.assertTrue(sources[0].id in item_ids)

    def test_validate_label(self):
        with open(self.label_example_1_uri) as f:
            label_example_1_dict = json.load(f)
        self.validator.validate_dict(label_example_1_dict, "ITEM")

        with TemporaryDirectory() as tmp_dir:
            cat_dir = os.path.join(tmp_dir, 'catalog')
            catalog = TestCases.test_case_1()
            catalog.normalize_and_save(cat_dir,
                                       catalog_type=CatalogType.SELF_CONTAINED)

            cat_read = Catalog.from_file(os.path.join(cat_dir, 'catalog.json'))
            label_item_read = cat_read.get_item("area-2-2-labels",
                                                recursive=True)
            self.validator.validate_object(label_item_read)

    def test_read_label_item_owns_asset(self):
        item = next(x for x in TestCases.test_case_2().get_all_items()
                    if x.ext.implements("label"))
        assert len(item.assets) > 0
        for asset_key in item.assets:
            self.assertEqual(item.assets[asset_key].owner, item)

    def test_label_description(self):
        label_item = pystac.read_file(self.label_example_1_uri)

        # Get
        self.assertIn("label:description", label_item.properties)
        label_desc = label_item.ext.label.label_description
        self.assertEqual(label_desc,
                         label_item.properties['label:description'])

        # Set
        label_item.ext.label.label_description = "A detailed description"
        self.assertEqual("A detailed description",
                         label_item.properties['label:description'])
        self.validator.validate_object(label_item)

    def test_label_type(self):
        label_item = pystac.read_file(self.label_example_1_uri)

        # Get
        self.assertIn("label:type", label_item.properties)
        label_type = label_item.ext.label.label_type
        self.assertEqual(label_type, label_item.properties['label:type'])

        # Set
        label_item.ext.label.label_type = label.LabelType.RASTER
        self.assertEqual(label.LabelType.RASTER,
                         label_item.properties['label:type'])
        self.validator.validate_object(label_item)

    def test_label_properties(self):
        label_item = pystac.read_file(self.label_example_1_uri)
        label_item2 = pystac.read_file(self.label_example_2_uri)

        # Get
        self.assertIn("label:properties", label_item.properties)
        label_prop = label_item.ext.label.label_properties
        self.assertEqual(label_prop, label_item.properties['label:properties'])
        raster_label_prop = label_item2.ext.label.label_properties
        self.assertEqual(raster_label_prop, None)

        # Set
        label_item.ext.label.label_properties = ["prop1", "prop2"]
        self.assertEqual(["prop1", "prop2"],
                         label_item.properties['label:properties'])
        self.validator.validate_object(label_item)

    def test_label_classes(self):
        # Get
        label_item = pystac.read_file(self.label_example_1_uri)
        label_classes = label_item.ext.label.label_classes

        self.assertEqual(len(label_classes), 2)
        self.assertEqual(label_classes[1].classes, ["three", "four"])

        # Set
        new_classes = [
            label.LabelClasses.create(name="label2", classes=["five", "six"]),
            label.LabelClasses.create(name="label", classes=["seven", "eight"])
        ]

        label_item.ext.label.label_classes = new_classes
        self.assertEqual([
            class_name for lc in label_item.properties["label:classes"]
            for class_name in lc["classes"]
        ], ["five", "six", "seven", "eight"])

        self.validator.validate_object(label_item)

    def test_label_tasks(self):
        label_item = pystac.read_file(self.label_example_1_uri)

        # Get
        self.assertIn("label:tasks", label_item.properties)
        label_prop = label_item.ext.label.label_tasks
        self.assertEqual(label_prop, ["classification", "regression"])

        # Set
        label_item.ext.label.label_tasks = ["classification"]
        self.assertEqual(["classification"],
                         label_item.properties['label:tasks'])
        self.validator.validate_object(label_item)

    def test_label_methods(self):
        label_item = pystac.read_file(self.label_example_1_uri)

        # Get
        self.assertIn("label:methods", label_item.properties)
        label_prop = label_item.ext.label.label_methods
        self.assertEqual(label_prop, ["manual"])

        # Set
        label_item.ext.label.label_methods = ["manual", "automated"]
        self.assertEqual(["manual", "automated"],
                         label_item.properties['label:methods'])
        self.validator.validate_object(label_item)

    def test_label_overviews(self):
        # Get
        label_item = pystac.read_file(self.label_example_1_uri)
        label_overviews = label_item.ext.label.label_overviews

        label_item2 = pystac.read_file(self.label_example_2_uri)
        label_overviews2 = label_item2.ext.label.label_overviews

        self.assertEqual(len(label_overviews), 2)
        self.assertEqual(label_overviews[1].property_key, "label-reg")
        self.assertEqual(label_overviews2[1].property_key, None)  # Raster

        label_counts = label_overviews[0].counts
        self.assertEqual(label_counts[1].count, 17)
        label_item.ext.label.label_overviews[0].counts[1].count = 18
        self.assertEqual(
            label_item.properties['label:overviews'][0]['counts'][1]['count'],
            18)

        label_statistics = label_overviews[1].statistics
        self.assertEqual(label_statistics[0].name, "mean")
        label_item.ext.label.label_overviews[1].statistics[0].name = "avg"
        self.assertEqual(
            label_item.properties['label:overviews'][1]['statistics'][0]
            ['name'], "avg")

        # Set
        new_overviews = [
            label.LabelOverview.create(property_key="label2",
                                       counts=[
                                           label.LabelCount.create(name="one",
                                                                   count=1),
                                           label.LabelCount.create(name="two",
                                                                   count=1),
                                       ]),
            label.LabelOverview.create(
                property_key="label-reg",
                statistics=[
                    label.LabelStatistics.create(name="min", value=0.1),
                    label.LabelStatistics.create(name="max", value=1.0),
                ])
        ]

        label_item.ext.label.label_overviews = new_overviews
        self.assertEqual([
            (count['name'], count['count'])
            for count in label_item.properties["label:overviews"][0]['counts']
        ], [("one", 1), ("two", 1)])

        self.assertEqual([(count['name'], count['value'])
                          for count in label_item.properties["label:overviews"]
                          [1]['statistics']], [("min", 0.1), ("max", 1.0)])

        self.validator.validate_object(label_item)
示例#10
0
class STACWritingTest(unittest.TestCase):
    """Tests writing STACs, using JSON Schema validation,
    and ensure that links are correctly set to relative or absolute.
    """
    def setUp(self):
        self.schema_validator = SchemaValidator()

    def validate_catalog(self, catalog):
        self.schema_validator.validate_object(catalog)
        validated_count = 1

        for child in catalog.get_children():
            validated_count += self.validate_catalog(child)

        for item in catalog.get_items():
            self.schema_validator.validate_object(item)
            validated_count += 1

        return validated_count

    def validate_file(self, path, object_type):
        d = STAC_IO.read_json(path)
        return self.schema_validator.validate_dict(d, object_type)

    def validate_link_types(self, root_href, catalog_type):
        def validate_item_link_type(href, link_type, should_include_self):
            item_dict = STAC_IO.read_json(href)
            item = STACObject.from_file(href)
            for link in item.get_links():
                if not link.rel == 'self':
                    self.assertEqual(link.link_type, link_type)

            rels = set([l['rel'] for l in item_dict['links']])
            self.assertEqual('self' in rels, should_include_self)

        def validate_catalog_link_type(href, link_type, should_include_self):
            cat_dict = STAC_IO.read_json(href)
            cat = STACObject.from_file(href)
            for link in cat.get_links():
                if not link.rel == 'self':
                    self.assertEqual(link.link_type, link_type)

            rels = set([l['rel'] for l in cat_dict['links']])
            self.assertEqual('self' in rels, should_include_self)

            for child_link in cat.get_child_links():
                child_href = make_absolute_href(child_link.target, href)
                validate_catalog_link_type(
                    child_href, link_type,
                    catalog_type == CatalogType.ABSOLUTE_PUBLISHED)

            for item_link in cat.get_item_links():
                item_href = make_absolute_href(item_link.target, href)
                validate_item_link_type(
                    item_href, link_type,
                    catalog_type == CatalogType.ABSOLUTE_PUBLISHED)

        link_type = LinkType.RELATIVE
        if catalog_type == CatalogType.ABSOLUTE_PUBLISHED:
            link_type = LinkType.ABSOLUTE

        root_should_include_href = catalog_type in [
            CatalogType.ABSOLUTE_PUBLISHED, CatalogType.RELATIVE_PUBLISHED
        ]

        validate_catalog_link_type(root_href, link_type,
                                   root_should_include_href)

    def do_test(self, catalog, catalog_type):
        with TemporaryDirectory() as tmp_dir:
            catalog.normalize_hrefs(tmp_dir)
            self.validate_catalog(catalog)

            catalog.save(catalog_type=catalog_type)

            root_href = catalog.get_self_href()
            self.validate_link_types(root_href, catalog_type)

            for parent, children, items in catalog.walk():
                self.validate_file(parent.get_self_href(), type(parent))

                for item in items:
                    self.validate_file(item.get_self_href(), type(item))

    def test_testcase1_absolute_published(self):
        catalog = TestCases.test_case_1()
        self.do_test(catalog, CatalogType.ABSOLUTE_PUBLISHED)

    def test_testcase1_relative_published(self):
        catalog = TestCases.test_case_1()
        self.do_test(catalog, CatalogType.RELATIVE_PUBLISHED)

    def test_testcase1_self_contained(self):
        catalog = TestCases.test_case_1()
        self.do_test(catalog, CatalogType.SELF_CONTAINED)

    def test_testcase2_absolute_published(self):
        catalog = TestCases.test_case_2()

        catalog = catalog.full_copy()
        self.do_test(catalog, CatalogType.ABSOLUTE_PUBLISHED)

    def test_testcase2_relative_published(self):
        catalog = TestCases.test_case_2()
        self.do_test(catalog, CatalogType.RELATIVE_PUBLISHED)

    def test_testcase2_self_contained(self):
        catalog = TestCases.test_case_2()
        self.do_test(catalog, CatalogType.SELF_CONTAINED)

    def test_testcase3_absolute_published(self):
        catalog = TestCases.test_case_3()

        catalog = catalog.full_copy()
        self.do_test(catalog, CatalogType.ABSOLUTE_PUBLISHED)

    def test_testcase3_relative_published(self):
        catalog = TestCases.test_case_3()
        self.do_test(catalog, CatalogType.RELATIVE_PUBLISHED)

    def test_testcase3_self_contained(self):
        catalog = TestCases.test_case_3()
        self.do_test(catalog, CatalogType.SELF_CONTAINED)