示例#1
0
 def test_attribute_name_map(self):
   """Test Control snapshot name map and order."""
   converter = mock.MagicMock()
   block = SnapshotBlockConverter(converter, [])
   block.child_type = "Control"
   self.assertEqual(
       block._attribute_name_map.items(),
       [
           ('slug', 'Code'),
           ('audit', 'Audit'),  # inserted attribute
           ('revision_date', 'Revision Date'),  # inserted attribute
           ('title', 'Title'),
           ('description', 'Description'),
           ('notes', 'Notes'),
           ('test_plan', 'Test Plan'),
           ('owners', 'Admin'),
           ('start_date', 'Effective Date'),
           ('end_date', 'Stop Date'),
           ('status', 'State'),
           ('os_state', 'Review State'),
           ('assertions', 'Assertions'),
           ('categories', 'Categories'),
           ('fraud_related', 'Fraud Related'),
           ('key_control', 'Significance'),
           ('kind', 'Kind/Nature'),
           ('means', 'Type/Means'),
           ('url', 'Control URL'),
           ('reference_url', 'Reference URL'),
           ('verify_frequency', 'Frequency'),
           ('document_evidence', 'Evidence'),
       ]
   )
示例#2
0
 def test_attribute_name_map(self):
     """Test Control snapshot name map and order."""
     converter = mock.MagicMock()
     block = SnapshotBlockConverter(converter, [])
     block.child_type = "Control"
     self.assertEqual(
         block._attribute_name_map.items(),
         [
             ('slug', 'Code'),
             ('audit', 'Audit'),  # inserted attribute
             ('revision_date', 'Revision Date'),  # inserted attribute
             ('title', 'Title'),
             ('description', 'Description'),
             ('notes', 'Notes'),
             ('test_plan', 'Test Plan'),
             ('start_date', 'Effective Date'),
             ('end_date', 'Last Deprecated Date'),
             ('status', 'State'),
             ('os_state', 'Review State'),
             ('assertions', 'Assertions'),
             ('categories', 'Categories'),
             ('fraud_related', 'Fraud Related'),
             ('key_control', 'Significance'),
             ('kind', 'Kind/Nature'),
             ('means', 'Type/Means'),
             ('reference_url', 'Reference URL'),
             ('verify_frequency', 'Frequency'),
             ('document_evidence', 'Evidence'),
             ('last_assessment_date', 'Last Assessment Date'),
         ])
示例#3
0
 def test_invalid_child_types(self):
   """Test child_type property with invalid snapshots list."""
   with factories.single_commit():
     snapshots = self._create_snapshots(
         factories.AuditFactory(),
         [factories.ControlFactory(), factories.PolicyFactory()],
     )
   converter = mock.MagicMock()
   ids = [s.id for s in snapshots]
   block = SnapshotBlockConverter(converter, ids)
   with self.assertRaises(AssertionError):
     block.child_type = block.child_type
示例#4
0
 def test_invalid_child_types(self):
   """Test child_type property with invalid snapshots list."""
   with factories.single_commit():
     snapshots = self._create_snapshots(
         factories.AuditFactory(),
         [factories.ControlFactory(), factories.PolicyFactory()],
     )
   converter = mock.MagicMock()
   ids = [s.id for s in snapshots]
   block = SnapshotBlockConverter(converter, ids)
   with self.assertRaises(AssertionError):
     block.child_type = block.child_type
