]> jfr.im git - yt-dlp.git/blame - test/test_download.py
implement fallbacks and defaults in _search_regex
[yt-dlp.git] / test / test_download.py
CommitLineData
fd5ff020
FV
1#!/usr/bin/env python
2
5c892b0b 3import errno
efe8902f 4import hashlib
fd5ff020 5import io
efe8902f 6import os
7f60b5aa 7import json
cdab8aa3
PH
8import unittest
9import sys
0eaf520d 10import hashlib
6b3aef80 11import socket
fd5ff020
FV
12
13# Allow direct execution
14sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
cdab8aa3 15
fd5ff020
FV
16import youtube_dl.FileDownloader
17import youtube_dl.InfoExtractors
18from youtube_dl.utils import *
1535ac2a 19
20DEF_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tests.json')
fd5ff020
FV
21PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "parameters.json")
22
8cc83b8d
FV
23RETRIES = 3
24
fd5ff020
FV
25# General configuration (from __init__, not very elegant...)
26jar = compat_cookiejar.CookieJar()
27cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
28proxy_handler = compat_urllib_request.ProxyHandler()
29opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
30compat_urllib_request.install_opener(opener)
d8bbf201 31socket.setdefaulttimeout(10)
fd5ff020 32
5c892b0b
PH
33def _try_rm(filename):
34 """ Remove a file if it exists """
35 try:
36 os.remove(filename)
37 except OSError as ose:
38 if ose.errno != errno.ENOENT:
39 raise
40
fd5ff020
FV
41class FileDownloader(youtube_dl.FileDownloader):
42 def __init__(self, *args, **kwargs):
fd5ff020 43 self.to_stderr = self.to_screen
0eaf520d
FV
44 self.processed_info_dicts = []
45 return youtube_dl.FileDownloader.__init__(self, *args, **kwargs)
46 def process_info(self, info_dict):
47 self.processed_info_dicts.append(info_dict)
48 return youtube_dl.FileDownloader.process_info(self, info_dict)
1535ac2a 49
fd5ff020
FV
50def _file_md5(fn):
51 with open(fn, 'rb') as f:
52 return hashlib.md5(f.read()).hexdigest()
53
54with io.open(DEF_FILE, encoding='utf-8') as deff:
55 defs = json.load(deff)
56with io.open(PARAMETERS_FILE, encoding='utf-8') as pf:
57 parameters = json.load(pf)
1535ac2a 58
0eaf520d 59
1535ac2a 60class TestDownload(unittest.TestCase):
744435f2 61 maxDiff = None
fd5ff020
FV
62 def setUp(self):
63 self.parameters = parameters
64 self.defs = defs
65
911ee27e 66### Dynamically generate tests
5d01a647
PH
67def generator(test_case):
68
1535ac2a 69 def test_template(self):
ba7c775a 70 ie = youtube_dl.InfoExtractors.get_info_extractor(test_case['name'])
fd5ff020
FV
71 if not ie._WORKING:
72 print('Skipping: IE marked as not _WORKING')
73 return
5c892b0b 74 if 'playlist' not in test_case and not test_case['file']:
6985325e
PH
75 print('Skipping: No output file specified')
76 return
fd5ff020
FV
77 if 'skip' in test_case:
78 print('Skipping: {0}'.format(test_case['skip']))
79 return
0eaf520d 80
c073e35b
PH
81 params = self.parameters.copy()
82 params.update(test_case.get('params', {}))
0eaf520d 83
fd5ff020 84 fd = FileDownloader(params)
f375d4b7
FV
85 for ie in youtube_dl.InfoExtractors.gen_extractors():
86 fd.add_info_extractor(ie)
bffbd5f0
PH
87 finished_hook_called = set()
88 def _hook(status):
89 if status['status'] == 'finished':
90 finished_hook_called.add(status['filename'])
91 fd.add_progress_hook(_hook)
5c892b0b
PH
92
93 test_cases = test_case.get('playlist', [test_case])
94 for tc in test_cases:
95 _try_rm(tc['file'])
3a648b20 96 _try_rm(tc['file'] + '.part')
5c892b0b
PH
97 _try_rm(tc['file'] + '.info.json')
98 try:
8cc83b8d
FV
99 for retry in range(1, RETRIES + 1):
100 try:
101 fd.download([test_case['url']])
102 except (DownloadError, ExtractorError) as err:
103 if retry == RETRIES: raise
104
105 # Check if the exception is not a network related one
90a99c1b 106 if not err.exc_info[0] in (compat_urllib_error.URLError, socket.timeout, UnavailableVideoError):
8cc83b8d
FV
107 raise
108
109 print('Retrying: {0} failed tries\n\n##########\n\n'.format(retry))
110 else:
111 break
5c892b0b
PH
112
113 for tc in test_cases:
511eda8e 114 if not test_case.get('params', {}).get('skip_download', False):
233a2296 115 self.assertTrue(os.path.exists(tc['file']), msg='Missing file ' + tc['file'])
bffbd5f0 116 self.assertTrue(tc['file'] in finished_hook_called)
5c892b0b
PH
117 self.assertTrue(os.path.exists(tc['file'] + '.info.json'))
118 if 'md5' in tc:
119 md5_for_file = _file_md5(tc['file'])
120 self.assertEqual(md5_for_file, tc['md5'])
121 with io.open(tc['file'] + '.info.json', encoding='utf-8') as infof:
122 info_dict = json.load(infof)
123 for (info_field, value) in tc.get('info_dict', {}).items():
30e9f449 124 self.assertEqual(value, info_dict.get(info_field))
5c892b0b
PH
125 finally:
126 for tc in test_cases:
127 _try_rm(tc['file'])
3a648b20 128 _try_rm(tc['file'] + '.part')
5c892b0b 129 _try_rm(tc['file'] + '.info.json')
fd5ff020 130
1535ac2a 131 return test_template
fd5ff020 132
5d01a647 133### And add them to TestDownload
fd5ff020 134for test_case in defs:
5d01a647 135 test_method = generator(test_case)
fd5ff020
FV
136 test_method.__name__ = "test_{0}".format(test_case["name"])
137 setattr(TestDownload, test_method.__name__, test_method)
5d01a647 138 del test_method
cdab8aa3
PH
139
140
141if __name__ == '__main__':
142 unittest.main()