#!/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()