示例#5
0
  def test_attribute_name_map(self):
    """Test Control snapshot name map and order."""
    converter = mock.MagicMock()
    block = SnapshotBlockConverter(converter, [])
    block.child_type = "Control"
    expected_attrs = [
        ('slug', 'Code'),
        ('audit', 'Audit'),  # inserted attribute
        ('revision_date', 'Revision Date'),  # inserted attribute
        ('title', 'Title'),
        ('description', 'Description'),
        ('notes', 'Notes'),
        ('test_plan', 'Assessment Procedure'),
        ('start_date', 'Effective Date'),
        ('end_date', 'Last Deprecated Date'),
        ('archived', 'Archived'),
        ('status', 'State'),
        ('review_status', 'Review State'),
        ('reviewers', 'Reviewers'),
        ('assertions', 'Assertions'),
        ('categories', 'Categories'),
        ('fraud_related', 'Fraud Related'),
        ('key_control', 'Significance'),
        ('kind', 'Kind/Nature'),
        ('means', 'Type/Means'),
        ('verify_frequency', 'Frequency'),
        ('recipients', 'Recipients'),
        ('send_by_default', 'Send by default'),
        ('documents_file', 'Document File'),
        ('documents_reference_url', 'Reference URL'),
        ('updated_at', 'Last Updated Date'),
        ('modified_by', 'Last Updated By'),
        ('created_at', 'Created Date'),
        ('folder', "Folder"),
    ]
    ac_roles = db.session.query(all_models.AccessControlRole.name).filter(
        all_models.AccessControlRole.object_type == "Control",
        all_models.AccessControlRole.internal == 0,
    ).all()
    expected_attrs += sorted(
        ("__acl__:{}".format(role[0]), role[0]) for role in ac_roles
    )
    # last_assessment_date and comments should be in the end
    # according to current order
    expected_attrs.append(('comments', 'Comments'))
    expected_attrs.append(('last_assessment_date', 'Last Assessment Date'))

    self.assertEqual(
        block._attribute_name_map.items(),
        expected_attrs
    )
示例#6
0
  def test_attribute_name_map(self):
    """Test Control snapshot name map and order."""
    converter = mock.MagicMock()
    block = SnapshotBlockConverter(converter, [])
    block.child_type = "Control"
    expected_attrs = [
        ('slug', 'Code'),
        ('audit', 'Audit'),  # inserted attribute
        ('revision_date', 'Revision Date'),  # inserted attribute
        ('title', 'Title'),
        ('description', 'Description'),
        ('notes', 'Notes'),
        ('test_plan', 'Assessment Procedure'),
        ('start_date', 'Effective Date'),
        ('end_date', 'Last Deprecated Date'),
        ('archived', 'Archived'),
        ('status', 'State'),
        ('os_state', 'Review State'),
        ('assertions', 'Assertions'),
        ('categories', 'Categories'),
        ('fraud_related', 'Fraud Related'),
        ('key_control', 'Significance'),
        ('kind', 'Kind/Nature'),
        ('means', 'Type/Means'),
        ('verify_frequency', 'Frequency'),
        ('recipients', 'Recipients'),
        ('send_by_default', 'Send by default'),
        ('documents_file', 'Document File'),
        ('documents_reference_url', 'Reference URL'),
        ('updated_at', 'Last Updated Date'),
        ('modified_by', 'Last Updated By'),
        ('created_at', 'Created Date'),
        ('folder', "Folder"),
    ]
    ac_roles = db.session.query(all_models.AccessControlRole.name).filter(
        all_models.AccessControlRole.object_type == "Control",
        all_models.AccessControlRole.internal == 0,
    ).all()
    expected_attrs += sorted(
        ("__acl__:{}".format(role[0]), role[0]) for role in ac_roles
    )
    # last_assessment_date and comments should be in the end
    # according to current order
    expected_attrs.append(('comments', 'Comments'))
    expected_attrs.append(('last_assessment_date', 'Last Assessment Date'))

    self.assertEqual(
        block._attribute_name_map.items(),
        expected_attrs
    )
示例#7
0
  def initialize_block_converters(self):
    """Generate block converters.

    Generate block converters from a list of tuples with an object name and
    ids and store it to an instance variable.
    """
    object_map = {o.__name__: o for o in self.exportable.values()}
    exportable_queries = self._get_exportable_queries()
    for object_data in exportable_queries:
      class_name = object_data["object_name"]
      object_class = object_map[class_name]
      object_ids = object_data.get("ids", [])
      fields = object_data.get("fields", "all")
      if class_name == "Snapshot":
        self.block_converters.append(
            SnapshotBlockConverter(self, object_ids, fields=fields)
        )
      else:
        block_converter = base_block.ExportBlockConverter(
            self,
            object_class=object_class,
            fields=fields,
            object_ids=object_ids,
            class_name=class_name,
        )
        self.block_converters.append(block_converter)
示例#8
0
 def test_valid_child_types(self):
   """Test child_type property with valid snapshots list."""
   with factories.single_commit():
     snapshots = self._create_snapshots(
         factories.AuditFactory(),
         [factories.ControlFactory(), factories.ControlFactory()],
     )
   converter = mock.MagicMock()
   ids = [s.id for s in snapshots]
   block = SnapshotBlockConverter(converter, ids)
   self.assertEqual(block.child_type, "Control")
