| #!/usr/bin/env python3 |
| # Copyright 2022 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Unit tests for dependency_analysis.target_dependency.""" |
| |
| from typing import List, Optional |
| import unittest |
| import unittest.mock |
| |
| import target_dependency |
| |
| |
| def create_mock_java_class(targets: Optional[List[str]] = None, |
| pkg='package', |
| cls='class'): |
| mock_class = unittest.mock.Mock() |
| mock_class.class_name = cls |
| mock_class.package = pkg |
| mock_class.name = f'{pkg}.{cls}' |
| mock_class.build_targets = targets |
| return mock_class |
| |
| |
| class TestJavaTargetDependencyGraph(unittest.TestCase): |
| """Unit tests for JavaTargetDependencyGraph. |
| |
| Full name: dependency_analysis.class_dependency.JavaTargetDependencyGraph. |
| """ |
| TEST_TARGET1 = 'target1' |
| TEST_TARGET2 = 'target2' |
| TEST_CLS = 'class' |
| |
| def test_initialization(self): |
| """Tests that initialization collapses a class dependency graph.""" |
| # Create three class nodes (1, 2, 3) in two targets: [1, 2] and [3]. |
| |
| mock_class_node_1 = create_mock_java_class(targets=[self.TEST_TARGET1]) |
| mock_class_node_2 = create_mock_java_class(targets=[self.TEST_TARGET1]) |
| mock_class_node_3 = create_mock_java_class(targets=[self.TEST_TARGET2]) |
| |
| # Create dependencies (1 -> 3) and (3 -> 2). |
| mock_class_graph = unittest.mock.Mock() |
| mock_class_graph.nodes = [ |
| mock_class_node_1, mock_class_node_2, mock_class_node_3 |
| ] |
| mock_class_graph.edges = [(mock_class_node_1, mock_class_node_3), |
| (mock_class_node_3, mock_class_node_2)] |
| |
| test_graph = target_dependency.JavaTargetDependencyGraph( |
| mock_class_graph) |
| |
| # Expected output: two-node target graph with a bidirectional edge. |
| self.assertEqual(test_graph.num_nodes, 2) |
| self.assertEqual(test_graph.num_edges, 2) |
| self.assertIsNotNone(test_graph.get_node_by_key(self.TEST_TARGET1)) |
| self.assertIsNotNone(test_graph.get_node_by_key(self.TEST_TARGET2)) |
| # Ensure there is a bidirectional edge. |
| (edge_1_start, edge_1_end), (edge_2_start, |
| edge_2_end) = test_graph.edges |
| self.assertEqual(edge_1_start, edge_2_end) |
| self.assertEqual(edge_2_start, edge_1_end) |
| |
| def test_initialization_no_dependencies(self): |
| """Tests that a target with no external dependencies is included.""" |
| # Create one class node (1) in one target: [1]. |
| mock_class_node = create_mock_java_class(targets=[self.TEST_TARGET1]) |
| |
| # Do not create any dependencies. |
| mock_class_graph = unittest.mock.Mock() |
| mock_class_graph.nodes = [mock_class_node] |
| mock_class_graph.edges = [] |
| |
| test_graph = target_dependency.JavaTargetDependencyGraph( |
| mock_class_graph) |
| |
| # Expected output: one-node package graph with no edges. |
| self.assertEqual(test_graph.num_nodes, 1) |
| self.assertEqual(test_graph.num_edges, 0) |
| self.assertIsNotNone(test_graph.get_node_by_key(self.TEST_TARGET1)) |
| |
| def test_initialization_internal_dependencies(self): |
| """Tests that a target with only internal dependencies has no edges. |
| |
| It is not useful to include intra-target dependencies in a build target |
| dependency graph. |
| """ |
| # Create two class nodes (1, 2) in one target: [1, 2]. |
| mock_class_node_1 = create_mock_java_class(targets=[self.TEST_TARGET1]) |
| mock_class_node_2 = create_mock_java_class(targets=[self.TEST_TARGET1]) |
| |
| # Create a dependency (1 -> 2). |
| mock_class_graph = unittest.mock.Mock() |
| mock_class_graph.nodes = [mock_class_node_1, mock_class_node_2] |
| mock_class_graph.edges = [(mock_class_node_1, mock_class_node_2)] |
| |
| test_graph = target_dependency.JavaTargetDependencyGraph( |
| mock_class_graph) |
| |
| # Expected output: one-node package graph with no edges. |
| self.assertEqual(test_graph.num_nodes, 1) |
| self.assertEqual(test_graph.num_edges, 0) |
| self.assertIsNotNone(test_graph.get_node_by_key(self.TEST_TARGET1)) |
| |
| def test_initialization_allows_multiple_targets_per_class(self): |
| """Tests that initialization handles a class in multiple targets.""" |
| # Create three class nodes (1, 2, 3) in in two targets [1, 2], [1, 3]. |
| |
| mock_class_node_1 = create_mock_java_class( |
| targets=[self.TEST_TARGET1, self.TEST_TARGET2]) |
| mock_class_node_2 = create_mock_java_class(targets=[self.TEST_TARGET1]) |
| mock_class_node_3 = create_mock_java_class(targets=[self.TEST_TARGET2]) |
| |
| # Create dependencies (1 -> 3) and (3 -> 2). |
| mock_class_graph = unittest.mock.Mock() |
| mock_class_graph.nodes = [ |
| mock_class_node_1, mock_class_node_2, mock_class_node_3 |
| ] |
| mock_class_graph.edges = [(mock_class_node_1, mock_class_node_3), |
| (mock_class_node_3, mock_class_node_2)] |
| |
| test_graph = target_dependency.JavaTargetDependencyGraph( |
| mock_class_graph) |
| |
| # Expected output: two-node target graph with a bidirectional edge and |
| # no self edge: target1 <=> target2 |
| self.assertEqual(test_graph.num_nodes, 2) |
| self.assertEqual(test_graph.num_edges, 2) |
| target1_node = test_graph.get_node_by_key(self.TEST_TARGET1) |
| target2_node = test_graph.get_node_by_key(self.TEST_TARGET2) |
| self.assertIsNotNone(target1_node) |
| self.assertIsNotNone(target2_node) |
| # Ensure there is a bidirectional edge. |
| (edge_1_start, edge_1_end), (edge_2_start, |
| edge_2_end) = test_graph.edges |
| self.assertEqual(edge_1_start, edge_2_end) |
| self.assertEqual(edge_2_start, edge_1_end) |
| |
| def test_create_node_from_key(self): |
| """Tests that a JavaTarget is correctly generated.""" |
| mock_class_graph = unittest.mock.Mock() |
| mock_class_graph.nodes = [] |
| mock_class_graph.edges = [] |
| test_graph = target_dependency.JavaTargetDependencyGraph( |
| mock_class_graph) |
| |
| created_node = test_graph.create_node_from_key(self.TEST_TARGET1) |
| self.assertEqual(created_node.name, self.TEST_TARGET1) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |