]> jfr.im git - yt-dlp.git/blame - test/test_download.py
Option to dump intermediate pages
[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):
fd5ff020
FV
61 def setUp(self):
62 self.parameters = parameters
63 self.defs = defs
64
911ee27e 65### Dynamically generate tests
5d01a647
PH
66def generator(test_case):
67
1535ac2a 68 def test_template(self):
fd5ff020
FV
69 ie = getattr(youtube_dl.InfoExtractors, test_case['name'] + 'IE')
70 if not ie._WORKING:
71 print('Skipping: IE marked as not _WORKING')
72 return
5c892b0b 73 if 'playlist' not in test_case and not test_case['file']:
6985325e
PH
74 print('Skipping: No output file specified')
75 return
fd5ff020
FV
76 if 'skip' in test_case:
77 print('Skipping: {0}'.format(test_case['skip']))
78 return
0eaf520d 79
c073e35b
PH
80 params = self.parameters.copy()
81 params.update(test_case.get('params', {}))
0eaf520d 82
fd5ff020 83 fd = FileDownloader(params)
f375d4b7
FV
84 for ie in youtube_dl.InfoExtractors.gen_extractors():
85 fd.add_info_extractor(ie)
bffbd5f0
PH
86 finished_hook_called = set()
87 def _hook(status):
88 if status['status'] == 'finished':
89 finished_hook_called.add(status['filename'])
90 fd.add_progress_hook(_hook)
5c892b0b
PH
91
92 test_cases = test_case.get('playlist', [test_case])
93 for tc in test_cases:
94 _try_rm(tc['file'])
3a648b20 95 _try_rm(tc['file'] + '.part')
5c892b0b
PH
96 _try_rm(tc['file'] + '.info.json')
97 try:
8cc83b8d
FV
98 for retry in range(1, RETRIES + 1):
99 try:
100 fd.download([test_case['url']])
101 except (DownloadError, ExtractorError) as err:
102 if retry == RETRIES: raise
103
104 # Check if the exception is not a network related one
90a99c1b 105 if not err.exc_info[0] in (compat_urllib_error.URLError, socket.timeout, UnavailableVideoError):
8cc83b8d
FV
106 raise
107
108 print('Retrying: {0} failed tries\n\n##########\n\n'.format(retry))
109 else:
110 break
5c892b0b
PH
111
112 for tc in test_cases:
511eda8e 113 if not test_case.get('params', {}).get('skip_download', False):
233a2296 114 self.assertTrue(os.path.exists(tc['file']), msg='Missing file ' + tc['file'])
bffbd5f0 115 self.assertTrue(tc['file'] in finished_hook_called)
5c892b0b
PH
116 self.assertTrue(os.path.exists(tc['file'] + '.info.json'))
117 if 'md5' in tc:
118 md5_for_file = _file_md5(tc['file'])
119 self.assertEqual(md5_for_file, tc['md5'])
120 with io.open(tc['file'] + '.info.json', encoding='utf-8') as infof:
121 info_dict = json.load(infof)
122 for (info_field, value) in tc.get('info_dict', {}).items():
30e9f449 123 self.assertEqual(value, info_dict.get(info_field))
5c892b0b
PH
124 finally:
125 for tc in test_cases:
126 _try_rm(tc['file'])
3a648b20 127 _try_rm(tc['file'] + '.part')
5c892b0b 128 _try_rm(tc['file'] + '.info.json')
fd5ff020 129
1535ac2a 130 return test_template
fd5ff020 131
5d01a647 132### And add them to TestDownload
fd5ff020 133for test_case in defs:
5d01a647 134 test_method = generator(test_case)
fd5ff020
FV
135 test_method.__name__ = "test_{0}".format(test_case["name"])
136 setattr(TestDownload, test_method.__name__, test_method)
5d01a647 137 del test_method
cdab8aa3
PH
138
139
140if __name__ == '__main__':
141 unittest.main()