示例#9
0
    def test_snapshots_property(self):
        """Test snapshots property and snapshot content."""
        with factories.single_commit():
            snapshots = self._create_snapshots(
                factories.AuditFactory(),
                [factories.ControlFactory()],
            )

        converter = mock.MagicMock()
        ids = [s.id for s in snapshots]
        block = SnapshotBlockConverter(converter, ids)
        self.assertEqual(block.snapshots, snapshots)
        for snapshot in snapshots:
            self.assertIn("audit", snapshot.content)
示例#10
0
  def block_converters_from_ids(self):
    """Generate block converters.

    Generate block converters from a list of tuples with an object name and
    ids and store it to an instance variable.
    """
    object_map = {o.__name__: o for o in self.exportable.values()}
    for object_data in self.ids_by_type:
      class_name = object_data["object_name"]
      object_class = object_map[class_name]
      object_ids = object_data.get("ids", [])
      fields = object_data.get("fields")
      if class_name == "Snapshot":
        self.block_converters.append(
            SnapshotBlockConverter(self, object_ids, fields=fields))
      else:
        block_converter = BlockConverter(self, object_class=object_class,
                                         fields=fields, object_ids=object_ids,
                                         class_name=class_name)
        block_converter.check_block_restrictions()
        self.block_converters.append(block_converter)
示例#11
0
 def setUp(self):
     super(TestSnapshotBlockConverter, self).setUp()
     converter = mock.MagicMock()
     ids = []
     self.block = SnapshotBlockConverter(converter, ids)
