1# Copyright (C) 2020 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Test manifest diff.""" 15import unittest 16import xml.etree.ElementTree as ET 17 18import manifest_diff 19 20 21class ManifestDiffTest(unittest.TestCase): 22 23 def _assertEqualCanonical(self, change1, change2): 24 def _canonicalize(change): 25 return { 26 identifier : ' '.join(sorted(value.split(' '))) 27 for identifier, value in change.items() 28 } 29 return self.assertEqual(_canonicalize(change1), _canonicalize(change2)) 30 31 def test_project_changes(self): 32 p1 = ET.fromstring("""<project attr1="hello"> 33 <linkfile src="newfile2" dest="notneeded" /> 34 <linkfile src="oldfile1" dest="dest1" /> 35 <copyfile src="oldfile2" dest="dest2" /> 36 </project> 37 """) 38 p2 = ET.fromstring("""<project> 39 <linkfile src="newfile1" dest="dest1" /> 40 <copyfile src="newfile2" dest="dest2" /> 41 <copyfile src="somefile" dest="addedfile" /> 42 </project> 43 """) 44 changes = manifest_diff.project_changes(p1, p2, set()) 45 self.assertEqual(changes.linkfiles.added, {}) 46 self._assertEqualCanonical( 47 changes.linkfiles.removed, 48 {'notneeded': '<linkfile src="newfile2" dest="notneeded" />'}) 49 self.assertEqual( 50 changes.linkfiles.modified, { 51 'dest1': 52 manifest_diff.ChangeMap(modified={ 53 'src': manifest_diff.Change('oldfile1', 'newfile1') 54 }) 55 }) 56 self._assertEqualCanonical( 57 changes.copyfiles.added, 58 {'addedfile': '<copyfile src="somefile" dest="addedfile" />'}) 59 self.assertEqual(changes.copyfiles.removed, {}) 60 self.assertEqual( 61 changes.copyfiles.modified, { 62 'dest2': 63 manifest_diff.ChangeMap(modified={ 64 'src': manifest_diff.Change('oldfile2', 'newfile2') 65 }) 66 }) 67 self.assertEqual( 68 changes.attributes, 69 manifest_diff.ChangeMap( 70 added={}, removed={'attr1': 'hello'}, modified={})) 71 72 def test_project_changes_same(self): 73 p1 = ET.fromstring("""<project attr1="hello"> 74 <linkfile src="newfile2" dest="notneeded" /> 75 <linkfile src="oldfile1" dest="dest1" /> 76 <copyfile src="oldfile2" dest="dest2" /> 77 </project> 78 """) 79 changes = manifest_diff.project_changes(p1, p1, set()) 80 self.assertFalse(changes) 81 82 def test_compare_single_node_elements(self): 83 m1 = ET.fromstring("""<manifest> 84 <default revision='dev' remote='aosp' /> 85 <repo-hooks /> 86 </manifest> 87 """) 88 m2 = ET.fromstring("""<manifest> 89 <default revision='release' /> 90 </manifest> 91 """) 92 changes = manifest_diff.compare_single_node_elements(m1, m2, set()) 93 self.assertEqual(changes.added, {}) 94 self._assertEqualCanonical(changes.removed, {'repo-hooks': '<repo-hooks />'}) 95 self.assertEqual( 96 changes.modified, { 97 'default': 98 manifest_diff.ChangeMap( 99 added={}, 100 removed={'remote': 'aosp'}, 101 modified={ 102 'revision': manifest_diff.Change('dev', 'release') 103 }) 104 }) 105 106 def test_compare_remote_elements(self): 107 m1 = ET.fromstring("""<manifest> 108 <remote revision="dev" name="aosp" fetch="https://aosp-source.com" /> 109 <remote name="android" fetch="https://android-source.com" attr="test" /> 110 <repo-hooks /> 111 </manifest> 112 """) 113 m2 = ET.fromstring("""<manifest> 114 <remote revision="dev" name="android" fetch="https://android-source.com" 115 attr="test2"/> 116 </manifest> 117 """) 118 changes = manifest_diff.compare_remote_elements(m1, m2, set()) 119 self.assertEqual(changes.added, {}) 120 self._assertEqualCanonical( 121 changes.removed, { 122 'aosp': 123 '<remote revision="dev" name="aosp" fetch="https://aosp-source.com" />' 124 }) 125 self.assertEqual( 126 changes.modified, { 127 'android': 128 manifest_diff.ChangeMap( 129 added={'revision': 'dev'}, 130 removed={}, 131 modified={'attr': manifest_diff.Change('test', 'test2')}) 132 }) 133 134 def test_compare_project_elements(self): 135 m1 = ET.fromstring("""<manifest> 136 <project name="platform/project1" path="system/project1" /> 137 <project name="platform/project2" path="system/project2" /> 138 <project name="platform/project3" path="system/project3" /> 139 </manifest>""") 140 m2 = ET.fromstring("""<manifest> 141 <project name="platform/project1" path="system/project1" /> 142 <project name="system/project2" /> 143 <project name="platform/project4" path="system/project4" /> 144 </manifest>""") 145 changes = manifest_diff.compare_project_elements(m1, m2, set()) 146 self._assertEqualCanonical( 147 changes.added, { 148 'system/project4': 149 '<project name="platform/project4" path="system/project4" />' 150 }) 151 self._assertEqualCanonical( 152 changes.removed, { 153 'system/project3': 154 '<project name="platform/project3" path="system/project3" />' 155 }) 156 self.assertEqual( 157 changes.modified, { 158 'system/project2': 159 manifest_diff.ProjectChanges( 160 attributes=manifest_diff.ChangeMap( 161 added={}, 162 removed={}, 163 modified={ 164 'name': 165 manifest_diff.Change('platform/project2', 166 'system/project2') 167 })) 168 }) 169