3 # Allow direct execution
8 sys
.path
.insert(0, os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
))))
11 from test
.helper
import FakeYDL
, report_warning
12 from yt_dlp
.update
import UpdateInfo
, Updater
15 # XXX: Keep in sync with yt_dlp.update.UPDATE_SOURCES
16 TEST_UPDATE_SOURCES
= {
17 'stable': 'yt-dlp/yt-dlp',
18 'nightly': 'yt-dlp/yt-dlp-nightly-builds',
19 'master': 'yt-dlp/yt-dlp-master-builds',
23 'yt-dlp/yt-dlp/latest': {
24 'tag_name': '2023.12.31',
25 'target_commitish': 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
26 'name': 'yt-dlp 2023.12.31',
29 'yt-dlp/yt-dlp-nightly-builds/latest': {
30 'tag_name': '2023.12.31.123456',
31 'target_commitish': 'master',
32 'name': 'yt-dlp nightly 2023.12.31.123456',
33 'body': 'Generated from: https://github.com/yt-dlp/yt-dlp/commit/cccccccccccccccccccccccccccccccccccccccc',
35 'yt-dlp/yt-dlp-master-builds/latest': {
36 'tag_name': '2023.12.31.987654',
37 'target_commitish': 'master',
38 'name': 'yt-dlp master 2023.12.31.987654',
39 'body': 'Generated from: https://github.com/yt-dlp/yt-dlp/commit/dddddddddddddddddddddddddddddddddddddddd',
41 'yt-dlp/yt-dlp/tags/testing': {
42 'tag_name': 'testing',
43 'target_commitish': '9999999999999999999999999999999999999999',
47 'fork/yt-dlp/latest': {
48 'tag_name': '2050.12.31',
49 'target_commitish': 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
53 'fork/yt-dlp/tags/pr0000': {
55 'target_commitish': 'ffffffffffffffffffffffffffffffffffffffff',
56 'name': 'pr1234 2023.11.11.000000',
59 'fork/yt-dlp/tags/pr1234': {
61 'target_commitish': '0000000000000000000000000000000000000000',
62 'name': 'pr1234 2023.12.31.555555',
65 'fork/yt-dlp/tags/pr9999': {
67 'target_commitish': '1111111111111111111111111111111111111111',
71 'fork/yt-dlp-satellite/tags/pr987': {
73 'target_commitish': 'master',
75 'body': 'Generated from: https://github.com/yt-dlp/yt-dlp/commit/2222222222222222222222222222222222222222',
79 TEST_LOCKFILE_COMMENT
= '# This file is used for regulating self-update'
81 TEST_LOCKFILE_V1
= rf
'''{TEST_LOCKFILE_COMMENT}
82 lock 2022.08.18.36 .+ Python 3\.6
83 lock 2023.11.16 (?!win_x86_exe).+ Python 3\.7
84 lock 2023.11.16 win_x86_exe .+ Windows-(?:Vista|2008Server)
85 lock 2024.10.22 py2exe .+
86 lock 2024.10.22 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b
87 lock 2024.10.22 (?!\w+_exe).+ Python 3\.8
88 lock 2024.10.22 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2)
91 TEST_LOCKFILE_V2_TMPL
= r
'''%s
92 lockV2 yt-dlp/yt-dlp 2022.08.18.36 .+ Python 3\.6
93 lockV2 yt-dlp/yt-dlp 2023.11.16 (?!win_x86_exe).+ Python 3\.7
94 lockV2 yt-dlp/yt-dlp 2023.11.16 win_x86_exe .+ Windows-(?:Vista|2008Server)
95 lockV2 yt-dlp/yt-dlp 2024.10.22 py2exe .+
96 lockV2 yt-dlp/yt-dlp 2024.10.22 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b
97 lockV2 yt-dlp/yt-dlp 2024.10.22 (?!\w+_exe).+ Python 3\.8
98 lockV2 yt-dlp/yt-dlp 2024.10.22 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2)
99 lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 (?!win_x86_exe).+ Python 3\.7
100 lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 win_x86_exe .+ Windows-(?:Vista|2008Server)
101 lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 py2exe .+
102 lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b
103 lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 (?!\w+_exe).+ Python 3\.8
104 lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2)
105 lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 (?!win_x86_exe).+ Python 3\.7
106 lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 win_x86_exe .+ Windows-(?:Vista|2008Server)
107 lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.045052 py2exe .+
108 lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.060347 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b
109 lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.060347 (?!\w+_exe).+ Python 3\.8
110 lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.060347 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2)
113 TEST_LOCKFILE_V2
= TEST_LOCKFILE_V2_TMPL
% TEST_LOCKFILE_COMMENT
115 TEST_LOCKFILE_ACTUAL
= TEST_LOCKFILE_V2_TMPL
% TEST_LOCKFILE_V1
.rstrip('\n')
117 TEST_LOCKFILE_FORK
= rf
'''{TEST_LOCKFILE_ACTUAL}# Test if a fork blocks updates to non-numeric tags
118 lockV2 fork/yt-dlp pr0000 .+ Python 3.6
119 lockV2 fork/yt-dlp pr1234 (?!win_x86_exe).+ Python 3\.7
120 lockV2 fork/yt-dlp pr1234 win_x86_exe .+ Windows-(?:Vista|2008Server)
121 lockV2 fork/yt-dlp pr9999 .+ Python 3.11
125 class FakeUpdater(Updater
):
126 current_version
= '2022.01.01'
127 current_commit
= 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
130 _origin
= 'yt-dlp/yt-dlp'
131 _update_sources
= TEST_UPDATE_SOURCES
133 def _download_update_spec(self
, *args
, **kwargs
):
134 return TEST_LOCKFILE_ACTUAL
136 def _call_api(self
, tag
):
137 tag
= f
'tags/{tag}' if tag
!= 'latest' else tag
138 return TEST_API_DATA
[f
'{self.requested_repo}/{tag}']
140 def _report_error(self
, msg
, *args
, **kwargs
):
144 class TestUpdate(unittest
.TestCase
):
147 def test_update_spec(self
):
149 updater
= FakeUpdater(ydl
, 'stable')
151 def test(lockfile
, identifier
, input_tag
, expect_tag
, exact
=False, repo
='yt-dlp/yt-dlp'):
152 updater
._identifier
= identifier
153 updater
._exact
= exact
154 updater
.requested_repo
= repo
155 result
= updater
._process
_update
_spec
(lockfile
, input_tag
)
158 f
'{identifier!r} requesting {repo}@{input_tag} (exact={exact}) '
159 f
'returned {result!r} instead of {expect_tag!r}')
161 for lockfile
in (TEST_LOCKFILE_V1
, TEST_LOCKFILE_V2
, TEST_LOCKFILE_ACTUAL
, TEST_LOCKFILE_FORK
):
163 test(lockfile
, 'zip Python 3.12.0', '2023.12.31', '2023.12.31')
164 test(lockfile
, 'zip Python 3.12.0', '2023.12.31', '2023.12.31', exact
=True)
165 # py2exe should never update beyond 2024.10.22
166 test(lockfile
, 'py2exe Python 3.8', '2025.01.01', '2024.10.22')
167 test(lockfile
, 'py2exe Python 3.8', '2025.01.01', None, exact
=True)
168 # Python 3.6 --update should update only to the py3.6 lock
169 test(lockfile
, 'zip Python 3.6.0', '2023.11.16', '2022.08.18.36')
170 # Python 3.6 --update-to an exact version later than the py3.6 lock should return None
171 test(lockfile
, 'zip Python 3.6.0', '2023.11.16', None, exact
=True)
172 # Python 3.7 should be able to update to the py3.7 lock
173 test(lockfile
, 'zip Python 3.7.0', '2023.11.16', '2023.11.16')
174 test(lockfile
, 'zip Python 3.7.1', '2023.11.16', '2023.11.16', exact
=True)
175 # Non-win_x86_exe builds on py3.7 must be locked at py3.7 lock
176 test(lockfile
, 'zip Python 3.7.1', '2023.12.31', '2023.11.16')
177 test(lockfile
, 'zip Python 3.7.1', '2023.12.31', None, exact
=True)
178 # Python 3.8 should only update to the py3.8 lock
179 test(lockfile
, 'zip Python 3.8.10', '2025.01.01', '2024.10.22')
180 test(lockfile
, 'zip Python 3.8.110', '2025.01.01', None, exact
=True)
181 test( # Windows Vista w/ win_x86_exe must be locked at Vista lock
182 lockfile
, 'win_x86_exe Python 3.7.9 (CPython x86 32bit) - Windows-Vista-6.0.6003-SP2',
183 '2023.12.31', '2023.11.16')
184 test( # Windows 2008Server w/ win_x86_exe must be locked at Vista lock
185 lockfile
, 'win_x86_exe Python 3.7.9 (CPython x86 32bit) - Windows-2008Server',
186 '2023.12.31', None, exact
=True)
187 test( # Windows 7 w/ win_x86_exe py3.7 build should be able to update beyond py3.7 lock
188 lockfile
, 'win_x86_exe Python 3.7.9 (CPython x86 32bit) - Windows-7-6.1.7601-SP1',
189 '2023.12.31', '2023.12.31', exact
=True)
190 test( # Windows 7 win_x86_exe should only update to Win7 lock
191 lockfile
, 'win_x86_exe Python 3.7.9 (CPython x86 32bit) - Windows-7-6.1.7601-SP1',
192 '2025.01.01', '2024.10.22')
193 test( # Windows 2008ServerR2 win_exe should only update to Win7 lock
194 lockfile
, 'win_exe Python 3.8.10 (CPython x86 32bit) - Windows-2008ServerR2',
195 '2025.12.31', '2024.10.22')
196 test( # Windows 8.1 w/ '2008Server' in platform string should be able to update beyond py3.7 lock
197 lockfile
, 'win_x86_exe Python 3.7.9 (CPython x86 32bit) - Windows-post2008Server-6.2.9200',
198 '2023.12.31', '2023.12.31', exact
=True)
199 test( # win_exe built w/Python 3.8 on Windows>=8 should be able to update beyond py3.8 lock
200 lockfile
, 'win_exe Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0',
201 '2025.01.01', '2025.01.01', exact
=True)
202 test( # linux_armv7l_exe w/glibc2.7 should only update to glibc<2.31 lock
203 lockfile
, 'linux_armv7l_exe Python 3.8.0 (CPython armv7l 32bit) - Linux-6.5.0-1025-azure-armv7l-with-glibc2.7',
204 '2025.01.01', '2024.10.22')
205 test( # linux_armv7l_exe w/Python 3.8 and glibc>=2.31 should be able to update beyond py3.8 and glibc<2.31 locks
206 lockfile
, 'linux_armv7l_exe Python 3.8.0 (CPython armv7l 32bit) - Linux-6.5.0-1025-azure-armv7l-with-glibc2.31',
207 '2025.01.01', '2025.01.01')
208 test( # linux_armv7l_exe w/glibc2.30 should only update to glibc<2.31 lock
209 lockfile
, 'linux_armv7l_exe Python 3.8.0 (CPython armv7l 64bit) - Linux-6.5.0-1025-azure-aarch64-with-glibc2.30 (OpenSSL',
210 '2025.01.01', '2024.10.22')
211 test( # linux_aarch64_exe w/glibc2.17 should only update to glibc<2.31 lock
212 lockfile
, 'linux_aarch64_exe Python 3.8.0 (CPython aarch64 64bit) - Linux-6.5.0-1025-azure-aarch64-with-glibc2.17',
213 '2025.01.01', '2024.10.22')
214 test( # linux_aarch64_exe w/glibc2.40 and glibc>=2.31 should be able to update beyond py3.8 and glibc<2.31 locks
215 lockfile
, 'linux_aarch64_exe Python 3.8.0 (CPython aarch64 64bit) - Linux-6.5.0-1025-azure-aarch64-with-glibc2.40',
216 '2025.01.01', '2025.01.01')
217 test( # linux_aarch64_exe w/glibc2.3 should only update to glibc<2.31 lock
218 lockfile
, 'linux_aarch64_exe Python 3.8.0 (CPython aarch64 64bit) - Linux-6.5.0-1025-azure-aarch64-with-glibc2.3 (OpenSSL',
219 '2025.01.01', '2024.10.22')
221 # Forks can block updates to non-numeric tags rather than lock
222 test(TEST_LOCKFILE_FORK
, 'zip Python 3.6.3', 'pr0000', None, repo
='fork/yt-dlp')
223 test(TEST_LOCKFILE_FORK
, 'zip Python 3.7.4', 'pr0000', 'pr0000', repo
='fork/yt-dlp')
224 test(TEST_LOCKFILE_FORK
, 'zip Python 3.7.4', 'pr1234', None, repo
='fork/yt-dlp')
225 test(TEST_LOCKFILE_FORK
, 'zip Python 3.8.1', 'pr1234', 'pr1234', repo
='fork/yt-dlp', exact
=True)
227 TEST_LOCKFILE_FORK
, 'win_x86_exe Python 3.7.9 (CPython x86 32bit) - Windows-Vista-6.0.6003-SP2',
228 'pr1234', None, repo
='fork/yt-dlp')
230 TEST_LOCKFILE_FORK
, 'win_x86_exe Python 3.7.9 (CPython x86 32bit) - Windows-7-6.1.7601-SP1',
231 '2023.12.31', '2023.12.31', repo
='fork/yt-dlp')
232 test(TEST_LOCKFILE_FORK
, 'zip Python 3.11.2', 'pr9999', None, repo
='fork/yt-dlp', exact
=True)
233 test(TEST_LOCKFILE_FORK
, 'zip Python 3.12.0', 'pr9999', 'pr9999', repo
='fork/yt-dlp')
235 def test_query_update(self
):
238 def test(target
, expected
, current_version
=None, current_commit
=None, identifier
=None):
239 updater
= FakeUpdater(ydl
, target
)
241 updater
.current_version
= current_version
243 updater
.current_commit
= current_commit
244 updater
._identifier
= identifier
or 'zip'
245 update_info
= updater
.query_update(_output
=True)
246 self
.assertDictEqual(
247 update_info
.__dict
__ if update_info
else {}, expected
.__dict
__ if expected
else {})
249 test('yt-dlp/yt-dlp@latest', UpdateInfo(
250 '2023.12.31', version
='2023.12.31', requested_version
='2023.12.31', commit
='b' * 40))
251 test('yt-dlp/yt-dlp-nightly-builds@latest', UpdateInfo(
252 '2023.12.31.123456', version
='2023.12.31.123456', requested_version
='2023.12.31.123456', commit
='c' * 40))
253 test('yt-dlp/yt-dlp-master-builds@latest', UpdateInfo(
254 '2023.12.31.987654', version
='2023.12.31.987654', requested_version
='2023.12.31.987654', commit
='d' * 40))
255 test('fork/yt-dlp@latest', UpdateInfo(
256 '2050.12.31', version
='2050.12.31', requested_version
='2050.12.31', commit
='e' * 40))
257 test('fork/yt-dlp@pr0000', UpdateInfo(
258 'pr0000', version
='2023.11.11.000000', requested_version
='2023.11.11.000000', commit
='f' * 40))
259 test('fork/yt-dlp@pr1234', UpdateInfo(
260 'pr1234', version
='2023.12.31.555555', requested_version
='2023.12.31.555555', commit
='0' * 40))
261 test('fork/yt-dlp@pr9999', UpdateInfo(
262 'pr9999', version
=None, requested_version
=None, commit
='1' * 40))
263 test('fork/yt-dlp-satellite@pr987', UpdateInfo(
264 'pr987', version
=None, requested_version
=None, commit
='2' * 40))
265 test('yt-dlp/yt-dlp', None, current_version
='2024.01.01')
266 test('stable', UpdateInfo(
267 '2023.12.31', version
='2023.12.31', requested_version
='2023.12.31', commit
='b' * 40))
268 test('nightly', UpdateInfo(
269 '2023.12.31.123456', version
='2023.12.31.123456', requested_version
='2023.12.31.123456', commit
='c' * 40))
270 test('master', UpdateInfo(
271 '2023.12.31.987654', version
='2023.12.31.987654', requested_version
='2023.12.31.987654', commit
='d' * 40))
272 test('testing', None, current_commit
='9' * 40)
273 test('testing', UpdateInfo('testing', commit
='9' * 40))
276 if __name__
== '__main__':