示例#12
0
class TestSnapshotBlockConverter(unittest.TestCase):
    """Unit tests for Snapshot block converter."""

    # Removing protected access checks because we wish to tests even the
    # protected functions.
    # pylint: disable=protected-access

    def setUp(self):
        super(TestSnapshotBlockConverter, self).setUp()
        converter = mock.MagicMock()
        ids = []
        self.block = SnapshotBlockConverter(converter, ids)

    @staticmethod
    def _mock_snapshot_factory(content_list):
        return [mock.MagicMock(content=content) for content in content_list]

    @classmethod
    def _dummy_cad_snapshots(cls):
        return cls._mock_snapshot_factory([{
            "id":
            44,
            "custom_attribute_definitions": [
                {
                    "id": 1,
                    "title": "CCC"
                },
                {
                    "id": 2,
                    "title": "BBB"
                },
            ],
        }, {
            "id":
            45,
            "custom_attribute_definitions": [
                {
                    "id": 1,
                    "title": "CCC"
                },
                {
                    "id": 3,
                    "title": "AAA"
                },
                {
                    "id": 4,
                    "title": "DDD"
                },
            ],
        }])

    def test_gather_stubs(self):
        """Test _gather_stubs method."""
        self.block.snapshots = self._mock_snapshot_factory([{
            "id":
            44,
            "owners": [
                {
                    "type": "person",
                    "id": 1
                },
                {
                    "type": "person",
                    "id": 2
                },
            ],
            "contact": {
                "type": "person",
                "id": 2
            },
            "cavs": [
                {
                    "cav_value": {
                        "type": "person",
                        "id": 3
                    }
                },
                {
                    "cav_value": {
                        "type": "option",
                        "id": 3
                    },
                    "type": "cav",
                    "id": 6,
                },
            ],
            "options": [{
                "type": "option",
                "id": 1
            }],
        }, {
            "id":
            44,
            "type":
            "other",
            "options": [{
                "type": "option",
                "id": 4
            }],
        }])
        stubs = self.block._gather_stubs()
        self.assertEqual(stubs, {
            "person": {1, 2, 3},
            "option": {1, 3, 4},
            "other": {44},
            "cav": {6},
        })

    def test_cad_map(self):
        """Test gathering name map for all custom attribute definitions."""
        self.block.snapshots = self._dummy_cad_snapshots()
        self.assertEqual(self.block._cad_map.items(), [
            (3, {
                "id": 3,
                "title": "AAA"
            }),
            (2, {
                "id": 2,
                "title": "BBB"
            }),
            (1, {
                "id": 1,
                "title": "CCC"
            }),
            (4, {
                "id": 4,
                "title": "DDD"
            }),
        ])

    def test_cad_name_map(self):
        """Test gathering name map for all custom attribute definitions."""
        self.block.snapshots = self._dummy_cad_snapshots()
        self.assertEqual(self.block._cad_name_map.items(), [
            (3, "AAA"),
            (2, "BBB"),
            (1, "CCC"),
            (4, "DDD"),
        ])

    @mock.patch("ggrc.converters.snapshot_block.models")
    @mock.patch("ggrc.converters.snapshot_block.AttributeInfo")
    def test_attribute_name_map(self, attribute_info, _):
        """Test getting attribute name map for a valid model."""
        self.block.child_type = "Dummy"
        attribute_info.gather_visible_aliases.return_value = {
            "key_1": "BBB",
            "key_2": "DDD",
            "key_3": {
                "display_name": "AAA"
            },
            "key_4": {
                "display_name": "CCC"
            },
        }
        attribute_info.get_column_order.return_value = [
            "key_3",
            "audit",
            "key_2",
            "key_1",
            "key_4",
        ]
        self.assertEqual(
            self.block._attribute_name_map.items(),
            [
                ("key_3", "AAA"),
                ("audit", "Audit"),  # inserted snapshot attribute
                ("key_2", "DDD"),
                ("key_1", "BBB"),
                ("key_4", "CCC"),
            ])

    @mock.patch("ggrc.converters.snapshot_block.models")
    def test_bad_attribute_name_map(self, models):
        """Test getting attribute name map for an invalid model."""
        self.block.child_type = "Dummy"
        models.all_models.Dummy = None
        self.assertEqual(self.block._attribute_name_map.items(), [])

    @ddt.data(
        ({
            "random_item": "Random value"
        }, "random_item", "Random value"),
        ({
            "dummy_item": "stored_value_1"
        }, "dummy_item", "User Text"),
        ({
            "dummy_item": True
        }, "dummy_item", "Stored boolean value"),
        ({
            "dummy_item": None
        }, "dummy_item", ""),
    )
    @ddt.unpack
    def test_get_content_string(self, content, attr_name, expected_value):
        """Test getting content for special mapped values."""
        self.block.get_value_string = lambda x: x or ""
        self.block.child_type = "Dummy Object"
        self.block._content_value_map = {
            "Dummy Object": {
                "dummy_item": {
                    "stored_value_1": "User Text",
                    True: "Stored boolean value",
                }
            }
        }
        self.assertEqual(self.block.get_content_string(content, attr_name),
                         expected_value)

    @ddt.data(
        ({
            "dummy_date": None
        }, "dummy_date", ""),
        ({
            "dummy_date": ""
        }, "dummy_date", ""),
        ({
            "random_item": "Random value",
        }, "random_item", "Random value"),
        ({
            "dummy_date": "2022-02-22",
        }, "dummy_date", "02/22/2022"),
        ({
            "dummy_date": "2017-04-08T17:57:09",
        }, "dummy_date", "04/08/2017"),
    )
    @ddt.unpack
    def test_get_content_string_date(self, content, attr_name, expected_value):
        """Test getting content for date values."""
        self.block.get_value_string = lambda x: x or ""
        self.block.DATE_FIELDS = {"dummy_date"}
        self.assertEqual(self.block.get_content_string(content, attr_name),
                         expected_value)

    @ddt.data(
        (None, ""),
        ([], ""),
        ({}, ""),
        (True, "yes"),
        (False, "no"),
        ("Foo", "Foo"),
        ({
            "type": "Fake",
            "id": 4
        }, ""),
        ({
            "type": "Dummy",
            "id": -3
        }, ""),
        ({
            "type": "Dummy",
            "id": 1
        }, "AAA"),
        ([
            {
                "type": "Dummy",
                "id": 1
            },
            {
                "type": "Object",
                "id": 1
            },
            {
                "type": "Dummy",
                "id": 3
            },
        ], "AAA\nDDD\nCCC"),
    )
    @ddt.unpack
    def test_get_value_string(self, value, expected_value):
        """Test get value string function for all value types."""
        self.block._stub_cache = {
            "Dummy": {
                1: "AAA",
                2: "BBB",
                3: "CCC",
            },
            "Object": {
                1: "DDD",
            }
        }
        self.assertEqual(self.block.get_value_string(value), expected_value)

    def test_invalid_cav_dict(self):
        """Test getting ca value from invalid cav representation."""
        with self.assertRaises(TypeError):
            self.block.get_cav_value_string("XX")
        with self.assertRaises(KeyError):
            self.block.get_cav_value_string({})

    @ddt.data(
        (None, ""),
        ({
            "custom_attribute_id": 2,
            "attribute_value": None
        }, ""),
        ({
            "custom_attribute_id": 2,
            "attribute_value": "2012-05-22"
        }, "05/22/2012"),
        ({
            "custom_attribute_id": 2,
            "attribute_value": ""
        }, ""),
        ({
            "custom_attribute_id": 1,
            "attribute_value": True
        }, "yes"),
        ({
            "custom_attribute_id": 1,
            "attribute_value": "1"
        }, "yes"),
        ({
            "custom_attribute_id": 1,
            "attribute_value": "0"
        }, "no"),
        ({
            "custom_attribute_id": 3,
            "attribute_value": "Person",
            "attribute_object": {
                "context_id": None,
                "href": "/api/people/4",
                "id": 4,
                "type": "Person"
            }
        }, "*****@*****.**"),
        # If the original object was deleted from the system we do not store all
        # of its values in he revision. Proper thing would be to go through
        # revisions of this object and use those static values. But we do not
        # currently support that.
        ({
            "custom_attribute_id": 3,
            "attribute_value": "Bad Option",
            "attribute_object": {
                "context_id": None,
                "href": "/api/people/4",
                "id": 4,
                "type": "Person"
            }
        }, ""),
    )
    @ddt.unpack
    def test_get_cav_value_string(self, value, expected_value):
        """Test get value string function for custom attributes."""
        self.block._cad_map = OrderedDict([
            (3, {
                "id": 3,
                "title": "AAA",
                "attribute_type": "Map:Person"
            }),
            (2, {
                "id": 2,
                "title": "BBB",
                "attribute_type": "Date"
            }),
            (1, {
                "id": 1,
                "title": "CCC",
                "attribute_type": "Checkbox"
            }),
            (4, {
                "id": 4,
                "title": "DDD",
                "attribute_type": "Map:Person"
            }),
            (5, {
                "id": 5,
                "title": "DDD",
                "attribute_type": "Text"
            }),
        ])
        self.block._stub_cache = {"Person": {4: "*****@*****.**"}}
        self.assertEqual(self.block.get_cav_value_string(value),
                         expected_value)

    @ddt.data(
        ({
            "name": "1",
            "third": "2",
            "other": "3",
        }, ["1", "3", "2"]),
        ({
            "name": "1",
            "third": "2",
        }, ["1", "", "2"]),
    )
    @ddt.unpack
    def test_obj_attr_line(self, content, expected_line):
        """Test get object attribute CSV values."""
        self.block.get_content_string = lambda x, name: x.get(name, "")
        self.block._attribute_name_map = OrderedDict([
            ("name", "display name"),
            ("other", "other display name"),
            ("third", "third display name"),
        ])
        self.assertEqual(self.block._obj_attr_line(content), expected_line)

    @ddt.data(
        ({}, ["", "", ""]),
        ({
            "custom_attribute_values": []
        }, ["", "", ""]),
        ({
            "custom_attribute_values": [{
                "custom_attribute_id": 5,
                "attribute_value": "five",
            }, {
                "custom_attribute_id": 3,
                "attribute_value": "three",
            }]
        }, ["three", "", "five"]),
        ({
            "custom_attribute_values": [{
                "custom_attribute_id": 5,
                "attribute_value": "five",
            }, {
                "custom_attribute_id": 8,
                "attribute_value": "eight",
            }]
        }, ["", "", "five"]),
    )
    @ddt.unpack
    def test_cav_attr_line(self, content, expected_line):
        """Test get custom attribute CSV values."""
        self.block.get_cav_value_string = lambda x: (x.get("attribute_value")
                                                     if x else "")
        self.block._cad_map = OrderedDict([
            (3, {
                "id": 3,
                "title": "AAA"
            }),
            (2, {
                "id": 2,
                "title": "BBB"
            }),
            (5, {
                "id": 5,
                "title": "DDD"
            }),
        ])
        self.assertEqual(self.block._cav_attr_line(content), expected_line)

    def test_header_list(self):
        """Test snapshot export header data."""
        self.block._attribute_name_map = OrderedDict([
            ("key_3", "AAA"),
            ("audit", "Audit"),  # inserted snapshot attribute
            ("key_2", "DDD"),
            ("key_1", "BBB"),
            ("key_4", "CCC"),
        ])
        self.block._cad_name_map = OrderedDict([
            (3, "A"),
            (2, "B"),
            (1, "C"),
            (4, "D"),
        ])
        self.assertEquals(
            self.block._header_list,
            [[], ["AAA", "Audit", "DDD", "BBB", "CCC", "A", "B", "C", "D"]])

    @ddt.data(
        ([], [[]]),
        ([1, 2, 3], [[], [], []]),
    )
    @ddt.unpack
    def test_body_list(self, snapshots, block_list):
        """Test basic CSV body format."""
        self.block._content_line_list = lambda x: []
        self.block.snapshots = snapshots
        self.assertEqual(self.block._body_list, block_list)
