xref: /aosp_15_r20/external/mesa3d/bin/gen_calendar_entries_test.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*61046927SAndroid Build Coastguard Worker# SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker
4*61046927SAndroid Build Coastguard Worker# Copyright © 2021 Intel Corporation
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a copy
7*61046927SAndroid Build Coastguard Worker# of this software and associated documentation files (the "Software"), to deal
8*61046927SAndroid Build Coastguard Worker# in the Software without restriction, including without limitation the rights
9*61046927SAndroid Build Coastguard Worker# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*61046927SAndroid Build Coastguard Worker# copies of the Software, and to permit persons to whom the Software is
11*61046927SAndroid Build Coastguard Worker# furnished to do so, subject to the following conditions:
12*61046927SAndroid Build Coastguard Worker
13*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice shall be included in
14*61046927SAndroid Build Coastguard Worker# all copies or substantial portions of the Software.
15*61046927SAndroid Build Coastguard Worker
16*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*61046927SAndroid Build Coastguard Worker# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*61046927SAndroid Build Coastguard Worker# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*61046927SAndroid Build Coastguard Worker# SOFTWARE.
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Workerfrom __future__ import annotations
25*61046927SAndroid Build Coastguard Workerfrom unittest import mock
26*61046927SAndroid Build Coastguard Workerimport argparse
27*61046927SAndroid Build Coastguard Workerimport csv
28*61046927SAndroid Build Coastguard Workerimport contextlib
29*61046927SAndroid Build Coastguard Workerimport datetime
30*61046927SAndroid Build Coastguard Workerimport tempfile
31*61046927SAndroid Build Coastguard Workerimport os
32*61046927SAndroid Build Coastguard Workerimport pathlib
33*61046927SAndroid Build Coastguard Workerimport typing
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Workerimport pytest
36*61046927SAndroid Build Coastguard Worker
37*61046927SAndroid Build Coastguard Workerfrom . import gen_calendar_entries
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Worker
40*61046927SAndroid Build Coastguard Worker@contextlib.contextmanager
41*61046927SAndroid Build Coastguard Workerdef mock_csv(data: typing.List[gen_calendar_entries.CalendarRowType]) -> typing.Iterator[None]:
42*61046927SAndroid Build Coastguard Worker    """Replace the actual CSV data with our test data."""
43*61046927SAndroid Build Coastguard Worker    with tempfile.TemporaryDirectory() as d:
44*61046927SAndroid Build Coastguard Worker        c = os.path.join(d, 'calendar.csv')
45*61046927SAndroid Build Coastguard Worker        with open(c, 'w') as f:
46*61046927SAndroid Build Coastguard Worker            writer = csv.writer(f)
47*61046927SAndroid Build Coastguard Worker            writer.writerows(data)
48*61046927SAndroid Build Coastguard Worker
49*61046927SAndroid Build Coastguard Worker        with mock.patch('bin.gen_calendar_entries.CALENDAR_CSV', pathlib.Path(c)):
50*61046927SAndroid Build Coastguard Worker            yield
51*61046927SAndroid Build Coastguard Worker
52*61046927SAndroid Build Coastguard Worker
53*61046927SAndroid Build Coastguard Worker@pytest.fixture(autouse=True, scope='module')
54*61046927SAndroid Build Coastguard Workerdef disable_git_commits() -> None:
55*61046927SAndroid Build Coastguard Worker    """Mock out the commit function so no git commits are made during testing."""
56*61046927SAndroid Build Coastguard Worker    with mock.patch('bin.gen_calendar_entries.commit', mock.Mock()):
57*61046927SAndroid Build Coastguard Worker        yield
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker
60*61046927SAndroid Build Coastguard Workerclass TestReleaseStart:
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker    def test_first_is_wednesday(self) -> None:
63*61046927SAndroid Build Coastguard Worker        d = gen_calendar_entries._calculate_release_start('20', '0')
64*61046927SAndroid Build Coastguard Worker        assert d.day == 15
65*61046927SAndroid Build Coastguard Worker        assert d.month == 1
66*61046927SAndroid Build Coastguard Worker        assert d.year == 2020
67*61046927SAndroid Build Coastguard Worker
68*61046927SAndroid Build Coastguard Worker    def test_first_is_before_wednesday(self) -> None:
69*61046927SAndroid Build Coastguard Worker        d = gen_calendar_entries._calculate_release_start('19', '0')
70*61046927SAndroid Build Coastguard Worker        assert d.day == 16
71*61046927SAndroid Build Coastguard Worker        assert d.month == 1
72*61046927SAndroid Build Coastguard Worker        assert d.year == 2019
73*61046927SAndroid Build Coastguard Worker
74*61046927SAndroid Build Coastguard Worker    def test_first_is_after_wednesday(self) -> None:
75*61046927SAndroid Build Coastguard Worker        d = gen_calendar_entries._calculate_release_start('21', '0')
76*61046927SAndroid Build Coastguard Worker        assert d.day == 13
77*61046927SAndroid Build Coastguard Worker        assert d.month == 1
78*61046927SAndroid Build Coastguard Worker        assert d.year == 2021
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Workerclass TestNextReleaseDate:
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard Worker    @contextlib.contextmanager
84*61046927SAndroid Build Coastguard Worker    def _patch_date(date: datetime.date) -> typing.Iterator[None]:
85*61046927SAndroid Build Coastguard Worker        mdate = mock.Mock()
86*61046927SAndroid Build Coastguard Worker        mdate.today = mock.Mock(return_value=date)
87*61046927SAndroid Build Coastguard Worker        with mock.patch('bin.gen_calendar_entries.datetime.date', mdate):
88*61046927SAndroid Build Coastguard Worker            yield
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker    class TestIsWeds:
91*61046927SAndroid Build Coastguard Worker
92*61046927SAndroid Build Coastguard Worker        @pytest.fixture(scope='class', autouse=True)
93*61046927SAndroid Build Coastguard Worker        def data(self) -> None:
94*61046927SAndroid Build Coastguard Worker            date = datetime.date(2021, 1, 6)
95*61046927SAndroid Build Coastguard Worker            with TestNextReleaseDate._patch_date(date):
96*61046927SAndroid Build Coastguard Worker                yield
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker        @pytest.mark.parametrize(
99*61046927SAndroid Build Coastguard Worker            'is_zero, expected',
100*61046927SAndroid Build Coastguard Worker            [
101*61046927SAndroid Build Coastguard Worker                (True, 13),
102*61046927SAndroid Build Coastguard Worker                (False, 20),
103*61046927SAndroid Build Coastguard Worker            ],
104*61046927SAndroid Build Coastguard Worker        )
105*61046927SAndroid Build Coastguard Worker        def test(self, is_zero: bool, expected: int) -> None:
106*61046927SAndroid Build Coastguard Worker            date = gen_calendar_entries._calculate_next_release_date(is_zero)
107*61046927SAndroid Build Coastguard Worker            assert date.day == expected
108*61046927SAndroid Build Coastguard Worker
109*61046927SAndroid Build Coastguard Worker    class TestBeforeWeds:
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker        @pytest.fixture(scope='class', autouse=True)
112*61046927SAndroid Build Coastguard Worker        def data(self) -> None:
113*61046927SAndroid Build Coastguard Worker            date = datetime.date(2021, 1, 5)
114*61046927SAndroid Build Coastguard Worker            with TestNextReleaseDate._patch_date(date):
115*61046927SAndroid Build Coastguard Worker                yield
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Worker        @pytest.mark.parametrize(
118*61046927SAndroid Build Coastguard Worker            'is_zero, expected',
119*61046927SAndroid Build Coastguard Worker            [
120*61046927SAndroid Build Coastguard Worker                (True, 13),
121*61046927SAndroid Build Coastguard Worker                (False, 20),
122*61046927SAndroid Build Coastguard Worker            ],
123*61046927SAndroid Build Coastguard Worker        )
124*61046927SAndroid Build Coastguard Worker        def test(self, is_zero: bool, expected: int) -> None:
125*61046927SAndroid Build Coastguard Worker            date = gen_calendar_entries._calculate_next_release_date(is_zero)
126*61046927SAndroid Build Coastguard Worker            assert date.day == expected
127*61046927SAndroid Build Coastguard Worker
128*61046927SAndroid Build Coastguard Worker    class TestAfterWeds:
129*61046927SAndroid Build Coastguard Worker
130*61046927SAndroid Build Coastguard Worker        @pytest.fixture(scope='class', autouse=True)
131*61046927SAndroid Build Coastguard Worker        def data(self) -> None:
132*61046927SAndroid Build Coastguard Worker            date = datetime.date(2021, 1, 8)
133*61046927SAndroid Build Coastguard Worker            with TestNextReleaseDate._patch_date(date):
134*61046927SAndroid Build Coastguard Worker                yield
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker        @pytest.mark.parametrize(
137*61046927SAndroid Build Coastguard Worker            'is_zero, expected',
138*61046927SAndroid Build Coastguard Worker            [
139*61046927SAndroid Build Coastguard Worker                (True, 13),
140*61046927SAndroid Build Coastguard Worker                (False, 20),
141*61046927SAndroid Build Coastguard Worker            ],
142*61046927SAndroid Build Coastguard Worker        )
143*61046927SAndroid Build Coastguard Worker        def test(self, is_zero: bool, expected: int) -> None:
144*61046927SAndroid Build Coastguard Worker            date = gen_calendar_entries._calculate_next_release_date(is_zero)
145*61046927SAndroid Build Coastguard Worker            assert date.day == expected
146*61046927SAndroid Build Coastguard Worker
147*61046927SAndroid Build Coastguard Worker
148*61046927SAndroid Build Coastguard Workerclass TestRC:
149*61046927SAndroid Build Coastguard Worker
150*61046927SAndroid Build Coastguard Worker    ORIGINAL_DATA = [
151*61046927SAndroid Build Coastguard Worker        ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
152*61046927SAndroid Build Coastguard Worker        ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'Last planned release of the 20.3.x series'),
153*61046927SAndroid Build Coastguard Worker    ]
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker    @pytest.fixture(autouse=True, scope='class')
156*61046927SAndroid Build Coastguard Worker    def mock_version(self) -> None:
157*61046927SAndroid Build Coastguard Worker        """Keep the version set at a specific value."""
158*61046927SAndroid Build Coastguard Worker        with tempfile.TemporaryDirectory() as d:
159*61046927SAndroid Build Coastguard Worker            v = os.path.join(d, 'version')
160*61046927SAndroid Build Coastguard Worker            with open(v, 'w') as f:
161*61046927SAndroid Build Coastguard Worker                f.write('21.0.0-devel\n')
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker            with mock.patch('bin.gen_calendar_entries.VERSION', pathlib.Path(v)):
164*61046927SAndroid Build Coastguard Worker                yield
165*61046927SAndroid Build Coastguard Worker
166*61046927SAndroid Build Coastguard Worker    @pytest.fixture(autouse=True)
167*61046927SAndroid Build Coastguard Worker    def csv(self) -> None:
168*61046927SAndroid Build Coastguard Worker        """inject our test data.."""
169*61046927SAndroid Build Coastguard Worker        with mock_csv(self.ORIGINAL_DATA):
170*61046927SAndroid Build Coastguard Worker            yield
171*61046927SAndroid Build Coastguard Worker
172*61046927SAndroid Build Coastguard Worker    def test_basic(self) -> None:
173*61046927SAndroid Build Coastguard Worker        args: gen_calendar_entries.RCArguments = argparse.Namespace()
174*61046927SAndroid Build Coastguard Worker        args.manager = "Dylan Baker"
175*61046927SAndroid Build Coastguard Worker        gen_calendar_entries.release_candidate(args)
176*61046927SAndroid Build Coastguard Worker
177*61046927SAndroid Build Coastguard Worker        expected = self.ORIGINAL_DATA.copy()
178*61046927SAndroid Build Coastguard Worker        expected.append(('21.0', '2021-01-13', f'21.0.0-rc1', 'Dylan Baker'))
179*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-01-20', f'21.0.0-rc2', 'Dylan Baker'))
180*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-01-27', f'21.0.0-rc3', 'Dylan Baker'))
181*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-02-03', f'21.0.0-rc4', 'Dylan Baker', 'Or 21.0.0 final.'))
182*61046927SAndroid Build Coastguard Worker
183*61046927SAndroid Build Coastguard Worker        actual = gen_calendar_entries.read_calendar()
184*61046927SAndroid Build Coastguard Worker
185*61046927SAndroid Build Coastguard Worker        assert actual == expected
186*61046927SAndroid Build Coastguard Worker
187*61046927SAndroid Build Coastguard Worker
188*61046927SAndroid Build Coastguard Workerclass TestExtend:
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker    def test_one_release(self) -> None:
191*61046927SAndroid Build Coastguard Worker        data = [
192*61046927SAndroid Build Coastguard Worker            ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
193*61046927SAndroid Build Coastguard Worker            ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
194*61046927SAndroid Build Coastguard Worker        ]
195*61046927SAndroid Build Coastguard Worker
196*61046927SAndroid Build Coastguard Worker        args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
197*61046927SAndroid Build Coastguard Worker        args.series = '20.3'
198*61046927SAndroid Build Coastguard Worker        args.count = 2
199*61046927SAndroid Build Coastguard Worker
200*61046927SAndroid Build Coastguard Worker        with mock_csv(data):
201*61046927SAndroid Build Coastguard Worker            gen_calendar_entries.extend(args)
202*61046927SAndroid Build Coastguard Worker            actual = gen_calendar_entries.read_calendar()
203*61046927SAndroid Build Coastguard Worker
204*61046927SAndroid Build Coastguard Worker        expected = [
205*61046927SAndroid Build Coastguard Worker            data[0],
206*61046927SAndroid Build Coastguard Worker            ('', '2021-01-27', '20.3.4', 'Dylan Baker', ''),
207*61046927SAndroid Build Coastguard Worker            ('', '2021-02-10', '20.3.5', 'Dylan Baker', ''),
208*61046927SAndroid Build Coastguard Worker            ('', '2021-02-24', '20.3.6', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
209*61046927SAndroid Build Coastguard Worker        ]
210*61046927SAndroid Build Coastguard Worker
211*61046927SAndroid Build Coastguard Worker        assert actual == expected
212*61046927SAndroid Build Coastguard Worker    def test_one_release(self) -> None:
213*61046927SAndroid Build Coastguard Worker        data = [
214*61046927SAndroid Build Coastguard Worker            ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
215*61046927SAndroid Build Coastguard Worker            ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
216*61046927SAndroid Build Coastguard Worker            ('21.0', '2021-01-13', '21.0.1', 'Dylan Baker', ''),
217*61046927SAndroid Build Coastguard Worker            ('',     '2021-01-27', '21.0.2', 'Dylan Baker', ''),
218*61046927SAndroid Build Coastguard Worker            ('',     '2021-02-10', '21.0.3', 'Dylan Baker', ''),
219*61046927SAndroid Build Coastguard Worker            ('',     '2021-02-24', '21.0.4', 'Dylan Baker', 'This is the last planned release of the 21.0.x series.'),
220*61046927SAndroid Build Coastguard Worker        ]
221*61046927SAndroid Build Coastguard Worker
222*61046927SAndroid Build Coastguard Worker        args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
223*61046927SAndroid Build Coastguard Worker        args.series = '21.0'
224*61046927SAndroid Build Coastguard Worker        args.count = 1
225*61046927SAndroid Build Coastguard Worker
226*61046927SAndroid Build Coastguard Worker        with mock_csv(data):
227*61046927SAndroid Build Coastguard Worker            gen_calendar_entries.extend(args)
228*61046927SAndroid Build Coastguard Worker            actual = gen_calendar_entries.read_calendar()
229*61046927SAndroid Build Coastguard Worker
230*61046927SAndroid Build Coastguard Worker        expected = data.copy()
231*61046927SAndroid Build Coastguard Worker        d = list(data[-1])
232*61046927SAndroid Build Coastguard Worker        d[-1] = ''
233*61046927SAndroid Build Coastguard Worker        expected[-1] = tuple(d)
234*61046927SAndroid Build Coastguard Worker        expected.extend([
235*61046927SAndroid Build Coastguard Worker            ('',     '2021-03-10', '21.0.5', 'Dylan Baker', 'This is the last planned release of the 21.0.x series.'),
236*61046927SAndroid Build Coastguard Worker        ])
237*61046927SAndroid Build Coastguard Worker
238*61046927SAndroid Build Coastguard Worker        assert actual == expected
239*61046927SAndroid Build Coastguard Worker
240*61046927SAndroid Build Coastguard Worker    def test_rc(self) -> None:
241*61046927SAndroid Build Coastguard Worker        data = [
242*61046927SAndroid Build Coastguard Worker            ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
243*61046927SAndroid Build Coastguard Worker            ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
244*61046927SAndroid Build Coastguard Worker            ('21.0', '2021-01-13', '21.0.0-rc1', 'Dylan Baker', ''),
245*61046927SAndroid Build Coastguard Worker            ('',     '2021-01-20', '21.0.0-rc2', 'Dylan Baker', gen_calendar_entries.OR_FINAL.format('21.0')),
246*61046927SAndroid Build Coastguard Worker        ]
247*61046927SAndroid Build Coastguard Worker
248*61046927SAndroid Build Coastguard Worker        args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
249*61046927SAndroid Build Coastguard Worker        args.series = '21.0'
250*61046927SAndroid Build Coastguard Worker        args.count = 2
251*61046927SAndroid Build Coastguard Worker
252*61046927SAndroid Build Coastguard Worker        with mock_csv(data):
253*61046927SAndroid Build Coastguard Worker            gen_calendar_entries.extend(args)
254*61046927SAndroid Build Coastguard Worker            actual = gen_calendar_entries.read_calendar()
255*61046927SAndroid Build Coastguard Worker
256*61046927SAndroid Build Coastguard Worker        expected = data.copy()
257*61046927SAndroid Build Coastguard Worker        d = list(expected[-1])
258*61046927SAndroid Build Coastguard Worker        d[-1] = ''
259*61046927SAndroid Build Coastguard Worker        expected[-1] = tuple(d)
260*61046927SAndroid Build Coastguard Worker        expected.extend([
261*61046927SAndroid Build Coastguard Worker            ('', '2021-01-27', '21.0.0-rc3', 'Dylan Baker', ''),
262*61046927SAndroid Build Coastguard Worker            ('', '2021-02-03', '21.0.0-rc4', 'Dylan Baker', gen_calendar_entries.OR_FINAL.format('21.0')),
263*61046927SAndroid Build Coastguard Worker        ])
264*61046927SAndroid Build Coastguard Worker
265*61046927SAndroid Build Coastguard Worker        assert actual == expected
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker
268*61046927SAndroid Build Coastguard Workerclass TestFinal:
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker    @pytest.fixture(autouse=True, scope='class')
271*61046927SAndroid Build Coastguard Worker    def _patch_date(self) -> typing.Iterator[None]:
272*61046927SAndroid Build Coastguard Worker        mdate = mock.Mock()
273*61046927SAndroid Build Coastguard Worker        mdate.today = mock.Mock(return_value=datetime.date(2021, 1, 6))
274*61046927SAndroid Build Coastguard Worker        with mock.patch('bin.gen_calendar_entries.datetime.date', mdate):
275*61046927SAndroid Build Coastguard Worker            yield
276*61046927SAndroid Build Coastguard Worker
277*61046927SAndroid Build Coastguard Worker    ORIGINAL_DATA = [
278*61046927SAndroid Build Coastguard Worker        ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
279*61046927SAndroid Build Coastguard Worker        ('',     '2021-01-27', '20.3.4', 'Dylan Baker', 'Last planned release of the 20.3.x series'),
280*61046927SAndroid Build Coastguard Worker    ]
281*61046927SAndroid Build Coastguard Worker
282*61046927SAndroid Build Coastguard Worker    @pytest.fixture(autouse=True)
283*61046927SAndroid Build Coastguard Worker    def csv(self) -> None:
284*61046927SAndroid Build Coastguard Worker        """inject our test data.."""
285*61046927SAndroid Build Coastguard Worker        with mock_csv(self.ORIGINAL_DATA):
286*61046927SAndroid Build Coastguard Worker            yield
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker    def test_zero_released(self) -> None:
289*61046927SAndroid Build Coastguard Worker        args: gen_calendar_entries.FinalArguments = argparse.Namespace()
290*61046927SAndroid Build Coastguard Worker        args.manager = "Dylan Baker"
291*61046927SAndroid Build Coastguard Worker        args.zero_released = True
292*61046927SAndroid Build Coastguard Worker        args.series = '21.0'
293*61046927SAndroid Build Coastguard Worker        gen_calendar_entries.final_release(args)
294*61046927SAndroid Build Coastguard Worker
295*61046927SAndroid Build Coastguard Worker        expected = self.ORIGINAL_DATA.copy()
296*61046927SAndroid Build Coastguard Worker        expected.append(('21.0', '2021-01-20', f'21.0.1', 'Dylan Baker'))
297*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-02-03', f'21.0.2', 'Dylan Baker'))
298*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-02-17', f'21.0.3', 'Dylan Baker', gen_calendar_entries.LAST_RELEASE.format(args.series)))
299*61046927SAndroid Build Coastguard Worker
300*61046927SAndroid Build Coastguard Worker        actual = gen_calendar_entries.read_calendar()
301*61046927SAndroid Build Coastguard Worker
302*61046927SAndroid Build Coastguard Worker        assert actual == expected
303*61046927SAndroid Build Coastguard Worker
304*61046927SAndroid Build Coastguard Worker    def test_zero_not_released(self) -> None:
305*61046927SAndroid Build Coastguard Worker        args: gen_calendar_entries.FinalArguments = argparse.Namespace()
306*61046927SAndroid Build Coastguard Worker        args.manager = "Dylan Baker"
307*61046927SAndroid Build Coastguard Worker        args.zero_released = False
308*61046927SAndroid Build Coastguard Worker        args.series = '21.0'
309*61046927SAndroid Build Coastguard Worker        gen_calendar_entries.final_release(args)
310*61046927SAndroid Build Coastguard Worker
311*61046927SAndroid Build Coastguard Worker        expected = self.ORIGINAL_DATA.copy()
312*61046927SAndroid Build Coastguard Worker        expected.append(('21.0', '2021-01-13', f'21.0.0', 'Dylan Baker'))
313*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-01-27', f'21.0.1', 'Dylan Baker'))
314*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-02-10', f'21.0.2', 'Dylan Baker'))
315*61046927SAndroid Build Coastguard Worker        expected.append((    '', '2021-02-24', f'21.0.3', 'Dylan Baker', gen_calendar_entries.LAST_RELEASE.format(args.series)))
316*61046927SAndroid Build Coastguard Worker
317*61046927SAndroid Build Coastguard Worker        actual = gen_calendar_entries.read_calendar()
318*61046927SAndroid Build Coastguard Worker
319*61046927SAndroid Build Coastguard Worker        assert actual == expected
320