]>
Commit | Line | Data |
---|---|---|
1 | import errno | |
2 | import io | |
3 | import hashlib | |
4 | import json | |
5 | import os.path | |
6 | import re | |
7 | import types | |
8 | import sys | |
9 | ||
10 | import youtube_dl.extractor | |
11 | from youtube_dl import YoutubeDL | |
12 | from youtube_dl.utils import ( | |
13 | compat_str, | |
14 | preferredencoding, | |
15 | ) | |
16 | ||
17 | ||
18 | def get_params(override=None): | |
19 | PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), | |
20 | "parameters.json") | |
21 | with io.open(PARAMETERS_FILE, encoding='utf-8') as pf: | |
22 | parameters = json.load(pf) | |
23 | if override: | |
24 | parameters.update(override) | |
25 | return parameters | |
26 | ||
27 | ||
28 | def try_rm(filename): | |
29 | """ Remove a file if it exists """ | |
30 | try: | |
31 | os.remove(filename) | |
32 | except OSError as ose: | |
33 | if ose.errno != errno.ENOENT: | |
34 | raise | |
35 | ||
36 | ||
37 | def report_warning(message): | |
38 | ''' | |
39 | Print the message to stderr, it will be prefixed with 'WARNING:' | |
40 | If stderr is a tty file the 'WARNING:' will be colored | |
41 | ''' | |
42 | if sys.stderr.isatty() and os.name != 'nt': | |
43 | _msg_header = u'\033[0;33mWARNING:\033[0m' | |
44 | else: | |
45 | _msg_header = u'WARNING:' | |
46 | output = u'%s %s\n' % (_msg_header, message) | |
47 | if 'b' in getattr(sys.stderr, 'mode', '') or sys.version_info[0] < 3: | |
48 | output = output.encode(preferredencoding()) | |
49 | sys.stderr.write(output) | |
50 | ||
51 | ||
52 | class FakeYDL(YoutubeDL): | |
53 | def __init__(self, override=None): | |
54 | # Different instances of the downloader can't share the same dictionary | |
55 | # some test set the "sublang" parameter, which would break the md5 checks. | |
56 | params = get_params(override=override) | |
57 | super(FakeYDL, self).__init__(params) | |
58 | self.result = [] | |
59 | ||
60 | def to_screen(self, s, skip_eol=None): | |
61 | print(s) | |
62 | ||
63 | def trouble(self, s, tb=None): | |
64 | raise Exception(s) | |
65 | ||
66 | def download(self, x): | |
67 | self.result.append(x) | |
68 | ||
69 | def expect_warning(self, regex): | |
70 | # Silence an expected warning matching a regex | |
71 | old_report_warning = self.report_warning | |
72 | def report_warning(self, message): | |
73 | if re.match(regex, message): return | |
74 | old_report_warning(message) | |
75 | self.report_warning = types.MethodType(report_warning, self) | |
76 | ||
77 | ||
78 | def gettestcases(include_onlymatching=False): | |
79 | for ie in youtube_dl.extractor.gen_extractors(): | |
80 | t = getattr(ie, '_TEST', None) | |
81 | if t: | |
82 | assert not hasattr(ie, '_TESTS'), \ | |
83 | '%s has _TEST and _TESTS' % type(ie).__name__ | |
84 | tests = [t] | |
85 | else: | |
86 | tests = getattr(ie, '_TESTS', []) | |
87 | for t in tests: | |
88 | if not include_onlymatching and t.get('only_matching', False): | |
89 | continue | |
90 | t['name'] = type(ie).__name__[:-len('IE')] | |
91 | yield t | |
92 | ||
93 | ||
94 | md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest() | |
95 | ||
96 | ||
97 | def expect_info_dict(self, expected_dict, got_dict): | |
98 | for info_field, expected in expected_dict.items(): | |
99 | if isinstance(expected, compat_str) and expected.startswith('re:'): | |
100 | got = got_dict.get(info_field) | |
101 | match_str = expected[len('re:'):] | |
102 | match_rex = re.compile(match_str) | |
103 | ||
104 | self.assertTrue( | |
105 | isinstance(got, compat_str) and match_rex.match(got), | |
106 | u'field %s (value: %r) should match %r' % (info_field, got, match_str)) | |
107 | elif isinstance(expected, type): | |
108 | got = got_dict.get(info_field) | |
109 | self.assertTrue(isinstance(got, expected), | |
110 | u'Expected type %r for field %s, but got value %r of type %r' % (expected, info_field, got, type(got))) | |
111 | else: | |
112 | if isinstance(expected, compat_str) and expected.startswith('md5:'): | |
113 | got = 'md5:' + md5(got_dict.get(info_field)) | |
114 | else: | |
115 | got = got_dict.get(info_field) | |
116 | self.assertEqual(expected, got, | |
117 | u'invalid value for field %s, expected %r, got %r' % (info_field, expected, got)) | |
118 | ||
119 | # Check for the presence of mandatory fields | |
120 | for key in ('id', 'url', 'title', 'ext'): | |
121 | self.assertTrue(got_dict.get(key), 'Missing mandatory field %s' % key) | |
122 | # Check for mandatory fields that are automatically set by YoutubeDL | |
123 | for key in ['webpage_url', 'extractor', 'extractor_key']: | |
124 | self.assertTrue(got_dict.get(key), u'Missing field: %s' % key) | |
125 | ||
126 | # Are checkable fields missing from the test case definition? | |
127 | test_info_dict = dict((key, value if not isinstance(value, compat_str) or len(value) < 250 else 'md5:' + md5(value)) | |
128 | for key, value in got_dict.items() | |
129 | if value and key in ('title', 'description', 'uploader', 'upload_date', 'timestamp', 'uploader_id', 'location')) | |
130 | missing_keys = set(test_info_dict.keys()) - set(expected_dict.keys()) | |
131 | if missing_keys: | |
132 | sys.stderr.write(u'\n"info_dict": ' + json.dumps(test_info_dict, ensure_ascii=False, indent=4) + u'\n') | |
133 | self.assertFalse( | |
134 | missing_keys, | |
135 | 'Missing keys in test definition: %s' % ( | |
136 | ', '.join(sorted(missing_keys)))) | |
137 | ||
138 | ||
139 | def assertRegexpMatches(self, text, regexp, msg=None): | |
140 | if hasattr(self, 'assertRegexpMatches'): | |
141 | return self.assertRegexpMatches(text, regexp, msg) | |
142 | else: | |
143 | m = re.match(regexp, text) | |
144 | if not m: | |
145 | note = 'Regexp didn\'t match: %r not found in %r' % (regexp, text) | |
146 | if msg is None: | |
147 | msg = note | |
148 | else: | |
149 | msg = note + ', ' + msg | |
150 | self.assertTrue(m, msg) | |
151 | ||
152 | ||
153 | def assertGreaterEqual(self, got, expected, msg=None): | |
154 | if not (got >= expected): | |
155 | if msg is None: | |
156 | msg = '%r not greater than or equal to %r' % (got, expected) | |
157 | self.assertTrue(got >= expected, msg) |