1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# -*- coding: utf-8 -*- 3*760c253cSXin Li# Copyright 2020 The ChromiumOS Authors 4*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 5*760c253cSXin Li# found in the LICENSE file. 6*760c253cSXin Li 7*760c253cSXin Li"""Tests for rust_watch.py.""" 8*760c253cSXin Li 9*760c253cSXin Liimport logging 10*760c253cSXin Liimport pathlib 11*760c253cSXin Liimport subprocess 12*760c253cSXin Liimport time 13*760c253cSXin Liimport unittest 14*760c253cSXin Liimport unittest.mock 15*760c253cSXin Li 16*760c253cSXin Lifrom cros_utils import tiny_render 17*760c253cSXin Liimport rust_watch 18*760c253cSXin Li 19*760c253cSXin Li 20*760c253cSXin Liclass Test(unittest.TestCase): 21*760c253cSXin Li """Tests.""" 22*760c253cSXin Li 23*760c253cSXin Li def _silence_logs(self): 24*760c253cSXin Li """Silences all log output until the end of the current test.""" 25*760c253cSXin Li 26*760c253cSXin Li def should_log(_record): 27*760c253cSXin Li return 0 28*760c253cSXin Li 29*760c253cSXin Li logger = logging.root 30*760c253cSXin Li logger.addFilter(should_log) 31*760c253cSXin Li self.addCleanup(logger.removeFilter, should_log) 32*760c253cSXin Li 33*760c253cSXin Li def test_release_version_parsing(self): 34*760c253cSXin Li self.assertEqual( 35*760c253cSXin Li rust_watch.RustReleaseVersion.from_string("1.2.3"), 36*760c253cSXin Li rust_watch.RustReleaseVersion(1, 2, 3), 37*760c253cSXin Li ) 38*760c253cSXin Li 39*760c253cSXin Li def test_release_version_json_round_trips(self): 40*760c253cSXin Li ver = rust_watch.RustReleaseVersion(1, 2, 3) 41*760c253cSXin Li self.assertEqual( 42*760c253cSXin Li rust_watch.RustReleaseVersion.from_json(ver.to_json()), ver 43*760c253cSXin Li ) 44*760c253cSXin Li 45*760c253cSXin Li def test_state_json_round_trips(self): 46*760c253cSXin Li state = rust_watch.State( 47*760c253cSXin Li last_seen_release=rust_watch.RustReleaseVersion(1, 2, 3), 48*760c253cSXin Li last_gentoo_sha="abc123", 49*760c253cSXin Li ) 50*760c253cSXin Li 51*760c253cSXin Li self.assertEqual(rust_watch.State.from_json(state.to_json()), state) 52*760c253cSXin Li 53*760c253cSXin Li @unittest.mock.patch.object(subprocess, "run") 54*760c253cSXin Li @unittest.mock.patch.object(time, "sleep") 55*760c253cSXin Li def test_update_git_repo_tries_again_on_failure(self, sleep_mock, run_mock): 56*760c253cSXin Li self._silence_logs() 57*760c253cSXin Li 58*760c253cSXin Li oh_no_error = ValueError("oh no") 59*760c253cSXin Li 60*760c253cSXin Li def check_returncode(): 61*760c253cSXin Li raise oh_no_error 62*760c253cSXin Li 63*760c253cSXin Li run_call_count = 0 64*760c253cSXin Li 65*760c253cSXin Li def run_sideeffect(*_args, **_kwargs): 66*760c253cSXin Li nonlocal run_call_count 67*760c253cSXin Li run_call_count += 1 68*760c253cSXin Li result = unittest.mock.Mock() 69*760c253cSXin Li result.returncode = 1 70*760c253cSXin Li result.check_returncode = check_returncode 71*760c253cSXin Li return result 72*760c253cSXin Li 73*760c253cSXin Li run_mock.side_effect = run_sideeffect 74*760c253cSXin Li 75*760c253cSXin Li with self.assertRaises(ValueError) as raised: 76*760c253cSXin Li rust_watch.update_git_repo(pathlib.Path("/does/not/exist/at/all")) 77*760c253cSXin Li 78*760c253cSXin Li self.assertIs(raised.exception, oh_no_error) 79*760c253cSXin Li self.assertEqual(run_call_count, 5) 80*760c253cSXin Li 81*760c253cSXin Li sleep_timings = [unittest.mock.call(60 * i) for i in range(1, 5)] 82*760c253cSXin Li self.assertEqual(sleep_mock.mock_calls, sleep_timings) 83*760c253cSXin Li 84*760c253cSXin Li @unittest.mock.patch.object(subprocess, "run") 85*760c253cSXin Li def test_get_new_gentoo_commits_functions(self, run_mock): 86*760c253cSXin Li returned = unittest.mock.Mock() 87*760c253cSXin Li returned.returncode = 0 88*760c253cSXin Li returned.stdout = "\n".join( 89*760c253cSXin Li ( 90*760c253cSXin Li "abc123 newer commit", 91*760c253cSXin Li "abcdef and an older commit", 92*760c253cSXin Li ) 93*760c253cSXin Li ) 94*760c253cSXin Li run_mock.return_value = returned 95*760c253cSXin Li results = rust_watch.get_new_gentoo_commits( 96*760c253cSXin Li pathlib.Path("/does/not/exist/at/all"), "defabc" 97*760c253cSXin Li ) 98*760c253cSXin Li self.assertEqual( 99*760c253cSXin Li results, 100*760c253cSXin Li [ 101*760c253cSXin Li rust_watch.GitCommit("abcdef", "and an older commit"), 102*760c253cSXin Li rust_watch.GitCommit("abc123", "newer commit"), 103*760c253cSXin Li ], 104*760c253cSXin Li ) 105*760c253cSXin Li 106*760c253cSXin Li def test_compose_email_on_a_new_gentoo_commit(self): 107*760c253cSXin Li sha_a = "a" * 40 108*760c253cSXin Li new_commit = rust_watch.maybe_compose_email( 109*760c253cSXin Li new_gentoo_commits=[ 110*760c253cSXin Li rust_watch.GitCommit( 111*760c253cSXin Li sha=sha_a, 112*760c253cSXin Li subject="summary_a", 113*760c253cSXin Li ), 114*760c253cSXin Li ], 115*760c253cSXin Li ) 116*760c253cSXin Li 117*760c253cSXin Li self.assertEqual( 118*760c253cSXin Li new_commit, 119*760c253cSXin Li ( 120*760c253cSXin Li "[rust-watch] new rust ebuild commit detected", 121*760c253cSXin Li [ 122*760c253cSXin Li "commit:", 123*760c253cSXin Li tiny_render.UnorderedList( 124*760c253cSXin Li [ 125*760c253cSXin Li [ 126*760c253cSXin Li tiny_render.Link( 127*760c253cSXin Li rust_watch.gentoo_sha_to_link(sha_a), 128*760c253cSXin Li sha_a[:12], 129*760c253cSXin Li ), 130*760c253cSXin Li ": summary_a", 131*760c253cSXin Li ], 132*760c253cSXin Li ] 133*760c253cSXin Li ), 134*760c253cSXin Li ], 135*760c253cSXin Li ), 136*760c253cSXin Li ) 137*760c253cSXin Li 138*760c253cSXin Li def test_compose_email_composes_nothing_when_no_new_updates_exist(self): 139*760c253cSXin Li self.assertIsNone(rust_watch.maybe_compose_email(new_gentoo_commits=())) 140*760c253cSXin Li 141*760c253cSXin Li def test_compose_bug_creates_bugs_on_new_versions(self): 142*760c253cSXin Li bug_body_start = "A new Rust stable release has been detected;" 143*760c253cSXin Li title, body = rust_watch.maybe_compose_bug( 144*760c253cSXin Li old_state=rust_watch.State( 145*760c253cSXin Li last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0), 146*760c253cSXin Li last_gentoo_sha="", 147*760c253cSXin Li ), 148*760c253cSXin Li newest_release=rust_watch.RustReleaseVersion(1, 0, 1), 149*760c253cSXin Li ) 150*760c253cSXin Li self.assertEqual(title, "[Rust] Update to 1.0.1") 151*760c253cSXin Li self.assertTrue(body.startswith(bug_body_start)) 152*760c253cSXin Li 153*760c253cSXin Li title, body = rust_watch.maybe_compose_bug( 154*760c253cSXin Li old_state=rust_watch.State( 155*760c253cSXin Li last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0), 156*760c253cSXin Li last_gentoo_sha="", 157*760c253cSXin Li ), 158*760c253cSXin Li newest_release=rust_watch.RustReleaseVersion(1, 1, 0), 159*760c253cSXin Li ) 160*760c253cSXin Li self.assertEqual(title, "[Rust] Update to 1.1.0") 161*760c253cSXin Li self.assertTrue(body.startswith(bug_body_start)) 162*760c253cSXin Li 163*760c253cSXin Li title, body = rust_watch.maybe_compose_bug( 164*760c253cSXin Li old_state=rust_watch.State( 165*760c253cSXin Li last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0), 166*760c253cSXin Li last_gentoo_sha="", 167*760c253cSXin Li ), 168*760c253cSXin Li newest_release=rust_watch.RustReleaseVersion(2, 0, 0), 169*760c253cSXin Li ) 170*760c253cSXin Li self.assertEqual(title, "[Rust] Update to 2.0.0") 171*760c253cSXin Li self.assertTrue(body.startswith(bug_body_start)) 172*760c253cSXin Li 173*760c253cSXin Li def test_compose_bug_does_nothing_when_no_new_updates_exist(self): 174*760c253cSXin Li self.assertIsNone( 175*760c253cSXin Li rust_watch.maybe_compose_bug( 176*760c253cSXin Li old_state=rust_watch.State( 177*760c253cSXin Li last_seen_release=rust_watch.RustReleaseVersion(1, 0, 0), 178*760c253cSXin Li last_gentoo_sha="", 179*760c253cSXin Li ), 180*760c253cSXin Li newest_release=rust_watch.RustReleaseVersion(1, 0, 0), 181*760c253cSXin Li ) 182*760c253cSXin Li ) 183*760c253cSXin Li 184*760c253cSXin Li 185*760c253cSXin Liif __name__ == "__main__": 186*760c253cSXin Li unittest.main() 187