1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7import os
8import sys
9basepath = os.path.abspath(os.path.dirname(__file__) + '/../../../../../')
10lib_path = basepath + '/scripts/lib'
11sys.path = sys.path + [lib_path]
12import oeqa.utils.gitarchive as ga
13from oeqa.utils.git import GitError
14import tempfile
15import shutil
16import scriptutils
17import logging
18from oeqa.selftest.case import OESelftestTestCase
19
20logger = scriptutils.logger_create('resulttool')
21
22def create_fake_repository(commit, tag_list=[], add_remote=True):
23    """ Create a testing git directory
24
25    Initialize a simple git repository with one initial commit, and as many
26    tags on this commit as listed in tag_list
27    Returns both git directory path and gitarchive git object
28    If commit is true, fake data will be commited, otherwise it will stay in staging area
29    If commit is true and tag_lsit is non empty, all tags in tag_list will be
30    created on the initial commit
31    Fake remote will also be added to make git ls-remote work
32    """
33    fake_data_file = "fake_data.txt"
34    tempdir = tempfile.mkdtemp(prefix='fake_results.')
35    repo = ga.init_git_repo(tempdir, False, False, logger)
36    if add_remote:
37        repo.run_cmd(["remote", "add", "origin", "."])
38    with open(os.path.join(tempdir, fake_data_file), "w") as fake_data:
39        fake_data.write("Fake data")
40    if commit:
41        repo.run_cmd(["add", fake_data_file])
42        repo.run_cmd(["commit", "-m", "\"Add fake data\""])
43        for tag in tag_list:
44            repo.run_cmd(["tag", tag])
45
46    return tempdir, repo
47
48def delete_fake_repository(path):
49    shutil.rmtree(path)
50
51def tag_exists(git_obj, target_tag):
52    for tag in git_obj.run_cmd(["tag"]).splitlines():
53        if target_tag == tag:
54            return True
55    return False
56
57class GitArchiveTests(OESelftestTestCase):
58    TEST_BRANCH="main"
59    TEST_COMMIT="0f7d5df"
60    TEST_COMMIT_COUNT="42"
61
62    @classmethod
63    def setUpClass(cls):
64        super().setUpClass()
65        cls.log = logging.getLogger('gitarchivetests')
66        cls.log.setLevel(logging.DEBUG)
67
68    def test_create_first_test_tag(self):
69        path, git_obj = create_fake_repository(False)
70        keywords = {'commit': self.TEST_COMMIT, 'branch': self.TEST_BRANCH, "commit_count": self.TEST_COMMIT_COUNT}
71        target_tag = f"{self.TEST_BRANCH}/{self.TEST_COMMIT_COUNT}-g{self.TEST_COMMIT}/0"
72
73        ga.gitarchive(path, path, True, False,
74                              "Results of {branch}:{commit}", "branch: {branch}\ncommit: {commit}", "{branch}",
75                              False, "{branch}/{commit_count}-g{commit}/{tag_number}",
76                              'Test run #{tag_number} of {branch}:{commit}', '',
77                              [], [], False, keywords, logger)
78        self.assertTrue(tag_exists(git_obj, target_tag), msg=f"Tag {target_tag} has not been created")
79        delete_fake_repository(path)
80
81    def test_create_second_test_tag(self):
82        first_tag = f"{self.TEST_BRANCH}/{self.TEST_COMMIT_COUNT}-g{self.TEST_COMMIT}/0"
83        second_tag = f"{self.TEST_BRANCH}/{self.TEST_COMMIT_COUNT}-g{self.TEST_COMMIT}/1"
84        keywords = {'commit': self.TEST_COMMIT, 'branch': self.TEST_BRANCH, "commit_count": self.TEST_COMMIT_COUNT}
85
86        path, git_obj = create_fake_repository(True, [first_tag])
87        ga.gitarchive(path, path, True, False,
88                              "Results of {branch}:{commit}", "branch: {branch}\ncommit: {commit}", "{branch}",
89                              False, "{branch}/{commit_count}-g{commit}/{tag_number}",
90                              'Test run #{tag_number} of {branch}:{commit}', '',
91                              [], [], False, keywords, logger)
92        self.assertTrue(tag_exists(git_obj, second_tag), msg=f"Second tag {second_tag} has not been created")
93        delete_fake_repository(path)
94
95    def test_get_revs_on_branch(self):
96        fake_tags_list=["main/10-g0f7d5df/0", "main/10-g0f7d5df/1", "foo/20-g2468f5d/0"]
97        tag_name = "{branch}/{commit_number}-g{commit}/{tag_number}"
98
99        path, git_obj = create_fake_repository(True, fake_tags_list)
100        revs = ga.get_test_revs(logger, git_obj, tag_name, branch="main")
101        self.assertEqual(len(revs), 1)
102        self.assertEqual(revs[0].commit, "0f7d5df")
103        self.assertEqual(len(revs[0].tags), 2)
104        self.assertEqual(revs[0].tags, ['main/10-g0f7d5df/0', 'main/10-g0f7d5df/1'])
105        delete_fake_repository(path)
106
107    def test_get_tags_without_valid_remote(self):
108        url = 'git://git.yoctoproject.org/poky'
109        path, git_obj = create_fake_repository(False, None, False)
110
111        tags = ga.get_tags(git_obj, self.log, pattern="yocto-*", url=url)
112        """Test for some well established tags (released tags)"""
113        self.assertIn("yocto-4.0", tags)
114        self.assertIn("yocto-4.1", tags)
115        self.assertIn("yocto-4.2", tags)
116        delete_fake_repository(path)
117
118    def test_get_tags_with_only_local_tag(self):
119        fake_tags_list=["main/10-g0f7d5df/0", "main/10-g0f7d5df/1", "foo/20-g2468f5d/0"]
120        path, git_obj = create_fake_repository(True, fake_tags_list, False)
121
122        """No remote is configured and no url is passed: get_tags must fall
123        back to local tags
124        """
125        tags = ga.get_tags(git_obj, self.log)
126        self.assertCountEqual(tags, fake_tags_list)
127        delete_fake_repository(path)
128
129    def test_get_tags_without_valid_remote_and_wrong_url(self):
130        url = 'git://git.foo.org/bar'
131        path, git_obj = create_fake_repository(False, None, False)
132
133        """Test for some well established tags (released tags)"""
134        with self.assertRaises(GitError):
135            tags = ga.get_tags(git_obj, self.log, pattern="yocto-*", url=url)
136        delete_fake_repository(path)
137