def test_resource_reference_removal_non_breaking2(self):
     # Removed resource reference is defined by child type, and it
     # can be resolved to the same resource with the message options.
     # Original field has resource reference `example.v1/Foo`.
     field_options = make_field_annotation_resource_reference(
         resource_type="example.v1/Foo", is_child_type=False
     )
     field_with_reference = make_field(name="Test", options=field_options)
     # Update field has no resource reference. But the message has
     # resource options `example.v1/Foo`.
     message_resource = make_resource_descriptor(
         resource_type="example.v1/Foo", resource_patterns=["bar/{bar}"]
     )
     field_resource = make_resource_descriptor(
         resource_type="example.v1/Foo", resource_patterns=["bar/{bar}/foo/{foo}"]
     )
     # Register the two resources in the database.
     resource_database = make_resource_database(
         resources=[message_resource, field_resource]
     )
     field_without_reference = make_field(
         name="Test",
         message_resource=message_resource,
         resource_database=resource_database,
     )
     # `bar/{bar}` is the parent resource of `bar/{bar}/foo/{foo}`.
     FieldComparator(
         field_with_reference,
         field_without_reference,
         self.finding_container,
         context="ctx",
     ).compare()
     finding = self.finding_container.get_all_findings()[0]
     self.assertEqual(finding.category.name, "RESOURCE_REFERENCE_MOVED")
     self.assertEqual(finding.change_type.name, "MINOR")
 def test_resource_reference_child_type_addition_non_breaking(self):
     # The added resource reference is in the database. Non-breaking change.
     # The original field is without resource reference.
     field_without_reference = make_field(name="Test")
     # Create a database with resource `example.v1/Foo` registered.
     resource = make_resource_descriptor(
         resource_type="example.v1/Foo", resource_patterns=["foo/{foo}"]
     )
     resource_child = make_resource_descriptor(
         resource_type="example.v1/Bar",
         resource_patterns=["foo/{foo}/bar/{bar}"],
     )
     resource_database = make_resource_database(resources=[resource, resource_child])
     # The update field has resource reference of child_type `example.v1/Bar`.
     field_options = desc.FieldOptions()
     field_options.Extensions[
         resource_pb2.resource_reference
     ].child_type = "example.v1/Bar"
     field_with_reference = make_field(
         name="Test", options=field_options, resource_database=resource_database
     )
     FieldComparator(
         field_without_reference,
         field_with_reference,
         self.finding_container,
         context="ctx",
     ).compare()
     finding = self.finding_container.get_all_findings()[0]
     self.assertEqual(finding.category.name, "RESOURCE_REFERENCE_ADDITION")
     self.assertEqual(finding.change_type.name, "MINOR")
    def test_resource_reference_change_type_conversion_non_breaking(self):
        child_resource = make_resource_descriptor(
            resource_type="example.v1/Foo",
            resource_patterns=["bar/{bar}/foo/{foo}", "bar/{bar}/foo"],
        )
        parent_resource = make_resource_descriptor(
            resource_type="example.v1/Bar", resource_patterns=["bar/{bar}"]
        )
        # Register two resources in database.
        resource_database = make_resource_database(
            resources=[child_resource, parent_resource]
        )
        # The original field is defined by child type.
        field_options_child = make_field_annotation_resource_reference(
            resource_type="example.v1/Foo", is_child_type=True
        )
        field_with_reference_child = make_field(
            name="Test",
            options=field_options_child,
            resource_database=resource_database,
        )

        # The update field is defined by parent type.
        field_options_parent = make_field_annotation_resource_reference(
            resource_type="example.v1/Bar", is_child_type=False
        )
        field_with_reference_parent = make_field(
            name="Test",
            options=field_options_parent,
            resource_database=resource_database,
        )
        # The two resources can be resolved to the identical resource.
        FieldComparator(
            field_with_reference_child,
            field_with_reference_parent,
            self.finding_container,
            context="ctx",
        ).compare()
        finding = self.finding_container.get_all_findings()
        # No breaking change should be detected.
        self.assertFalse(finding)

        # Reverse should be same since the two resources can
        # be resolved to the identical resource.
        FieldComparator(
            field_with_reference_parent,
            field_with_reference_child,
            self.finding_container,
            context="ctx",
        ).compare()
        finding = self.finding_container.get_all_findings()
        # No breaking change should be detected.
        self.assertFalse(finding)
    def test_resource_reference_removal_non_breaking1(self):
        # Removed resource reference is defined by type, and it is
        # added back to the message options.
        # Original field has resource reference `example.v1/Foo`.
        field_options = make_field_annotation_resource_reference(
            resource_type="example.v1/Foo", is_child_type=False
        )
        field_with_reference = make_field(name="Test", options=field_options)
        # Update field has no resource reference. But the message has
        # resource options `example.v1/Foo`.
        message_resource = make_resource_descriptor(
            resource_type="example.v1/Foo", resource_patterns=["bar/{bar}"]
        )

        field_without_reference = make_field(
            name="Test", message_resource=message_resource
        )
        FieldComparator(
            field_with_reference,
            field_without_reference,
            self.finding_container,
            context="ctx",
        ).compare()
        finding = self.finding_container.get_all_findings()[0]
        self.assertEqual(finding.category.name, "RESOURCE_REFERENCE_MOVED")
        self.assertEqual(finding.change_type.name, "MINOR")
 def test_resource_reference_removal_breaking2(self):
     # Removed resource reference is defined by type, which is not identical
     # with the message options.
     # Original field has resource reference `example.v1/Foo`.
     field_options = make_field_annotation_resource_reference(
         resource_type="example.v1/Foo", is_child_type=False
     )
     field_with_reference = make_field(name="Test", options=field_options)
     # Update field has no resource reference, and the resource type
     # is different from the message options type.
     message_resource = make_resource_descriptor(
         resource_type="NotInteresting", resource_patterns=["NotInteresting"]
     )
     field_without_reference = make_field(
         name="Test", message_resource=message_resource
     )
     FieldComparator(
         field_with_reference,
         field_without_reference,
         self.finding_container,
         context="ctx",
     ).compare()
     finding = self.finding_container.get_actionable_findings()[0]
     self.assertEqual(finding.category.name, "RESOURCE_REFERENCE_REMOVAL")
     self.assertEqual(finding.change_type.name, "MAJOR")
