blob: 0e785b3eee6b46ea6767e35414999da06a346357 [file] [log] [blame]
Lann Martin4fbdf202018-08-30 12:02:52 -06001# -*- coding: utf-8 -*-
2# Copyright 2018 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Tests for scripts/repo_sync_manifest."""
7
8from __future__ import print_function
9
Lann Martin4fbdf202018-08-30 12:02:52 -060010import os
Mike Frysinger2688ef62020-02-16 00:00:46 -050011import sys
Lann Martin4fbdf202018-08-30 12:02:52 -060012
Mike Frysinger6db648e2018-07-24 19:57:58 -040013import mock
14
Lann Martin4fbdf202018-08-30 12:02:52 -060015from chromite.lib import cros_build_lib
16from chromite.lib import cros_test_lib
17from chromite.lib import git
18from chromite.lib import osutils
19from chromite.lib import parallel_unittest
20from chromite.lib import repo_util
21from chromite.lib import repo_manifest
22from chromite.lib import repo_manifest_unittest
23from chromite.scripts import create_manifest_snapshot
24
25
Mike Frysinger2688ef62020-02-16 00:00:46 -050026assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
27
28
Lann Martin4fbdf202018-08-30 12:02:52 -060029MANIFEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
30<manifest>
31 <remote name="origin"/>
32 <default remote="origin"/>
33 <project name="project/a" revision="f01dab1e"/>
34 <project name="project/b" revision="cafe1234" upstream="short"/>
35 <project name="project/c" revision="deadbeef" upstream="refs/heads/master"/>
36 <project name="dupe" revision="d1" upstream="dupe"/>
37 <project name="dupe" revision="d2" upstream="dupe"/>
38</manifest>
39"""
40
41
42class CreateManifestSnapshotTest(cros_test_lib.MockTempDirTestCase,
43 repo_manifest_unittest.XMLTestCase):
44 """Unit tests for create_manifest_snapshot."""
45
46 # pylint: disable=protected-access
47
48 def setUp(self):
49 self.manifest = repo_manifest.Manifest.FromString(MANIFEST_XML)
50 self.project_a = self.manifest.GetUniqueProject('project/a')
51 self.project_b = self.manifest.GetUniqueProject('project/b')
52 self.project_c = self.manifest.GetUniqueProject('project/c')
53 self.dupes = [x for x in self.manifest.Projects() if x.name == 'dupe']
54
55 self.mock_is_reachable = self.PatchObject(git, 'IsReachable')
56 self.mock_git_push = self.PatchObject(git, 'GitPush')
57
58 self.repo_root = os.path.join(self.tempdir, 'root')
59 os.makedirs(os.path.join(self.repo_root, '.repo'))
60 self.output_file = os.path.join(self.tempdir, 'snapshot.xml')
61 self.main_args = ['--repo-path', self.repo_root,
62 '--log-level', 'fatal',
63 '--jobs', '1',
64 '--output-file', self.output_file]
65 self.PatchObject(repo_util.Repository, 'Manifest',
66 return_value=self.manifest)
67
68 def testGetUpstreamBranchNoUpstream(self):
69 """Test _GetUpstreamBranch with no upstream."""
70 branch = create_manifest_snapshot._GetUpstreamBranch(self.project_a)
71 self.assertIsNone(branch)
72
73 def testGetUpstreamBranchShortUpstream(self):
74 """Test _GetUpstreamBranch with short upstream ref."""
75 branch = create_manifest_snapshot._GetUpstreamBranch(self.project_b)
76 self.assertEqual(branch, 'short')
77
78 def testGetUpstreamBranchFullUpstream(self):
79 """Test _GetUpstreamBranch with full upstream ref."""
80 branch = create_manifest_snapshot._GetUpstreamBranch(self.project_c)
81 self.assertEqual(branch, 'master')
82
83 def testNeedsSnapshotReachable(self):
84 """Test _NeedsSnapshot with revision reachable from upstream."""
85 self.mock_is_reachable.return_value = True
86 result = create_manifest_snapshot._NeedsSnapshot('root', self.project_c)
87 self.assertFalse(result)
88 self.mock_is_reachable.assert_called_with(
89 'root/project/c', 'deadbeef', 'refs/remotes/origin/master')
90
91 def testNeedsSnapshotUnreachable(self):
92 """Test _NeedsSnapshot with revision reachable from upstream."""
93 self.mock_is_reachable.return_value = False
94 result = create_manifest_snapshot._NeedsSnapshot('root', self.project_b)
95 self.assertTrue(result)
96 self.mock_is_reachable.assert_called_with(
97 'root/project/b', 'cafe1234', 'refs/remotes/origin/short')
98
99 def testNeedsSnapshotNoUpstream(self):
100 """Test _NeedsSnapshot with no project upstream."""
101 create_manifest_snapshot._NeedsSnapshot('root', self.project_a)
102 self.mock_is_reachable.assert_called_with(
103 'root/project/a', 'f01dab1e', 'refs/remotes/origin/master')
104
105 def testNeedsSnapshotIsReachableFailure(self):
106 """Test _NeedsSnapshot with no project upstream."""
Mike Frysinger929f3ba2019-09-12 03:24:59 -0400107 self.mock_is_reachable.side_effect = cros_build_lib.RunCommandError('')
Lann Martin4fbdf202018-08-30 12:02:52 -0600108 result = create_manifest_snapshot._NeedsSnapshot('root', self.project_a)
109 self.assertTrue(result)
110
111 def testMakeUniqueRefMaster(self):
112 """Test _MakeUniqueRef with upstream master."""
113 used = set()
114 ref1 = create_manifest_snapshot._MakeUniqueRef(self.project_c, 'base', used)
115 ref2 = create_manifest_snapshot._MakeUniqueRef(self.project_c, 'base', used)
116 ref3 = create_manifest_snapshot._MakeUniqueRef(self.project_c, 'base', used)
117 self.assertEqual(ref1, 'base')
118 self.assertEqual(ref2, 'base/1')
119 self.assertEqual(ref3, 'base/2')
120
121 def testMakeUniqueRefNonMaster(self):
122 """Test _MakeUniqueRef with non-master upstream."""
123 used = set()
124 ref1 = create_manifest_snapshot._MakeUniqueRef(self.project_b, 'base', used)
125 ref2 = create_manifest_snapshot._MakeUniqueRef(self.project_b, 'base', used)
126 self.assertEqual(ref1, 'base/short')
127 self.assertEqual(ref2, 'base/short/1')
128
129 def testGitPushProjectUpstream(self):
130 """Test _GitPushProjectUpstream."""
131 create_manifest_snapshot._GitPushProjectUpstream(
132 'root', self.project_b, False)
133 self.mock_git_push.assert_called_with(
134 'root/project/b', 'cafe1234', git.RemoteRef('origin', 'short'),
135 dry_run=False)
136
137 def testGitPushProjectUpstreamDryRun(self):
138 """Test _GitPushProjectUpstream with dry_run=True."""
139 create_manifest_snapshot._GitPushProjectUpstream(
140 'root', self.project_b, True)
141 self.mock_git_push.assert_called_with(
142 'root/project/b', 'cafe1234', git.RemoteRef('origin', 'short'),
143 dry_run=True)
144
145 def testMainNoSnapshots(self):
146 """Test main with projects that don't need snapshots."""
147 self.mock_is_reachable.return_value = True
148 create_manifest_snapshot.main(self.main_args)
149 snapshot_xml = osutils.ReadFile(self.output_file)
150 self.AssertXMLAlmostEqual(snapshot_xml, MANIFEST_XML)
151
152 def testMainSnapshots(self):
153 """Test main with projects that need snapshots."""
154 self.mock_is_reachable.return_value = False
155 args = self.main_args + ['--snapshot-ref', 'refs/snap']
156 with parallel_unittest.ParallelMock():
157 create_manifest_snapshot.main(args)
158 snapshot_xml = osutils.ReadFile(self.output_file)
159
160 self.mock_git_push.assert_has_calls([
161 mock.call(os.path.join(self.repo_root, 'project/a'),
162 'f01dab1e', git.RemoteRef('origin', 'refs/snap'),
163 dry_run=False),
164 mock.call(os.path.join(self.repo_root, 'project/b'),
165 'cafe1234', git.RemoteRef('origin', 'refs/snap'),
166 dry_run=False),
167 mock.call(os.path.join(self.repo_root, 'project/c'),
168 'deadbeef', git.RemoteRef('origin', 'refs/snap'),
169 dry_run=False),
170 mock.call(os.path.join(self.repo_root, 'dupe'),
171 'd1', git.RemoteRef('origin', 'refs/snap/dupe'),
172 dry_run=False),
173 mock.call(os.path.join(self.repo_root, 'dupe'),
174 'd2', git.RemoteRef('origin', 'refs/snap/dupe/1'),
175 dry_run=False),
176 ], any_order=True)
177
178 expected = repo_manifest.Manifest.FromString(MANIFEST_XML)
179 for project in expected.Projects():
180 if project.name == 'dupe':
181 if project.revision == 'd1':
182 project.upstream = 'refs/snap/dupe'
183 else:
184 project.upstream = 'refs/snap/dupe/1'
185 else:
186 project.upstream = 'refs/snap'
187 expected_xml = repo_manifest_unittest.ManifestToString(expected)
188 self.AssertXMLAlmostEqual(snapshot_xml, expected_xml)
189
190 def testMainNeedsSnapshotNoSnapshotRef(self):
191 """Test main with projects that need snapshots but no --snapshot-ref."""
192 self.mock_is_reachable.return_value = False
193 with self.assertRaises(SystemExit):
194 create_manifest_snapshot.main(self.main_args)