1*3c875a21SAndroid Build Coastguard Worker# 2*3c875a21SAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project 3*3c875a21SAndroid Build Coastguard Worker# 4*3c875a21SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the 'License'); 5*3c875a21SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*3c875a21SAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*3c875a21SAndroid Build Coastguard Worker# 8*3c875a21SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*3c875a21SAndroid Build Coastguard Worker# 10*3c875a21SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*3c875a21SAndroid Build Coastguard Worker# distributed under the License is distributed on an 'AS IS' BASIS, 12*3c875a21SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*3c875a21SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*3c875a21SAndroid Build Coastguard Worker# limitations under the License. 15*3c875a21SAndroid Build Coastguard Worker# 16*3c875a21SAndroid Build Coastguard Worker"""Tests for manifest.py.""" 17*3c875a21SAndroid Build Coastguard Workerimport textwrap 18*3c875a21SAndroid Build Coastguard Workerfrom pathlib import Path 19*3c875a21SAndroid Build Coastguard Worker 20*3c875a21SAndroid Build Coastguard Workerimport pytest 21*3c875a21SAndroid Build Coastguard Worker 22*3c875a21SAndroid Build Coastguard Workerfrom manifest import Manifest, ManifestParser, find_manifest_xml_for_tree 23*3c875a21SAndroid Build Coastguard Worker 24*3c875a21SAndroid Build Coastguard Worker 25*3c875a21SAndroid Build Coastguard Workerclass TestFindManifestXmlForTree: 26*3c875a21SAndroid Build Coastguard Worker """Tests for find_manifest_xml_for_tree.""" 27*3c875a21SAndroid Build Coastguard Worker 28*3c875a21SAndroid Build Coastguard Worker def test_repo_tree(self, repo_tree: Path) -> None: 29*3c875a21SAndroid Build Coastguard Worker """Tests that the correct manifest file is found in a repo tree.""" 30*3c875a21SAndroid Build Coastguard Worker manifest_dir = Path(repo_tree / ".repo/manifests") 31*3c875a21SAndroid Build Coastguard Worker manifest_dir.mkdir() 32*3c875a21SAndroid Build Coastguard Worker manifest_path = manifest_dir / "default.xml" 33*3c875a21SAndroid Build Coastguard Worker manifest_path.touch() 34*3c875a21SAndroid Build Coastguard Worker assert find_manifest_xml_for_tree(repo_tree) == manifest_path 35*3c875a21SAndroid Build Coastguard Worker 36*3c875a21SAndroid Build Coastguard Worker def test_no_manifest(self, tmp_path: Path) -> None: 37*3c875a21SAndroid Build Coastguard Worker """Tests that an error is raised when no manifest is found.""" 38*3c875a21SAndroid Build Coastguard Worker with pytest.raises(FileNotFoundError): 39*3c875a21SAndroid Build Coastguard Worker find_manifest_xml_for_tree(tmp_path) 40*3c875a21SAndroid Build Coastguard Worker 41*3c875a21SAndroid Build Coastguard Worker 42*3c875a21SAndroid Build Coastguard Workerclass TestManifestParser: 43*3c875a21SAndroid Build Coastguard Worker """Tests for ManifestParser.""" 44*3c875a21SAndroid Build Coastguard Worker 45*3c875a21SAndroid Build Coastguard Worker def test_default_missing(self, tmp_path: Path) -> None: 46*3c875a21SAndroid Build Coastguard Worker """Tests that an error is raised when the default node is missing.""" 47*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 48*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 49*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 50*3c875a21SAndroid Build Coastguard Worker """\ 51*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 52*3c875a21SAndroid Build Coastguard Worker <manifest> 53*3c875a21SAndroid Build Coastguard Worker <project path="external/project" revision="master" /> 54*3c875a21SAndroid Build Coastguard Worker </manifest> 55*3c875a21SAndroid Build Coastguard Worker """ 56*3c875a21SAndroid Build Coastguard Worker ) 57*3c875a21SAndroid Build Coastguard Worker ) 58*3c875a21SAndroid Build Coastguard Worker with pytest.raises(RuntimeError): 59*3c875a21SAndroid Build Coastguard Worker ManifestParser(manifest_path).parse() 60*3c875a21SAndroid Build Coastguard Worker 61*3c875a21SAndroid Build Coastguard Worker def test_name_missing(self, tmp_path: Path) -> None: 62*3c875a21SAndroid Build Coastguard Worker """Tests that an error is raised when neither name nor path is defined for a project.""" 63*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 64*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 65*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 66*3c875a21SAndroid Build Coastguard Worker """\ 67*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 68*3c875a21SAndroid Build Coastguard Worker <manifest> 69*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 70*3c875a21SAndroid Build Coastguard Worker 71*3c875a21SAndroid Build Coastguard Worker <project /> 72*3c875a21SAndroid Build Coastguard Worker </manifest> 73*3c875a21SAndroid Build Coastguard Worker """ 74*3c875a21SAndroid Build Coastguard Worker ) 75*3c875a21SAndroid Build Coastguard Worker ) 76*3c875a21SAndroid Build Coastguard Worker with pytest.raises(RuntimeError): 77*3c875a21SAndroid Build Coastguard Worker ManifestParser(manifest_path).parse() 78*3c875a21SAndroid Build Coastguard Worker 79*3c875a21SAndroid Build Coastguard Worker 80*3c875a21SAndroid Build Coastguard Worker def test_multiple_default(self, tmp_path: Path) -> None: 81*3c875a21SAndroid Build Coastguard Worker """Tests that an error is raised when there is more than one default node.""" 82*3c875a21SAndroid Build Coastguard Worker manifest = tmp_path / "manifest.xml" 83*3c875a21SAndroid Build Coastguard Worker manifest.write_text( 84*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 85*3c875a21SAndroid Build Coastguard Worker """\ 86*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 87*3c875a21SAndroid Build Coastguard Worker <manifest> 88*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 89*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 90*3c875a21SAndroid Build Coastguard Worker 91*3c875a21SAndroid Build Coastguard Worker <project path="external/project" revision="master" /> 92*3c875a21SAndroid Build Coastguard Worker </manifest> 93*3c875a21SAndroid Build Coastguard Worker """ 94*3c875a21SAndroid Build Coastguard Worker ) 95*3c875a21SAndroid Build Coastguard Worker ) 96*3c875a21SAndroid Build Coastguard Worker with pytest.raises(RuntimeError): 97*3c875a21SAndroid Build Coastguard Worker ManifestParser(manifest).parse() 98*3c875a21SAndroid Build Coastguard Worker 99*3c875a21SAndroid Build Coastguard Worker def test_remote_default(self, tmp_path: Path) -> None: 100*3c875a21SAndroid Build Coastguard Worker """Tests that the default remote is used when not defined by the project.""" 101*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 102*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 103*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 104*3c875a21SAndroid Build Coastguard Worker """\ 105*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 106*3c875a21SAndroid Build Coastguard Worker <manifest> 107*3c875a21SAndroid Build Coastguard Worker <remote name="aosp" /> 108*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 109*3c875a21SAndroid Build Coastguard Worker 110*3c875a21SAndroid Build Coastguard Worker <project path="external/project" /> 111*3c875a21SAndroid Build Coastguard Worker </manifest> 112*3c875a21SAndroid Build Coastguard Worker """ 113*3c875a21SAndroid Build Coastguard Worker ) 114*3c875a21SAndroid Build Coastguard Worker ) 115*3c875a21SAndroid Build Coastguard Worker manifest = ManifestParser(manifest_path).parse() 116*3c875a21SAndroid Build Coastguard Worker assert manifest.project_with_path("external/project").remote == "aosp" 117*3c875a21SAndroid Build Coastguard Worker 118*3c875a21SAndroid Build Coastguard Worker def test_revision_default(self, tmp_path: Path) -> None: 119*3c875a21SAndroid Build Coastguard Worker """Tests that the default revision is used when not defined by the project.""" 120*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 121*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 122*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 123*3c875a21SAndroid Build Coastguard Worker """\ 124*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 125*3c875a21SAndroid Build Coastguard Worker <manifest> 126*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 127*3c875a21SAndroid Build Coastguard Worker 128*3c875a21SAndroid Build Coastguard Worker <project path="external/project" /> 129*3c875a21SAndroid Build Coastguard Worker </manifest> 130*3c875a21SAndroid Build Coastguard Worker """ 131*3c875a21SAndroid Build Coastguard Worker ) 132*3c875a21SAndroid Build Coastguard Worker ) 133*3c875a21SAndroid Build Coastguard Worker manifest = ManifestParser(manifest_path).parse() 134*3c875a21SAndroid Build Coastguard Worker assert manifest.project_with_path("external/project").revision == "main" 135*3c875a21SAndroid Build Coastguard Worker 136*3c875a21SAndroid Build Coastguard Worker def test_path_default(self, tmp_path: Path) -> None: 137*3c875a21SAndroid Build Coastguard Worker """Tests that the default path is used when not defined by the project.""" 138*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 139*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 140*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 141*3c875a21SAndroid Build Coastguard Worker """\ 142*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 143*3c875a21SAndroid Build Coastguard Worker <manifest> 144*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 145*3c875a21SAndroid Build Coastguard Worker 146*3c875a21SAndroid Build Coastguard Worker <project name="external/project" /> 147*3c875a21SAndroid Build Coastguard Worker </manifest> 148*3c875a21SAndroid Build Coastguard Worker """ 149*3c875a21SAndroid Build Coastguard Worker ) 150*3c875a21SAndroid Build Coastguard Worker ) 151*3c875a21SAndroid Build Coastguard Worker manifest = ManifestParser(manifest_path).parse() 152*3c875a21SAndroid Build Coastguard Worker assert manifest.project_with_path("external/project") is not None 153*3c875a21SAndroid Build Coastguard Worker 154*3c875a21SAndroid Build Coastguard Worker def test_remote_explicit(self, tmp_path: Path) -> None: 155*3c875a21SAndroid Build Coastguard Worker """Tests that the project remote is used when defined.""" 156*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 157*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 158*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 159*3c875a21SAndroid Build Coastguard Worker """\ 160*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 161*3c875a21SAndroid Build Coastguard Worker <manifest> 162*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 163*3c875a21SAndroid Build Coastguard Worker 164*3c875a21SAndroid Build Coastguard Worker <project path="external/project" remote="origin" /> 165*3c875a21SAndroid Build Coastguard Worker </manifest> 166*3c875a21SAndroid Build Coastguard Worker """ 167*3c875a21SAndroid Build Coastguard Worker ) 168*3c875a21SAndroid Build Coastguard Worker ) 169*3c875a21SAndroid Build Coastguard Worker manifest = ManifestParser(manifest_path).parse() 170*3c875a21SAndroid Build Coastguard Worker assert manifest.project_with_path("external/project").remote == "origin" 171*3c875a21SAndroid Build Coastguard Worker 172*3c875a21SAndroid Build Coastguard Worker def test_revision_explicit(self, tmp_path: Path) -> None: 173*3c875a21SAndroid Build Coastguard Worker """Tests that the project revision is used when defined.""" 174*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 175*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 176*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 177*3c875a21SAndroid Build Coastguard Worker """\ 178*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 179*3c875a21SAndroid Build Coastguard Worker <manifest> 180*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 181*3c875a21SAndroid Build Coastguard Worker 182*3c875a21SAndroid Build Coastguard Worker <project path="external/project" revision="master" /> 183*3c875a21SAndroid Build Coastguard Worker </manifest> 184*3c875a21SAndroid Build Coastguard Worker """ 185*3c875a21SAndroid Build Coastguard Worker ) 186*3c875a21SAndroid Build Coastguard Worker ) 187*3c875a21SAndroid Build Coastguard Worker manifest = ManifestParser(manifest_path).parse() 188*3c875a21SAndroid Build Coastguard Worker assert manifest.project_with_path("external/project").revision == "master" 189*3c875a21SAndroid Build Coastguard Worker 190*3c875a21SAndroid Build Coastguard Worker def test_path_explicit(self, tmp_path: Path) -> None: 191*3c875a21SAndroid Build Coastguard Worker """Tests that the project path is used when defined.""" 192*3c875a21SAndroid Build Coastguard Worker manifest_path = tmp_path / "manifest.xml" 193*3c875a21SAndroid Build Coastguard Worker manifest_path.write_text( 194*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 195*3c875a21SAndroid Build Coastguard Worker """\ 196*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 197*3c875a21SAndroid Build Coastguard Worker <manifest> 198*3c875a21SAndroid Build Coastguard Worker <default revision="main" remote="aosp" /> 199*3c875a21SAndroid Build Coastguard Worker 200*3c875a21SAndroid Build Coastguard Worker <project name="external/project" path="other/path" /> 201*3c875a21SAndroid Build Coastguard Worker </manifest> 202*3c875a21SAndroid Build Coastguard Worker """ 203*3c875a21SAndroid Build Coastguard Worker ) 204*3c875a21SAndroid Build Coastguard Worker ) 205*3c875a21SAndroid Build Coastguard Worker manifest = ManifestParser(manifest_path).parse() 206*3c875a21SAndroid Build Coastguard Worker assert manifest.project_with_path("other/path") is not None 207*3c875a21SAndroid Build Coastguard Worker 208*3c875a21SAndroid Build Coastguard Workerclass TestManifest: 209*3c875a21SAndroid Build Coastguard Worker """Tests for Manifest.""" 210*3c875a21SAndroid Build Coastguard Worker 211*3c875a21SAndroid Build Coastguard Worker def test_for_tree(self, repo_tree: Path) -> None: 212*3c875a21SAndroid Build Coastguard Worker """Tests the Manifest.for_tree constructor.""" 213*3c875a21SAndroid Build Coastguard Worker manifest_dir = Path(repo_tree / ".repo/manifests") 214*3c875a21SAndroid Build Coastguard Worker manifest_dir.mkdir() 215*3c875a21SAndroid Build Coastguard Worker (manifest_dir / "default.xml").write_text( 216*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 217*3c875a21SAndroid Build Coastguard Worker """\ 218*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 219*3c875a21SAndroid Build Coastguard Worker <manifest> 220*3c875a21SAndroid Build Coastguard Worker <default remote="aosp" revision="main" /> 221*3c875a21SAndroid Build Coastguard Worker 222*3c875a21SAndroid Build Coastguard Worker <project path="external/a" /> 223*3c875a21SAndroid Build Coastguard Worker <project path="external/b" /> 224*3c875a21SAndroid Build Coastguard Worker <project path="external/c" /> 225*3c875a21SAndroid Build Coastguard Worker </manifest> 226*3c875a21SAndroid Build Coastguard Worker """ 227*3c875a21SAndroid Build Coastguard Worker ) 228*3c875a21SAndroid Build Coastguard Worker ) 229*3c875a21SAndroid Build Coastguard Worker manifest = Manifest.for_tree(repo_tree) 230*3c875a21SAndroid Build Coastguard Worker assert len(manifest.projects_by_path) == 3 231*3c875a21SAndroid Build Coastguard Worker 232*3c875a21SAndroid Build Coastguard Worker def test_project_with_path(self, repo_tree: Path) -> None: 233*3c875a21SAndroid Build Coastguard Worker """Tests that Manifest.project_with_path returns the correct project.""" 234*3c875a21SAndroid Build Coastguard Worker manifest_dir = Path(repo_tree / ".repo/manifests") 235*3c875a21SAndroid Build Coastguard Worker manifest_dir.mkdir() 236*3c875a21SAndroid Build Coastguard Worker (manifest_dir / "default.xml").write_text( 237*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 238*3c875a21SAndroid Build Coastguard Worker """\ 239*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 240*3c875a21SAndroid Build Coastguard Worker <manifest> 241*3c875a21SAndroid Build Coastguard Worker <default remote="aosp" revision="main" /> 242*3c875a21SAndroid Build Coastguard Worker 243*3c875a21SAndroid Build Coastguard Worker <project path="external/a" /> 244*3c875a21SAndroid Build Coastguard Worker <project path="external/b" /> 245*3c875a21SAndroid Build Coastguard Worker <project path="external/c" /> 246*3c875a21SAndroid Build Coastguard Worker </manifest> 247*3c875a21SAndroid Build Coastguard Worker """ 248*3c875a21SAndroid Build Coastguard Worker ) 249*3c875a21SAndroid Build Coastguard Worker ) 250*3c875a21SAndroid Build Coastguard Worker manifest = Manifest.for_tree(repo_tree) 251*3c875a21SAndroid Build Coastguard Worker assert manifest.project_with_path("external/b").path == "external/b" 252*3c875a21SAndroid Build Coastguard Worker 253*3c875a21SAndroid Build Coastguard Worker def test_project_with_path_missing(self, repo_tree: Path) -> None: 254*3c875a21SAndroid Build Coastguard Worker """Tests that Manifest.project_with_path raises an error when not found.""" 255*3c875a21SAndroid Build Coastguard Worker manifest_dir = Path(repo_tree / ".repo/manifests") 256*3c875a21SAndroid Build Coastguard Worker manifest_dir.mkdir() 257*3c875a21SAndroid Build Coastguard Worker (manifest_dir / "default.xml").write_text( 258*3c875a21SAndroid Build Coastguard Worker textwrap.dedent( 259*3c875a21SAndroid Build Coastguard Worker """\ 260*3c875a21SAndroid Build Coastguard Worker <?xml version="1.0" encoding="UTF-8"?> 261*3c875a21SAndroid Build Coastguard Worker <manifest> 262*3c875a21SAndroid Build Coastguard Worker <default remote="aosp" revision="main" /> 263*3c875a21SAndroid Build Coastguard Worker 264*3c875a21SAndroid Build Coastguard Worker <project path="external/a" /> 265*3c875a21SAndroid Build Coastguard Worker <project path="external/b" /> 266*3c875a21SAndroid Build Coastguard Worker <project path="external/c" /> 267*3c875a21SAndroid Build Coastguard Worker </manifest> 268*3c875a21SAndroid Build Coastguard Worker """ 269*3c875a21SAndroid Build Coastguard Worker ) 270*3c875a21SAndroid Build Coastguard Worker ) 271*3c875a21SAndroid Build Coastguard Worker manifest = Manifest.for_tree(repo_tree) 272*3c875a21SAndroid Build Coastguard Worker with pytest.raises(KeyError): 273*3c875a21SAndroid Build Coastguard Worker manifest.project_with_path("external/d") 274