示例#6
0
 def test_get_resource_by_type(self):
     resource = make_resource_descriptor(resource_type="resource",
                                         resource_patterns=["a"])
     self.resource_database.register_resource(resource)
     self.assertEqual(
         self.resource_database.get_resource_by_type("resource"), resource)
     self.assertEqual(
         self.resource_database.get_resource_by_type("resource1"), None)
示例#7
0
 def test_register_invalid_resource(self):
     # Register resource with no type.
     resource_without_type = make_resource_descriptor(
         resource_type=None, resource_patterns=["a"])
     # Raise TypeError: APIs must define a resource type
     # and resource pattern for each resource in the API.
     with self.assertRaises(TypeError):
         self.resource_database.register_resource(resource_without_type)
示例#8
0
 def test_get_resource_by_pattern(self):
     resource = make_resource_descriptor(resource_type="resource",
                                         resource_patterns=["a", "b"])
     self.resource_database.register_resource(resource)
     # The resourc could be query by either type.
     self.assertEqual(self.resource_database.get_resource_by_pattern("a"),
                      resource)
     self.assertEqual(self.resource_database.get_resource_by_pattern("b"),
                      resource)
示例#9
0
 def test_register_valid_resource(self):
     resource = make_resource_descriptor(resource_type="resource",
                                         resource_patterns=["a"])
     self.resource_database.register_resource(resource)
     self.assertEqual(list(self.resource_database.types.keys()),
                      ["resource"])
     self.assertEqual(self.resource_database.types["resource"], resource)
     self.assertEqual(list(self.resource_database.patterns.keys()), ["a"])
     self.assertEqual(self.resource_database.patterns["a"], resource)
