def test_nested_enum_change(self):
     nested_enum1 = make_enum(
         name="Foo",
         values=(
             ("RED", 1),
             ("GREEN", 2),
         ),
     )
     nested_enum2 = make_enum(
         name="Foo",
         values=(
             ("RED", 1),
             ("GREEN", 2),
             ("BLUE", 3),
         ),
     )
     message1 = make_message(nested_enums=[nested_enum1])
     message2 = make_message(nested_enums=[nested_enum2])
     DescriptorComparator(message1, message2,
                          self.finding_container).compare()
     findings_map = {
         f.message: f
         for f in self.finding_container.getAllFindings()
     }
     finding = findings_map["A new EnumValue `BLUE` is added."]
     self.assertEqual(finding.category.name, "ENUM_VALUE_ADDITION")
     self.assertEqual(finding.change_type.name, "MINOR")
     self.assertEqual(finding.location.proto_file_name, "foo")
예제 #2
0
 def test_enum_change(self):
     enum_original = make_enum(
         name="Irrelevant",
         values=(
             ("RED", 1),
             ("GREEN", 2),
             ("BLUE", 3),
         ),
     )
     enum_update = make_enum(
         name="Irrelevant",
         values=(
             ("RED", 1),
             ("GREEN", 2),
         ),
     )
     FileSetComparator(
         make_file_set(files=[make_file_pb2(enums=[enum_original])]),
         make_file_set(files=[make_file_pb2(enums=[enum_update])]),
         self.finding_container,
     ).compare()
     finding = self.finding_container.getAllFindings()[0]
     self.assertEqual(finding.message,
                      "An existing EnumValue `BLUE` is removed.")
     self.assertEqual(finding.category.name, "ENUM_VALUE_REMOVAL")
     self.assertEqual(finding.change_type.name, "MAJOR")
     self.assertEqual(finding.location.proto_file_name, "my_proto.proto")
 def test_nested_enum_change(self):
     nested_enum1 = make_enum(
         name="Foo",
         values=(
             ("RED", 1),
             ("GREEN", 2),
         ),
     )
     nested_enum2 = make_enum(
         name="Foo",
         values=(
             ("RED", 1),
             ("GREEN", 2),
             ("BLUE", 3),
         ),
     )
     message1 = make_message(nested_enums=[nested_enum1])
     message2 = make_message(nested_enums=[nested_enum2])
     DescriptorComparator(message1,
                          message2,
                          self.finding_container,
                          context="ctx").compare()
     finding = next(f for f in self.finding_container.get_all_findings()
                    if f.category.name == "ENUM_VALUE_ADDITION")
     self.assertEqual(finding.change_type.name, "MINOR")
     self.assertEqual(finding.location.proto_file_name, "foo")
 def setUp(self):
     L = descriptor_pb2.SourceCodeInfo.Location
     # fmt: off
     locations = [
         L(path=(
             4,
             0,
         ), span=(1, 2, 3, 4)),
         # Enum will add (2, 1) for each EnumValue in the path.
         L(path=(4, 0, 2, 1), span=(2, 3, 4, 5)),
     ]
     self.enum_foo = make_enum(
         name="Foo",
         values=(("VALUE1", 1), ),
         proto_file_name="test.proto",
         locations=locations,
         path=(
             4,
             0,
         ),
     )
     self.enum_bar = make_enum(
         name="Bar",
         values=(
             ("VALUE1", 1),
             ("VALUE2", 2),
         ),
         proto_file_name="test_update.proto",
         locations=locations,
         path=(
             4,
             0,
         ),
     )
     self.finding_container = FindingContainer()
 def test_detector_without_opts(self):
     # Mock original and updated FileDescriptorSet.
     enum_foo = make_enum(name="foo")
     enum_bar = make_enum(name="bar")
     file_set_original = desc.FileDescriptorSet(
         file=[make_file_pb2(name="original.proto", enums=[enum_foo])])
     file_set_update = desc.FileDescriptorSet(
         file=[make_file_pb2(name="update.proto", enums=[enum_bar])])
     breaking_changes = Detector(file_set_original,
                                 file_set_update).detect_breaking_changes()
     # Without options, the detector returns an array of actionable Findings.
     self.assertEqual(breaking_changes[0].message,
                      "An existing Enum `foo` is removed.")
    def test_source_code_properties(self):
        L = descriptor_pb2.SourceCodeInfo.Location
        # fmt: off
        locations = [L(path=(
            4,
            0,
        ), span=(1, 2, 3, 4))]
        enum = make_enum(
            name="Foo",
            proto_file_name="test.proto",
            locations=locations,
            path=(
                4,
                0,
            ),
        )

        # fmt: on
        self.assertEqual(enum.name, "Foo")
        self.assertEqual(enum.values, {})
        self.assertEqual(enum.proto_file_name, "test.proto")
        self.assertEqual(
            enum.source_code_line,
            2,
        )
        self.assertEqual(enum.path, (4, 0))