示例#13
0
 def test_empty_child_type(self):
     """Test child_type property with empty snapshots list."""
     converter = mock.MagicMock()
     block = SnapshotBlockConverter(converter, [])
     self.assertEqual(block.child_type, "")
示例#14
0
 def test_empty_snapshots(self):
     """Test snapshots property for empty ids list."""
     converter = mock.MagicMock()
     block = SnapshotBlockConverter(converter, [])
     self.assertEqual(block.snapshots, [])
示例#15
0
 def setUp(self):
   super(TestSnapshotBlockConverter, self).setUp()
   converter = mock.MagicMock()
   ids = []
   self.block = SnapshotBlockConverter(converter, ids)
示例#16
0
class TestSnapshotBlockConverter(unittest.TestCase):
  """Unit tests for Snapshot block converter."""
  # Removing protected access checks because we wish to tests even the
  # protected functions.
  # pylint: disable=protected-access

  def setUp(self):
    super(TestSnapshotBlockConverter, self).setUp()
    converter = mock.MagicMock()
    ids = []
    self.block = SnapshotBlockConverter(converter, ids)

  @staticmethod
  def _mock_snapshot_factory(content_list):
    return [mock.MagicMock(content=content) for content in content_list]

  @classmethod
  def _dummy_cad_snapshots(cls):
    return cls._mock_snapshot_factory([{
        "id": 44,
        "custom_attribute_definitions": [
            {"id": 1, "title": "CCC"},
            {"id": 2, "title": "BBB"},
        ],
    }, {
        "id": 45,
        "custom_attribute_definitions": [
            {"id": 1, "title": "CCC"},
            {"id": 3, "title": "AAA"},
            {"id": 4, "title": "DDD"},
        ],
    }])

  def test_gather_stubs(self):
    """Test _gather_stubs method."""
    self.block.snapshots = self._mock_snapshot_factory([{
        "id": 44,
        "owners": [
            {"type": "person", "id": 1},
            {"type": "person", "id": 2},
        ],
        "contact": {"type": "person", "id": 2},
        "cavs": [
            {"cav_value": {"type": "person", "id": 3}},
            {
                "cav_value": {"type": "option", "id": 3},
                "type": "cav",
                "id": 6,
            },
        ],
        "options": [{"type": "option", "id": 1}],
    }, {
        "id": 44,
        "type": "other",
        "options": [{"type": "option", "id": 4}],
    }])
    stubs = self.block._gather_stubs()
    self.assertEqual(
        stubs,
        {
            "person": {1, 2, 3},
            "option": {1, 3, 4},
            "other": {44},
            "cav": {6},
        }
    )

  def test_cad_map(self):
    """Test gathering name map for all custom attribute definitions."""
    self.block.snapshots = self._dummy_cad_snapshots()
    self.assertEqual(
        self.block._cad_map.items(),
        [
            (3, {"id": 3, "title": "AAA"}),
            (2, {"id": 2, "title": "BBB"}),
            (1, {"id": 1, "title": "CCC"}),
            (4, {"id": 4, "title": "DDD"}),
        ]
    )

  def test_cad_name_map(self):
    """Test gathering name map for all custom attribute definitions."""
    self.block.snapshots = self._dummy_cad_snapshots()
    self.assertEqual(
        self.block._cad_name_map.items(),
        [
            (3, "AAA"),
            (2, "BBB"),
            (1, "CCC"),
            (4, "DDD"),
        ]
    )

  @mock.patch("ggrc.converters.snapshot_block.models")
  @mock.patch("ggrc.converters.snapshot_block.AttributeInfo")
  def test_attribute_name_map(self, attribute_info, _):
    """Test getting attribute name map for a valid model."""
    self.block.child_type = "Dummy"
    attribute_info.gather_visible_aliases.return_value = {
        "key_1": "BBB",
        "key_2": "DDD",
        "key_3": {"display_name": "AAA"},
        "key_4": {"display_name": "CCC"},
    }
    attribute_info.get_column_order.return_value = [
        "key_3",
        "audit",
        "key_2",
        "key_1",
        "key_4",
    ]
    self.assertEqual(
        self.block._attribute_name_map.items(),
        [
            ("key_3", "AAA"),
            ("audit", "Audit"),  # inserted snapshot attribute
            ("key_2", "DDD"),
            ("key_1", "BBB"),
            ("key_4", "CCC"),
        ]
    )

  @mock.patch("ggrc.converters.snapshot_block.models")
  def test_bad_attribute_name_map(self, models):
    """Test getting attribute name map for an invalid model."""
    self.block.child_type = "Dummy"
    models.all_models.Dummy = None
    self.assertEqual(
        self.block._attribute_name_map.items(),
        []
    )

  @ddt.data(
      ({"random_item": "Random value"}, "random_item", "Random value"),
      ({"dummy_item": "stored_value_1"}, "dummy_item", "User Text"),
      ({"dummy_item": True}, "dummy_item", "Stored boolean value"),
      ({"dummy_item": None}, "dummy_item", ""),
  )
  @ddt.unpack
  def test_get_content_string(self, content, attr_name, expected_value):
    """Test getting content for special mapped values."""
    self.block.get_value_string = lambda x: x or ""
    self.block.child_type = "Dummy Object"
    self.block._content_value_map = {
        "Dummy Object": {
            "dummy_item": {
                "stored_value_1": "User Text",
                True: "Stored boolean value",
            }
        }
    }
    self.assertEqual(
        self.block.get_content_string(content, attr_name),
        expected_value
    )

  @ddt.data(
      ({"dummy_date": None}, "dummy_date", ""),
      ({"dummy_date": ""}, "dummy_date", ""),
      ({"random_item": "Random value", }, "random_item", "Random value"),
      ({"dummy_date": "2022-02-22", }, "dummy_date", "02/22/2022"),
      ({"dummy_date": "2017-04-08T17:57:09", }, "dummy_date", "04/08/2017"),
  )
  @ddt.unpack
  def test_get_content_string_date(self, content, attr_name, expected_value):
    """Test getting content for date values."""
    self.block.get_value_string = lambda x: x or ""
    self.block.DATE_FIELDS = {
        "dummy_date"
    }
    self.assertEqual(
        self.block.get_content_string(content, attr_name),
        expected_value
    )

  @ddt.data(
      (None, ""),
      ([], ""),
      ({}, ""),
      (True, "yes"),
      (False, "no"),
      ("Foo", "Foo"),
      ({"type": "Fake", "id": 4}, ""),
      ({"type": "Dummy", "id": -3}, ""),
      ({"type": "Dummy", "id": 1}, "AAA"),
      (
          [
              {"type": "Dummy", "id": 1},
              {"type": "Object", "id": 1},
              {"type": "Dummy", "id": 3},
          ],
          "AAA\nDDD\nCCC"
      ),
  )
  @ddt.unpack
  def test_get_value_string(self, value, expected_value):
    """Test get value string function for all value types."""
    self.block._stub_cache = {
        "Dummy": {
            1: "AAA",
            2: "BBB",
            3: "CCC",
        },
        "Object": {
            1: "DDD",
        }
    }
    self.assertEqual(self.block.get_value_string(value), expected_value)

  def test_invalid_cav_dict(self):
    """Test getting ca value from invalid cav representation."""
    with self.assertRaises(TypeError):
      self.block.get_cav_value_string("XX")
    with self.assertRaises(KeyError):
      self.block.get_cav_value_string({})

  @ddt.data(
      (None, ""),
      ({"custom_attribute_id": 2, "attribute_value": None}, ""),
      ({"custom_attribute_id": 2, "attribute_value": "2012-05-22"},
       "05/22/2012"),
      ({"custom_attribute_id": 2, "attribute_value": ""}, ""),
      ({"custom_attribute_id": 1, "attribute_value": True}, "yes"),
      ({"custom_attribute_id": 1, "attribute_value": "1"}, "yes"),
      ({"custom_attribute_id": 1, "attribute_value": "0"}, "no"),
      ({"custom_attribute_id": 3, "attribute_value":
        "Person", "attribute_object_id": 4}, "*****@*****.**"),
      # If the original object was deleted from the system we do not store all
      # of its values in he revision. Proper thing would be to go through
      # revisions of this object and use those static values. But we do not
      # currently support that.
      ({"custom_attribute_id": 3, "attribute_value": "Bad Option",
        "attribute_object_id": 4}, ""),
  )
  @ddt.unpack
  def test_get_cav_value_string(self, value, expected_value):
    """Test get value string function for custom attributes."""
    self.block._cad_map = OrderedDict(
        [
            (3, {"id": 3, "title": "AAA", "attribute_type": "Map:Person"}),
            (2, {"id": 2, "title": "BBB", "attribute_type": "Date"}),
            (1, {"id": 1, "title": "CCC", "attribute_type": "Checkbox"}),
            (4, {"id": 4, "title": "DDD", "attribute_type": "Map:Person"}),
            (5, {"id": 5, "title": "DDD", "attribute_type": "Text"}),
        ]
    )
    self.block._stub_cache = {
        "Person": {
            4: "*****@*****.**"
        }
    }
    self.assertEqual(self.block.get_cav_value_string(value), expected_value)

  @ddt.data(
      ({"name": "1", "third": "2", "other": "3", }, ["1", "3", "2"]),
      ({"name": "1", "third": "2", }, ["1", "", "2"]),
  )
  @ddt.unpack
  def test_obj_attr_line(self, content, expected_line):
    """Test get object attribute CSV values."""
    self.block.get_content_string = lambda x, name: x.get(name, "")
    self.block._attribute_name_map = OrderedDict([
        ("name", "display name"),
        ("other", "other display name"),
        ("third", "third display name"),
    ])
    self.assertEqual(self.block._obj_attr_line(content), expected_line)

  @ddt.data(
      ({}, ["", "", ""]),
      ({"custom_attribute_values": []}, ["", "", ""]),
      (
          {
              "custom_attribute_values": [{
                  "custom_attribute_id": 5,
                  "attribute_value": "five",
              }, {
                  "custom_attribute_id": 3,
                  "attribute_value": "three",
              }]
          },
          ["three", "", "five"]
      ),
      (
          {
              "custom_attribute_values": [{
                  "custom_attribute_id": 5,
                  "attribute_value": "five",
              }, {
                  "custom_attribute_id": 8,
                  "attribute_value": "eight",
              }]
          },
          ["", "", "five"]
      ),
  )
  @ddt.unpack
  def test_cav_attr_line(self, content, expected_line):
    """Test get custom attribute CSV values."""
    self.block.get_cav_value_string = lambda x: (
        x.get("attribute_value") if x else ""
    )
    self.block._cad_map = OrderedDict(
        [
            (3, {"id": 3, "title": "AAA"}),
            (2, {"id": 2, "title": "BBB"}),
            (5, {"id": 5, "title": "DDD"}),
        ]
    )
    self.assertEqual(self.block._cav_attr_line(content), expected_line)

  def test_header_list(self):
    """Test snapshot export header data."""
    self.block._attribute_name_map = OrderedDict([
        ("key_3", "AAA"),
        ("audit", "Audit"),  # inserted snapshot attribute
        ("key_2", "DDD"),
        ("key_1", "BBB"),
        ("key_4", "CCC"),
    ])
    self.block._cad_name_map = OrderedDict([
        (3, "A"),
        (2, "B"),
        (1, "C"),
        (4, "D"),
    ])
    self.assertEquals(
        self.block._header_list,
        [[], ["AAA", "Audit", "DDD", "BBB", "CCC", "A", "B", "C", "D"]]
    )

  @ddt.data(
      ([], [[]]),
      ([1, 2, 3], [[], [], []]),
  )
  @ddt.unpack
  def test_body_list(self, snapshots, block_list):
    """Test basic CSV body format."""
    self.block._content_line_list = lambda x: []
    self.block.snapshots = snapshots
    self.assertEqual(self.block._body_list, block_list)