示例#10
0
 def test_register_resource_with_multiple_patterns(self):
     resource = make_resource_descriptor(resource_type="resource",
                                         resource_patterns=["b", "c"])
     self.resource_database.register_resource(resource)
     self.assertEqual(list(self.resource_database.types.keys()),
                      ["resource"])
     self.assertEqual(self.resource_database.types["resource"], resource)
     self.assertEqual(list(self.resource_database.patterns.keys()),
                      ["b", "c"])
     self.assertEqual(self.resource_database.patterns["b"], resource)
     self.assertEqual(self.resource_database.patterns["c"], resource)
    def test_resource_reference_change_type_conversion_breaking(self):
        resource_bar = make_resource_descriptor(
            resource_type="example.v1/Bar",
            resource_patterns=["bar/{bar}/foo/{foo}", "bar/{bar}/foo"],
        )
        resource_foo = make_resource_descriptor(
            resource_type="example.v1/Foo", resource_patterns=["foo/{foo}"]
        )
        # Register two resources in database.
        resource_database = make_resource_database(
            resources=[resource_bar, resource_foo]
        )
        # The original field is defined by child type.
        field_options_child = make_field_annotation_resource_reference(
            resource_type="example.v1/Bar", is_child_type=True
        )
        field_with_reference_child = make_field(
            name="Test",
            options=field_options_child,
            resource_database=resource_database,
        )

        # The update field is defined by parent type.
        field_options_parent = make_field_annotation_resource_reference(
            resource_type="example.v1/Foo", is_child_type=False
        )
        field_with_reference_parent = make_field(
            name="Test",
            options=field_options_parent,
            resource_database=resource_database,
        )
        # The two resources can nnot be resolved to the identical resource.
        FieldComparator(
            field_with_reference_child,
            field_with_reference_parent,
            self.finding_container,
            context="ctx",
        ).compare()
        finding = self.finding_container.get_all_findings()[0]
        self.assertEqual(finding.category.name, "RESOURCE_REFERENCE_CHANGE_CHILD_TYPE")
        self.assertEqual(finding.change_type.name, "MAJOR")
示例#12
0
 def test_get_parent_resource_by_type(self):
     child_resource = make_resource_descriptor(
         resource_type="child", resource_patterns=["a/{a}/b/{b}", "b/{b}"])
     parent_resource = make_resource_descriptor(
         resource_type="parent", resource_patterns=["a/{a}/b"])
     self.resource_database.register_resource(child_resource)
     self.resource_database.register_resource(parent_resource)
     # Check None child type, should return [].
     parent_resources = self.resource_database.get_parent_resources_by_child_type(
         None)
     self.assertFalse(parent_resources)
     # `a/{a}/b` is the parent pattern of `a/{a}/b/{b}`
     parent_resources = self.resource_database.get_parent_resources_by_child_type(
         "child")
     self.assertIn(parent_resource, parent_resources)
     # Reverse query would not have any result.
     parent_resources = self.resource_database.get_parent_resources_by_child_type(
         "parent")
     self.assertFalse(parent_resources)
     # Search parent resource for an non-existing resource, should return [].
     parent_resources = self.resource_database.get_parent_resources_by_child_type(
         "non-existing")
     self.assertFalse(parent_resources)
    def test_resource_reference_removal_breaking3(self):
        # Removed resource reference is defined by child type, which can not
        # be resolved to identical resource with the message options.
        # Original field has resource reference `example.v1/Foo`.
        field_options = make_field_annotation_resource_reference(
            resource_type="example.v1/Foo", is_child_type=True
        )
        field_with_reference = make_field(name="Test", options=field_options)
        # Update field has no resource reference, and the removed resource child type
        # is not identical with the message resource option.
        message_resource = make_resource_descriptor(
            resource_type="example.v1/Bar", resource_patterns=["bar/{bar}"]
        )
        field_resource = make_resource_descriptor(
            resource_type="example.v1/Foo", resource_patterns=["foo/{foo}"]
        )
        # Register the two resources in the database.
        resource_database = make_resource_database(
            resources=[message_resource, field_resource]
        )

        field_without_reference = make_field(
            name="Test",
            resource_database=resource_database,
            message_resource=message_resource,
        )
        FieldComparator(
            field_with_reference,
            field_without_reference,
            self.finding_container,
            context="ctx",
        ).compare()
        # `bar/{bar}` is not parent resource of `foo/{foo}`.
        finding = self.finding_container.get_actionable_findings()[0]
        self.assertEqual(finding.category.name, "RESOURCE_REFERENCE_REMOVAL")
        self.assertEqual(finding.change_type.name, "MAJOR")