예제 #7
0
    def test_nested_types(self):
        # Create the inner message.
        inner_msg = [
            make_message(
                "InnerMessage",
                fields=(make_field(
                    name="hidden_message",
                    number=1,
                ), ),
            )
        ]
        inner_enums = [make_enum(name="InnerEnum")]
        inner_fields = [make_field("not_interesting")]

        # Create the outer message, which contains inner fields, enums, messages.
        outer_msg = make_message(
            "Outer",
            fields=inner_fields,
            nested_enums=inner_enums,
            nested_messages=inner_msg,
        )

        self.assertEqual(len(outer_msg.fields.keys()), 1)
        self.assertEqual(outer_msg.fields[1].name, "not_interesting")
        self.assertEqual(len(outer_msg.nested_enums.keys()), 1)
        self.assertEqual(
            outer_msg.nested_messages["InnerMessage"].fields[1].name,
            "hidden_message")
예제 #8
0
 def test_enum_in_dependency_change_breaking(self):
     # Enum "dep_message" is imported from dep.proto and referenced as a field type.
     field_type_original = make_enum(
         name="dep_enum",
         proto_file_name="dep.proto",
     )
     message_original = make_message(
         fields=[make_field(type_name=".test.import.dep_enum")], )
     # Message "test_enum" is defined in update.proto referenced as a field type.
     field_type_update = make_enum(name="test_enum", )
     message_update = make_message(
         fields=[make_field(type_name="test_enum")])
     FileSetComparator(
         make_file_set(files=[
             make_file_pb2(
                 name="orignal.proto",
                 messages=[message_original],
                 dependency="test/import/dep.proto",
                 package="example.v1",
             ),
             make_file_pb2(
                 name="dep.proto",
                 enums=[field_type_original],
                 package="test.import",
             ),
         ]),
         make_file_set(files=[
             make_file_pb2(
                 name="update.proto",
                 messages=[message_update],
                 enums=[field_type_update],
                 package="example.v1beta1",
             )
         ]),
         self.finding_container,
     ).compare()
     # The breaking change should be in field level, instead of message removal,
     # since the message is imported from dependency file.
     finding = self.finding_container.getAllFindings()[0]
     self.assertEqual(
         finding.message,
         "Type of an existing field `my_field` is changed from `.test.import.dep_enum` to `test_enum`.",
     )
     self.assertEqual(finding.change_type.name, "MAJOR")
     self.assertEqual(finding.category.name, "FIELD_TYPE_CHANGE")
     self.assertEqual(finding.location.proto_file_name, "update.proto")
 def test_basic_properties(self):
     enum = make_enum("Foo")
     self.assertEqual(enum.name, "Foo")
     self.assertEqual(enum.proto_file_name, "foo")
     self.assertEqual(enum.path, ())
     self.assertEqual(
         enum.source_code_line,
         -1,
     )
     self.assertEqual(enum.full_name, ".example.foo.enum")
 def test_nested_enum_addition(self):
     DescriptorComparator(
         make_message(),
         make_message(nested_enums=[make_enum(name="nested_message")]),
         self.finding_container,
     ).compare()
     finding = self.finding_container.getAllFindings()[0]
     self.assertEqual(finding.category.name, "ENUM_ADDITION")
     self.assertEqual(finding.change_type.name, "MINOR")
     self.assertEqual(finding.location.proto_file_name, "foo")
 def test_nested_enum_removal(self):
     DescriptorComparator(
         make_message(nested_enums=[make_enum(name="nested_message")]),
         make_message(),
         self.finding_container,
         context="ctx",
     ).compare()
     finding = self.finding_container.get_all_findings()[0]
     self.assertEqual(finding.category.name, "ENUM_REMOVAL")
     self.assertEqual(finding.change_type.name, "MAJOR")
     self.assertEqual(finding.location.proto_file_name, "foo")
 def test_enum_value_properties(self):
     enum_type = make_enum(
         name="Irrelevant",
         values=(
             ("RED", 1),
             ("GREEN", 2),
             ("BLUE", 3),
         ),
     )
     self.assertEqual(len(enum_type.values), 3)
     for ev, expected in zip(enum_type.values.values(),
                             ("RED", "GREEN", "BLUE")):
         self.assertEqual(ev.name, expected)
    def test_file_set_source_code_location(self):
        L = descriptor_pb2.SourceCodeInfo.Location
        locations = [
            L(path=(4, 0, 2, 0, 5), span=(5, 2, 3, 4)),
            L(path=(4, 0, 3, 0), span=(6, 1, 2, 4)),
            L(path=(4, 0, 4, 0), span=(7, 1, 2, 4)),
            L(path=(4, 0, 4, 0, 2, 1), span=(9, 1, 2, 4)),
        ]
        messages = [
            make_message(
                "OuterMessage",
                fields=(make_field(
                    name="hidden_message",
                    number=1,
                ), ),
                nested_messages=(make_message(name="InterMessage"), ),
                nested_enums=(make_enum(
                    name="InterEnum",
                    values=(
                        ("RED", 1),
                        ("GREEN", 2),
                        ("BLUE", 3),
                    ),
                ), ),
            )
        ]

        file_pb2 = make_file_pb2(messages=messages, locations=locations)
        file_set = make_file_set(files=[file_pb2])
        self.assertEqual(
            file_set.messages_map[".example.v1.OuterMessage"].fields[1].
            proto_type.source_code_line,
            6,
        )
        self.assertEqual(
            file_set.messages_map[".example.v1.OuterMessage"].
            nested_messages["InterMessage"].source_code_line,
            7,
        )
        self.assertEqual(
            file_set.messages_map[".example.v1.OuterMessage"].
            nested_enums["InterEnum"].source_code_line,
            8,
        )
        self.assertEqual(
            file_set.messages_map[".example.v1.OuterMessage"].
            nested_enums["InterEnum"].values[2].source_code_line,
            10,
        )
 def test_file_set_properties(self):
     input_message = make_message(name="request",
                                  full_name=".example.v1.request")
     output_message = make_message(name="response",
                                   full_name=".example.v1.response")
     messages = [
         make_message(
             "InnerMessage",
             fields=(make_field(name="hidden_message",
                                number=1,
                                type_name=".example.v1.request"), ),
             full_name=".example.v1.InnerMessage",
         ),
         input_message,
         output_message,
     ]
     services = [
         make_service(
             name="ThingDoer",
             methods=(make_method(
                 name="DoThing",
                 input_message=input_message,
                 output_message=output_message,
             ), ),
         )
     ]
     enums = [
         make_enum(
             name="Irrelevant",
             values=(
                 ("RED", 1),
                 ("GREEN", 2),
                 ("BLUE", 3),
             ),
         )
     ]
     file_foo = make_file_pb2(
         name="foo.proto",
         package="example.v1",
         services=services,
         enums=enums,
         dependency=["bar.proto"],
     )
     file_bar = make_file_pb2(name="bar.proto",
                              package="example.v1",
                              messages=messages)
     file_set = make_file_set(files=[file_bar, file_foo])
     # Default to be empty.
     self.assertFalse(file_set.packaging_options_map)
     self.assertEqual(
         list(file_set.messages_map.keys()),
         [
             ".example.v1.InnerMessage", ".example.v1.request",
             ".example.v1.response"
         ],
     )
     self.assertEqual(list(file_set.enums_map.keys()),
                      [".example.v1.Irrelevant"])
     self.assertEqual(list(file_set.services_map.keys()), ["ThingDoer"])
     self.assertEqual(
         file_set.messages_map[".example.v1.InnerMessage"].fields[1].name,
         "hidden_message",
     )
     self.assertEqual(
         file_set.enums_map[".example.v1.Irrelevant"].values[2].name,
         "GREEN")
     self.assertEqual(
         list(file_set.services_map["ThingDoer"].methods.keys()),
         ["DoThing"],
     )
     self.assertEqual(list(file_set.global_enums_map.keys()),
                      [".example.v1.Irrelevant"])
     self.assertEqual(
         list(file_set.global_messages_map.keys()),
         [
             ".example.v1.response", ".example.v1.request",
             ".example.v1.InnerMessage"
         ],
     )