123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- #!/usr/bin/env python3
- """ Tests for git_oh script """
-
- import calendar
- import datetime
- import gc
- import os
- import random
- import shutil
- import tempfile
- import unittest
-
- import git
-
- import git_oh
-
-
- class TestGitIterations(unittest.TestCase):
- """ Testing iterator on git commits """
-
- def setUp(self):
- self.repo_path = tempfile.mkdtemp(prefix="git_oh_test_")
- self.repo = git.Repo.init(self.repo_path)
- self.actors = [git.Actor(f"User{i:d}", f"user{i:d}@localhost")
- for i in range(8)]
-
- def tearDown(self):
- shutil.rmtree(self.repo_path)
-
- def test_metadata(self):
- """ Fetch commits and their metadata in a simple git repository """
- fromisoformat = datetime.datetime.fromisoformat
- commit_date_fmt = "2022-12-13T23:32:2%d+0200"
-
- commits = [
- self.git_commit_mod(author=self.actors[0],
- commit_date=fromisoformat(commit_date_fmt % i))
- for i in range(10)]
- found_commits = list(git_oh.iter_commits(self.repo))
-
- set_a = {c.hexsha for c in commits}
- set_b = {c.hexsha for c in found_commits}
-
- self.assertEqual(set_a, set_b)
-
- for commit in found_commits:
- self.assertEqual(commit.author, self.actors[0])
- self.assertLessEqual(commit.committed_datetime,
- fromisoformat(commit_date_fmt % 9))
- self.assertGreaterEqual(commit.committed_datetime,
- fromisoformat(commit_date_fmt % 0))
-
- def test_branches(self):
- """ Fetch commits from a repo with mutliple branches """
-
- commits = [self.git_commit_mod(author=self.actors[0])
- for _ in range(10)]
-
- self.repo.git.checkout("HEAD", b="new_branch")
-
- commits += [self.git_commit_mod(author=self.actors[0])
- for _ in range(10)]
-
- self.repo.git.checkout("HEAD", b="another_branch")
-
- commits += [self.git_commit_mod(author=self.actors[0])
- for _ in range(10)]
-
- self.repo.git.checkout("new_branch")
-
- found_commits = {commit.hexsha
- for commit in git_oh.iter_commits(self.repo)}
- commits = {commit.hexsha for commit in commits}
-
- self.assertEqual(commits, found_commits)
-
-
- def test_temp_remote_repo(self):
- """ Testing TempRemoteRepo class commit fetch __iter__ method """
- commits = {self.git_commit_mod(author=self.actors[0]).hexsha
- for _ in range(10)}
- repo = git_oh.TempRemoteRepo(f"file://{self.repo_path:s}",
- force_remote=True)
-
- found_commits = {commit.hexsha for commit in repo}
-
- self.assertEqual(commits, found_commits)
-
-
- def test_temp_remote_repo_cleanup(self):
- """ Testing TempRemoteRepo class cleanup """
- self.git_commit_mod(author=self.actors[0])
- repo = git_oh.TempRemoteRepo(f"file://{self.repo_path:s}",
- force_remote=True)
- tmppath = repo.temppath
-
- self.assertTrue(os.path.isdir(tmppath))
-
- # ref to commits should prevent gc to call repo.__del__()
- commits = list(repo)
-
- del repo
- gc.collect()
- self.assertTrue(os.path.isdir(tmppath))
-
- del commits
- gc.collect() # not more refs, gc should have called repo.__del__()
- self.assertFalse(os.path.isdir(tmppath))
-
-
- def test_temp_remote_repo_branches(self):
- """ Testing TempRemoteRepo branch commit fetch """
- commits = []
- for i in range(5):
- commits += [self.git_commit_mod(author=self.actors[0])
- for _ in range(10)]
- self.repo.git.checkout("HEAD", b=f"branch-{i:d}")
- repo_url = f"file://{self.repo_path:s}"
- repo = git_oh.TempRemoteRepo(repo_url, force_remote=True)
- found_commits = {commit.hexsha for commit in repo}
- commits = {commit.hexsha for commit in commits}
-
- self.assertEqual(commits, found_commits)
-
-
- def git_commit_mod(self, msg="new commit", filename="foo.txt",
- **commit_kwargs):
- """ Add a random modification to repository and commit them
- Arguments :
- - msg : commit message
- - filename : the filename to modify/add/commit
- - **commit_kwargs : see help(git.index.base.IndexFile.commit)
- Returns :
- - the commit instance
- """
- with open(os.path.join(self.repo_path, filename), "w+",
- encoding="utf-8") as repo_fp:
- repo_fp.write(random.choices("abcdef")[0])
- self.repo.index.add([filename])
- return self.repo.index.commit(msg, **commit_kwargs)
-
-
- class TestTimeUtils(unittest.TestCase):
- """ Testing in_office_hours() filter and valid_day() argument validator """
-
- def test_valid_days(self):
- """ Test day argument validator/convertion """
-
- for i, day in enumerate(calendar.day_name):
- self.assertEqual(i, git_oh.valid_day(day))
- for i, day in enumerate(calendar.day_abbr):
- self.assertEqual(i, git_oh.valid_day(day))
- for i in range(7):
- with self.subTest(day=i):
- self.assertEqual(i, git_oh.valid_day(str(i)))
-
- def test_office_hours_weekend(self):
- """ Test in_office_hours filtering weekend """
-
- weekends = ([5,6], [0], [], [1,2,3,4,5,6])
-
- daydelta = datetime.timedelta(days=1)
-
- for weekend in weekends:
- test_dt = datetime.datetime(1988,12,13,12,0,0)
-
- for _ in range(14):
- with self.subTest(weekend=weekend, moment=test_dt):
- res = git_oh.in_office_hours(test_dt,
- starthour=datetime.time(8,0,0),
- stophour=datetime.time(20,0,0),
- weekend=weekend)
- expected = test_dt.weekday() not in weekend
- self.assertEqual(expected, res)
- test_dt -= daydelta
-
- def test_office_hours(self):
- """ Test in_office_hours filtering hours """
- starthour = datetime.time(8,0)
- stophour = datetime.time(20,0)
- weekend = (5,6)
-
- off_oh = [(7,59,59),(20,0,1), (20,1), (0,0), (1,0)]
- in_oh = [(8,0), (20,0), (12,0)]
-
- for time_arg in off_oh:
- moment = datetime.datetime(2023, 11, 1, *time_arg)
- self.assertFalse(git_oh.in_office_hours(moment,
- starthour, stophour, weekend=weekend))
-
- for time_arg in in_oh:
- moment = datetime.datetime(2023, 11, 1, *time_arg)
- self.assertTrue(git_oh.in_office_hours(moment,
- starthour, stophour, weekend=weekend))
-
- def test_office_hours_tz_drop(self):
- """ Checks that in_office_hours do not use tzinfo to compare
- moment with start & stop hours
- """
- moment = datetime.datetime.fromisoformat("2023-11-01T08:00:01+0200")
- self.assertTrue(git_oh.in_office_hours(
- moment,
- datetime.time(8,0),
- datetime.time(8,1),
- weekend=[]))
-
- moment = moment.astimezone(datetime.timezone.utc)
- self.assertFalse(git_oh.in_office_hours(
- moment,
- datetime.time(8,0),
- datetime.time(8,1),
- weekend=[]))
-
- def test_office_hours_invalid_weekend(self):
- """ Test in_office_hours weekend validation """
- bad_weekend = ([-1,0,1], [5,6,7], [7])
- for badarg in bad_weekend:
- with self.assertRaises(ValueError):
- git_oh.in_office_hours(datetime.datetime.now(),
- weekend=badarg)
-
- def test_office_hours_tz_warn(self):
- """ in_office_hours should warn when tz aware times are given """
- utc_tz = datetime.timezone.utc
- some_tz = datetime.timezone(datetime.timedelta(hours=2))
- tz_aware = [
- (datetime.time(1,2,tzinfo=utc_tz), datetime.time(0,0)),
- (datetime.time(3,4,tzinfo=some_tz), datetime.time(1,0)),
- (datetime.time(4,5), datetime.time(2,0, tzinfo=utc_tz)),
- (datetime.time(4,5), datetime.time(2,0, tzinfo=some_tz)),
- (datetime.time(1,2,tzinfo=utc_tz),
- datetime.time(0,0, tzinfo=some_tz)),
- ]
-
- for bad_args in tz_aware:
- with self.assertWarns(Warning):
- git_oh.in_office_hours(datetime.datetime.now(), *bad_args)
-
- class TestCli(unittest.TestCase):
- """ Testing CLI arguments parsing """
-
- def test_weekend_parser(self):
- """ Testing weekend parser """
- for _ in range(10):
- weekend = random.choices(list(range(7)), k=random.randint(1,5))
- weekend_arg = " , ".join([calendar.day_abbr[i] for i in weekend])
- with self.subTest(weekend=f"-w '{weekend_arg}'"):
- try:
- cliargs = ["file://fake_url", "-w", weekend_arg]
- args = git_oh.parse_args(cliargs)
- self.assertEqual(set(weekend), set(args.weekend))
- except SystemExit:
- self.fail(msg="Parser fails to parse --weekend argument")
-
- def test_nul_weekend_parser(self):
- """ Testing -w NUl argument support """
- try:
- args = git_oh.parse_args(["file://fake_url", "-w", "NUL"])
- except SystemExit:
- self.fail(msg="Parser fails to parse -w NUL")
- self.assertEqual(len(args.weekend), 0)
-
-
- if __name__ == "__main__":
- unittest.main()
|