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