aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/parameters.json41
-rw-r--r--test/test_all_urls.py27
-rw-r--r--test/test_download.py210
-rw-r--r--test/test_execution.py26
-rw-r--r--test/test_utils.py105
-rw-r--r--test/test_write_info_json.py77
-rw-r--r--test/test_youtube_lists.py73
-rw-r--r--test/test_youtube_subtitles.py57
-rw-r--r--test/tests.json164
9 files changed, 664 insertions, 116 deletions
diff --git a/test/parameters.json b/test/parameters.json
index cc2b017eb..8215d25c5 100644
--- a/test/parameters.json
+++ b/test/parameters.json
@@ -1 +1,40 @@
-{"username": null, "listformats": null, "skip_download": false, "usenetrc": false, "max_downloads": null, "noprogress": false, "forcethumbnail": false, "forceformat": false, "format_limit": null, "ratelimit": null, "nooverwrites": false, "forceurl": false, "writeinfojson": false, "simulate": false, "playliststart": 1, "continuedl": true, "password": null, "prefer_free_formats": false, "nopart": false, "retries": 10, "updatetime": true, "consoletitle": false, "verbose": true, "forcefilename": false, "ignoreerrors": false, "logtostderr": false, "format": null, "subtitleslang": null, "quiet": false, "outtmpl": "%(id)s.%(ext)s", "rejecttitle": null, "playlistend": -1, "writedescription": false, "forcetitle": false, "forcedescription": false, "writesubtitles": false, "matchtitle": null} \ No newline at end of file
+{
+ "consoletitle": false,
+ "continuedl": true,
+ "forcedescription": false,
+ "forcefilename": false,
+ "forceformat": false,
+ "forcethumbnail": false,
+ "forcetitle": false,
+ "forceurl": false,
+ "format": null,
+ "format_limit": null,
+ "ignoreerrors": false,
+ "listformats": null,
+ "logtostderr": false,
+ "matchtitle": null,
+ "max_downloads": null,
+ "nooverwrites": false,
+ "nopart": false,
+ "noprogress": false,
+ "outtmpl": "%(id)s.%(ext)s",
+ "password": null,
+ "playlistend": -1,
+ "playliststart": 1,
+ "prefer_free_formats": false,
+ "quiet": false,
+ "ratelimit": null,
+ "rejecttitle": null,
+ "retries": 10,
+ "simulate": false,
+ "skip_download": false,
+ "subtitleslang": null,
+ "test": true,
+ "updatetime": true,
+ "usenetrc": false,
+ "username": null,
+ "verbose": true,
+ "writedescription": false,
+ "writeinfojson": true,
+ "writesubtitles": false
+} \ No newline at end of file
diff --git a/test/test_all_urls.py b/test/test_all_urls.py
new file mode 100644
index 000000000..06de8e7b8
--- /dev/null
+++ b/test/test_all_urls.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import sys
+import unittest
+
+# Allow direct execution
+import os
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from youtube_dl.InfoExtractors import YoutubeIE, YoutubePlaylistIE
+
+class TestAllURLsMatching(unittest.TestCase):
+ def test_youtube_playlist_matching(self):
+ self.assertTrue(YoutubePlaylistIE().suitable(u'ECUl4u3cNGP61MdtwGTqZA0MreSaDybji8'))
+ self.assertTrue(YoutubePlaylistIE().suitable(u'PL63F0C78739B09958'))
+ self.assertFalse(YoutubePlaylistIE().suitable(u'PLtS2H6bU1M'))
+
+ def test_youtube_matching(self):
+ self.assertTrue(YoutubeIE().suitable(u'PLtS2H6bU1M'))
+
+ def test_youtube_extract(self):
+ self.assertEqual(YoutubeIE()._extract_id('http://www.youtube.com/watch?&v=BaW_jenozKc'), 'BaW_jenozKc')
+ self.assertEqual(YoutubeIE()._extract_id('https://www.youtube.com/watch?&v=BaW_jenozKc'), 'BaW_jenozKc')
+ self.assertEqual(YoutubeIE()._extract_id('https://www.youtube.com/watch?feature=player_embedded&v=BaW_jenozKc'), 'BaW_jenozKc')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_download.py b/test/test_download.py
index 545afb922..40d596fdf 100644
--- a/test/test_download.py
+++ b/test/test_download.py
@@ -1,93 +1,125 @@
-#!/usr/bin/env python2
-import unittest
+#!/usr/bin/env python
+
+import errno
import hashlib
+import io
import os
import json
+import unittest
+import sys
+import hashlib
+import socket
+
+# Allow direct execution
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+import youtube_dl.FileDownloader
+import youtube_dl.InfoExtractors
+from youtube_dl.utils import *
+
+DEF_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tests.json')
+PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "parameters.json")
+
+# General configuration (from __init__, not very elegant...)
+jar = compat_cookiejar.CookieJar()
+cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
+proxy_handler = compat_urllib_request.ProxyHandler()
+opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
+compat_urllib_request.install_opener(opener)
+
+def _try_rm(filename):
+ """ Remove a file if it exists """
+ try:
+ os.remove(filename)
+ except OSError as ose:
+ if ose.errno != errno.ENOENT:
+ raise
+
+class FileDownloader(youtube_dl.FileDownloader):
+ def __init__(self, *args, **kwargs):
+ self.to_stderr = self.to_screen
+ self.processed_info_dicts = []
+ return youtube_dl.FileDownloader.__init__(self, *args, **kwargs)
+ def process_info(self, info_dict):
+ self.processed_info_dicts.append(info_dict)
+ return youtube_dl.FileDownloader.process_info(self, info_dict)
+
+def _file_md5(fn):
+ with open(fn, 'rb') as f:
+ return hashlib.md5(f.read()).hexdigest()
+
+with io.open(DEF_FILE, encoding='utf-8') as deff:
+ defs = json.load(deff)
+with io.open(PARAMETERS_FILE, encoding='utf-8') as pf:
+ parameters = json.load(pf)
+
+
+class TestDownload(unittest.TestCase):
+ def setUp(self):
+ self.parameters = parameters
+ self.defs = defs
+
+### Dynamically generate tests
+def generator(test_case):
+
+ def test_template(self):
+ ie = getattr(youtube_dl.InfoExtractors, test_case['name'] + 'IE')
+ if not ie._WORKING:
+ print('Skipping: IE marked as not _WORKING')
+ return
+ if 'playlist' not in test_case and not test_case['file']:
+ print('Skipping: No output file specified')
+ return
+ if 'skip' in test_case:
+ print('Skipping: {0}'.format(test_case['skip']))
+ return
+
+ params = self.parameters.copy()
+ params.update(test_case.get('params', {}))
+
+ fd = FileDownloader(params)
+ fd.add_info_extractor(ie())
+ for ien in test_case.get('add_ie', []):
+ fd.add_info_extractor(getattr(youtube_dl.InfoExtractors, ien + 'IE')())
+
+ test_cases = test_case.get('playlist', [test_case])
+ for tc in test_cases:
+ _try_rm(tc['file'])
+ _try_rm(tc['file'] + '.part')
+ _try_rm(tc['file'] + '.info.json')
+ try:
+ fd.download([test_case['url']])
+
+ for tc in test_cases:
+ if not test_case.get('params', {}).get('skip_download', False):
+ self.assertTrue(os.path.exists(tc['file']))
+ self.assertTrue(os.path.exists(tc['file'] + '.info.json'))
+ if 'md5' in tc:
+ md5_for_file = _file_md5(tc['file'])
+ self.assertEqual(md5_for_file, tc['md5'])
+ with io.open(tc['file'] + '.info.json', encoding='utf-8') as infof:
+ info_dict = json.load(infof)
+ for (info_field, value) in tc.get('info_dict', {}).items():
+ if value.startswith('md5:'):
+ md5_info_value = hashlib.md5(info_dict.get(info_field, '')).hexdigest()
+ self.assertEqual(value[3:], md5_info_value)
+ else:
+ self.assertEqual(value, info_dict.get(info_field))
+ finally:
+ for tc in test_cases:
+ _try_rm(tc['file'])
+ _try_rm(tc['file'] + '.part')
+ _try_rm(tc['file'] + '.info.json')
+
+ return test_template
+
+### And add them to TestDownload
+for test_case in defs:
+ test_method = generator(test_case)
+ test_method.__name__ = "test_{0}".format(test_case["name"])
+ setattr(TestDownload, test_method.__name__, test_method)
+ del test_method
+
-from youtube_dl.FileDownloader import FileDownloader
-from youtube_dl.InfoExtractors import YoutubeIE, DailymotionIE
-from youtube_dl.InfoExtractors import MetacafeIE, BlipTVIE
-
-
-class DownloadTest(unittest.TestCase):
- PARAMETERS_FILE = "test/parameters.json"
- #calculated with md5sum:
- #md5sum (GNU coreutils) 8.19
-
- YOUTUBE_SIZE = 1993883
- YOUTUBE_URL = "http://www.youtube.com/watch?v=BaW_jenozKc"
- YOUTUBE_FILE = "BaW_jenozKc.mp4"
-
- DAILYMOTION_MD5 = "d363a50e9eb4f22ce90d08d15695bb47"
- DAILYMOTION_URL = "http://www.dailymotion.com/video/x33vw9_tutoriel-de-youtubeur-dl-des-video_tech"
- DAILYMOTION_FILE = "x33vw9.mp4"
-
- METACAFE_SIZE = 5754305
- METACAFE_URL = "http://www.metacafe.com/watch/yt-_aUehQsCQtM/the_electric_company_short_i_pbs_kids_go/"
- METACAFE_FILE = "_aUehQsCQtM.flv"
-
- BLIP_MD5 = "93c24d2f4e0782af13b8a7606ea97ba7"
- BLIP_URL = "http://blip.tv/cbr/cbr-exclusive-gotham-city-imposters-bats-vs-jokerz-short-3-5796352"
- BLIP_FILE = "5779306.m4v"
-
- XVIDEO_MD5 = ""
- XVIDEO_URL = ""
- XVIDEO_FILE = ""
-
-
- def test_youtube(self):
- #let's download a file from youtube
- with open(DownloadTest.PARAMETERS_FILE) as f:
- fd = FileDownloader(json.load(f))
- fd.add_info_extractor(YoutubeIE())
- fd.download([DownloadTest.YOUTUBE_URL])
- self.assertTrue(os.path.exists(DownloadTest.YOUTUBE_FILE))
- self.assertEqual(os.path.getsize(DownloadTest.YOUTUBE_FILE), DownloadTest.YOUTUBE_SIZE)
-
- def test_dailymotion(self):
- with open(DownloadTest.PARAMETERS_FILE) as f:
- fd = FileDownloader(json.load(f))
- fd.add_info_extractor(DailymotionIE())
- fd.download([DownloadTest.DAILYMOTION_URL])
- self.assertTrue(os.path.exists(DownloadTest.DAILYMOTION_FILE))
- md5_down_file = md5_for_file(DownloadTest.DAILYMOTION_FILE)
- self.assertEqual(md5_down_file, DownloadTest.DAILYMOTION_MD5)
-
- def test_metacafe(self):
- #this emulate a skip,to be 2.6 compatible
- with open(DownloadTest.PARAMETERS_FILE) as f:
- fd = FileDownloader(json.load(f))
- fd.add_info_extractor(MetacafeIE())
- fd.add_info_extractor(YoutubeIE())
- fd.download([DownloadTest.METACAFE_URL])
- self.assertTrue(os.path.exists(DownloadTest.METACAFE_FILE))
- self.assertEqual(os.path.getsize(DownloadTest.METACAFE_FILE), DownloadTest.METACAFE_SIZE)
-
- def test_blip(self):
- with open(DownloadTest.PARAMETERS_FILE) as f:
- fd = FileDownloader(json.load(f))
- fd.add_info_extractor(BlipTVIE())
- fd.download([DownloadTest.BLIP_URL])
- self.assertTrue(os.path.exists(DownloadTest.BLIP_FILE))
- md5_down_file = md5_for_file(DownloadTest.BLIP_FILE)
- self.assertEqual(md5_down_file, DownloadTest.BLIP_MD5)
-
- def tearDown(self):
- if os.path.exists(DownloadTest.YOUTUBE_FILE):
- os.remove(DownloadTest.YOUTUBE_FILE)
- if os.path.exists(DownloadTest.DAILYMOTION_FILE):
- os.remove(DownloadTest.DAILYMOTION_FILE)
- if os.path.exists(DownloadTest.METACAFE_FILE):
- os.remove(DownloadTest.METACAFE_FILE)
- if os.path.exists(DownloadTest.BLIP_FILE):
- os.remove(DownloadTest.BLIP_FILE)
-
-def md5_for_file(filename, block_size=2**20):
- with open(filename) as f:
- md5 = hashlib.md5()
- while True:
- data = f.read(block_size)
- if not data:
- break
- md5.update(data)
- return md5.hexdigest()
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_execution.py b/test/test_execution.py
new file mode 100644
index 000000000..2b115fb31
--- /dev/null
+++ b/test/test_execution.py
@@ -0,0 +1,26 @@
+import unittest
+
+import sys
+import os
+import subprocess
+
+rootDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+try:
+ _DEV_NULL = subprocess.DEVNULL
+except AttributeError:
+ _DEV_NULL = open(os.devnull, 'wb')
+
+class TestExecution(unittest.TestCase):
+ def test_import(self):
+ subprocess.check_call([sys.executable, '-c', 'import youtube_dl'], cwd=rootDir)
+
+ def test_module_exec(self):
+ if sys.version_info >= (2,7): # Python 2.6 doesn't support package execution
+ subprocess.check_call([sys.executable, '-m', 'youtube_dl', '--version'], cwd=rootDir, stdout=_DEV_NULL)
+
+ def test_main_exec(self):
+ subprocess.check_call([sys.executable, 'youtube_dl/__main__.py', '--version'], cwd=rootDir, stdout=_DEV_NULL)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_utils.py b/test/test_utils.py
index e7c6d5b3d..eeaaa7fad 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -1,47 +1,100 @@
-# -*- coding: utf-8 -*-
+#!/usr/bin/env python
# Various small unit tests
+import sys
import unittest
+# Allow direct execution
+import os
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
#from youtube_dl.utils import htmlentity_transform
from youtube_dl.utils import timeconvert
from youtube_dl.utils import sanitize_filename
from youtube_dl.utils import unescapeHTML
from youtube_dl.utils import orderedSet
+if sys.version_info < (3, 0):
+ _compat_str = lambda b: b.decode('unicode-escape')
+else:
+ _compat_str = lambda s: s
+
class TestUtil(unittest.TestCase):
- def test_timeconvert(self):
- self.assertTrue(timeconvert('') is None)
- self.assertTrue(timeconvert('bougrg') is None)
+ def test_timeconvert(self):
+ self.assertTrue(timeconvert('') is None)
+ self.assertTrue(timeconvert('bougrg') is None)
+
+ def test_sanitize_filename(self):
+ self.assertEqual(sanitize_filename('abc'), 'abc')
+ self.assertEqual(sanitize_filename('abc_d-e'), 'abc_d-e')
+
+ self.assertEqual(sanitize_filename('123'), '123')
+
+ self.assertEqual('abc_de', sanitize_filename('abc/de'))
+ self.assertFalse('/' in sanitize_filename('abc/de///'))
+
+ self.assertEqual('abc_de', sanitize_filename('abc/<>\\*|de'))
+ self.assertEqual('xxx', sanitize_filename('xxx/<>\\*|'))
+ self.assertEqual('yes no', sanitize_filename('yes? no'))
+ self.assertEqual('this - that', sanitize_filename('this: that'))
+
+ self.assertEqual(sanitize_filename('AT&T'), 'AT&T')
+ aumlaut = _compat_str('\xe4')
+ self.assertEqual(sanitize_filename(aumlaut), aumlaut)
+ tests = _compat_str('\u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430')
+ self.assertEqual(sanitize_filename(tests), tests)
+
+ forbidden = '"\0\\/'
+ for fc in forbidden:
+ for fbc in forbidden:
+ self.assertTrue(fbc not in sanitize_filename(fc))
+
+ def test_sanitize_filename_restricted(self):
+ self.assertEqual(sanitize_filename('abc', restricted=True), 'abc')
+ self.assertEqual(sanitize_filename('abc_d-e', restricted=True), 'abc_d-e')
+
+ self.assertEqual(sanitize_filename('123', restricted=True), '123')
+
+ self.assertEqual('abc_de', sanitize_filename('abc/de', restricted=True))
+ self.assertFalse('/' in sanitize_filename('abc/de///', restricted=True))
- def test_sanitize_filename(self):
- self.assertEqual(sanitize_filename(u'abc'), u'abc')
- self.assertEqual(sanitize_filename(u'abc_d-e'), u'abc_d-e')
+ self.assertEqual('abc_de', sanitize_filename('abc/<>\\*|de', restricted=True))
+ self.assertEqual('xxx', sanitize_filename('xxx/<>\\*|', restricted=True))
+ self.assertEqual('yes_no', sanitize_filename('yes? no', restricted=True))
+ self.assertEqual('this_-_that', sanitize_filename('this: that', restricted=True))
- self.assertEqual(sanitize_filename(u'123'), u'123')
+ tests = _compat_str('a\xe4b\u4e2d\u56fd\u7684c')
+ self.assertEqual(sanitize_filename(tests, restricted=True), 'a_b_c')
+ self.assertTrue(sanitize_filename(_compat_str('\xf6'), restricted=True) != '') # No empty filename
- self.assertEqual(u'abc-de', sanitize_filename(u'abc/de'))
- self.assertFalse(u'/' in sanitize_filename(u'abc/de///'))
+ forbidden = '"\0\\/&!: \'\t\n()[]{}$;`^,#'
+ for fc in forbidden:
+ for fbc in forbidden:
+ self.assertTrue(fbc not in sanitize_filename(fc, restricted=True))
- self.assertEqual(u'abc-de', sanitize_filename(u'abc/<>\\*|de'))
- self.assertEqual(u'xxx', sanitize_filename(u'xxx/<>\\*|'))
- self.assertEqual(u'yes no', sanitize_filename(u'yes? no'))
- self.assertEqual(u'this - that', sanitize_filename(u'this: that'))
+ # Handle a common case more neatly
+ self.assertEqual(sanitize_filename(_compat_str('\u5927\u58f0\u5e26 - Song'), restricted=True), 'Song')
+ self.assertEqual(sanitize_filename(_compat_str('\u603b\u7edf: Speech'), restricted=True), 'Speech')
+ # .. but make sure the file name is never empty
+ self.assertTrue(sanitize_filename('-', restricted=True) != '')
+ self.assertTrue(sanitize_filename(':', restricted=True) != '')
- self.assertEqual(sanitize_filename(u'ä'), u'ä')
- self.assertEqual(sanitize_filename(u'кириллица'), u'кириллица')
+ def test_sanitize_ids(self):
+ self.assertEqual(sanitize_filename('_n_cd26wFpw', is_id=True), '_n_cd26wFpw')
+ self.assertEqual(sanitize_filename('_BD_eEpuzXw', is_id=True), '_BD_eEpuzXw')
+ self.assertEqual(sanitize_filename('N0Y__7-UOdI', is_id=True), 'N0Y__7-UOdI')
- for forbidden in u'"\0\\/':
- self.assertTrue(forbidden not in sanitize_filename(forbidden))
+ def test_ordered_set(self):
+ self.assertEqual(orderedSet([1, 1, 2, 3, 4, 4, 5, 6, 7, 3, 5]), [1, 2, 3, 4, 5, 6, 7])
+ self.assertEqual(orderedSet([]), [])
+ self.assertEqual(orderedSet([1]), [1])
+ #keep the list ordered
+ self.assertEqual(orderedSet([135, 1, 1, 1]), [135, 1])
- def test_ordered_set(self):
- self.assertEqual(orderedSet([1,1,2,3,4,4,5,6,7,3,5]), [1,2,3,4,5,6,7])
- self.assertEqual(orderedSet([]), [])
- self.assertEqual(orderedSet([1]), [1])
- #keep the list ordered
- self.assertEqual(orderedSet([135,1,1,1]), [135,1])
+ def test_unescape_html(self):
+ self.assertEqual(unescapeHTML(_compat_str('%20;')), _compat_str('%20;'))
- def test_unescape_html(self):
- self.assertEqual(unescapeHTML(u"%20;"), u"%20;")
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_write_info_json.py b/test/test_write_info_json.py
new file mode 100644
index 000000000..8134dda37
--- /dev/null
+++ b/test/test_write_info_json.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+import json
+import os
+import sys
+import unittest
+
+# Allow direct execution
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+import youtube_dl.FileDownloader
+import youtube_dl.InfoExtractors
+from youtube_dl.utils import *
+
+PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "parameters.json")
+
+# General configuration (from __init__, not very elegant...)
+jar = compat_cookiejar.CookieJar()
+cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
+proxy_handler = compat_urllib_request.ProxyHandler()
+opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
+compat_urllib_request.install_opener(opener)
+
+class FileDownloader(youtube_dl.FileDownloader):
+ def __init__(self, *args, **kwargs):
+ youtube_dl.FileDownloader.__init__(self, *args, **kwargs)
+ self.to_stderr = self.to_screen
+
+with io.open(PARAMETERS_FILE, encoding='utf-8') as pf:
+ params = json.load(pf)
+params['writeinfojson'] = True
+params['skip_download'] = True
+params['writedescription'] = True
+
+TEST_ID = 'BaW_jenozKc'
+INFO_JSON_FILE = TEST_ID + '.mp4.info.json'
+DESCRIPTION_FILE = TEST_ID + '.mp4.description'
+EXPECTED_DESCRIPTION = u'''test chars: "'/\ä↭𝕐
+
+This is a test video for youtube-dl.
+
+For more information, contact phihag@phihag.de .'''
+
+class TestInfoJSON(unittest.TestCase):
+ def setUp(self):
+ # Clear old files
+ self.tearDown()
+
+ def test_info_json(self):
+ ie = youtube_dl.InfoExtractors.YoutubeIE()
+ fd = FileDownloader(params)
+ fd.add_info_extractor(ie)
+ fd.download([TEST_ID])
+ self.assertTrue(os.path.exists(INFO_JSON_FILE))
+ with io.open(INFO_JSON_FILE, 'r', encoding='utf-8') as jsonf:
+ jd = json.load(jsonf)
+ self.assertEqual(jd['upload_date'], u'20121002')
+ self.assertEqual(jd['description'], EXPECTED_DESCRIPTION)
+ self.assertEqual(jd['id'], TEST_ID)
+ self.assertEqual(jd['extractor'], 'youtube')
+ self.assertEqual(jd['title'], u'''youtube-dl test video "'/\ä↭𝕐''')
+ self.assertEqual(jd['uploader'], 'Philipp Hagemeister')
+
+ self.assertTrue(os.path.exists(DESCRIPTION_FILE))
+ with io.open(DESCRIPTION_FILE, 'r', encoding='utf-8') as descf:
+ descr = descf.read()
+ self.assertEqual(descr, EXPECTED_DESCRIPTION)
+
+ def tearDown(self):
+ if os.path.exists(INFO_JSON_FILE):
+ os.remove(INFO_JSON_FILE)
+ if os.path.exists(DESCRIPTION_FILE):
+ os.remove(DESCRIPTION_FILE)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_youtube_lists.py b/test/test_youtube_lists.py
new file mode 100644
index 000000000..3044e0852
--- /dev/null
+++ b/test/test_youtube_lists.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+import sys
+import unittest
+import json
+
+# Allow direct execution
+import os
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from youtube_dl.InfoExtractors import YoutubeUserIE,YoutubePlaylistIE
+from youtube_dl.utils import *
+
+PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "parameters.json")
+with io.open(PARAMETERS_FILE, encoding='utf-8') as pf:
+ parameters = json.load(pf)
+
+# General configuration (from __init__, not very elegant...)
+jar = compat_cookiejar.CookieJar()
+cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
+proxy_handler = compat_urllib_request.ProxyHandler()
+opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
+compat_urllib_request.install_opener(opener)
+
+class FakeDownloader(object):
+ def __init__(self):
+ self.result = []
+ self.params = parameters
+ def to_screen(self, s):
+ print(s)
+ def trouble(self, s):
+ raise Exception(s)
+ def download(self, x):
+ self.result.append(x)
+
+class TestYoutubeLists(unittest.TestCase):
+ def test_youtube_playlist(self):
+ DL = FakeDownloader()
+ IE = YoutubePlaylistIE(DL)
+ IE.extract('https://www.youtube.com/playlist?list=PLwiyx1dc3P2JR9N8gQaQN_BCvlSlap7re')
+ self.assertEqual(DL.result, [
+ ['http://www.youtube.com/watch?v=bV9L5Ht9LgY'],
+ ['http://www.youtube.com/watch?v=FXxLjLQi3Fg'],
+ ['http://www.youtube.com/watch?v=tU3Bgo5qJZE']
+ ])
+
+ def test_youtube_playlist_long(self):
+ DL = FakeDownloader()
+ IE = YoutubePlaylistIE(DL)
+ IE.extract('https://www.youtube.com/playlist?list=UUBABnxM4Ar9ten8Mdjj1j0Q')
+ self.assertTrue(len(DL.result) >= 799)
+
+ def test_youtube_course(self):
+ DL = FakeDownloader()
+ IE = YoutubePlaylistIE(DL)
+ # TODO find a > 100 (paginating?) videos course
+ IE.extract('https://www.youtube.com/course?list=ECUl4u3cNGP61MdtwGTqZA0MreSaDybji8')
+ self.assertEqual(DL.result[0], ['http://www.youtube.com/watch?v=j9WZyLZCBzs'])
+ self.assertEqual(len(DL.result), 25)
+ self.assertEqual(DL.result[-1], ['http://www.youtube.com/watch?v=rYefUsYuEp0'])
+
+ def test_youtube_channel(self):
+ # I give up, please find a channel that does paginate and test this like test_youtube_playlist_long
+ pass # TODO
+
+ def test_youtube_user(self):
+ DL = FakeDownloader()
+ IE = YoutubeUserIE(DL)
+ IE.extract('https://www.youtube.com/user/TheLinuxFoundation')
+ self.assertTrue(len(DL.result) >= 320)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_youtube_subtitles.py b/test/test_youtube_subtitles.py
new file mode 100644
index 000000000..5d3566a35
--- /dev/null
+++ b/test/test_youtube_subtitles.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+import sys
+import unittest
+import json
+import io
+import hashlib
+
+# Allow direct execution
+import os
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from youtube_dl.InfoExtractors import YoutubeIE
+from youtube_dl.utils import *
+
+PARAMETERS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "parameters.json")
+with io.open(PARAMETERS_FILE, encoding='utf-8') as pf:
+ parameters = json.load(pf)
+
+# General configuration (from __init__, not very elegant...)
+jar = compat_cookiejar.CookieJar()
+cookie_processor = compat_urllib_request.HTTPCookieProcessor(jar)
+proxy_handler = compat_urllib_request.ProxyHandler()
+opener = compat_urllib_request.build_opener(proxy_handler, cookie_processor, YoutubeDLHandler())
+compat_urllib_request.install_opener(opener)
+
+class FakeDownloader(object):
+ def __init__(self):
+ self.result = []
+ self.params = parameters
+ def to_screen(self, s):
+ print(s)
+ def trouble(self, s):
+ raise Exception(s)
+ def download(self, x):
+ self.result.append(x)
+
+md5 = lambda s: hashlib.md5(s.encode('utf-8')).hexdigest()
+
+class TestYoutubeSubtitles(unittest.TestCase):
+ def test_youtube_subtitles(self):
+ DL = FakeDownloader()
+ DL.params['writesubtitles'] = True
+ IE = YoutubeIE(DL)
+ info_dict = IE.extract('QRS8MkLhQmM')
+ self.assertEqual(md5(info_dict[0]['subtitles']), 'c3228550d59116f3c29fba370b55d033')
+
+ def test_youtube_subtitles_it(self):
+ DL = FakeDownloader()
+ DL.params['writesubtitles'] = True
+ DL.params['subtitleslang'] = 'it'
+ IE = YoutubeIE(DL)
+ info_dict = IE.extract('QRS8MkLhQmM')
+ self.assertEqual(md5(info_dict[0]['subtitles']), '132a88a0daf8e1520f393eb58f1f646a')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/tests.json b/test/tests.json
new file mode 100644
index 000000000..cd72a88e3
--- /dev/null
+++ b/test/tests.json
@@ -0,0 +1,164 @@
+[
+ {
+ "name": "Youtube",
+ "url": "http://www.youtube.com/watch?v=BaW_jenozKc",
+ "file": "BaW_jenozKc.mp4",
+ "info_dict": {
+ "title": "youtube-dl test video \"'/\\ä↭𝕐",
+ "uploader": "Philipp Hagemeister",
+ "uploader_id": "phihag",
+ "upload_date": "20121002",
+ "description": "test chars: \"'/\\ä↭𝕐\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de ."
+ }
+ },
+ {
+ "name": "Dailymotion",
+ "md5": "392c4b85a60a90dc4792da41ce3144eb",
+ "url": "http://www.dailymotion.com/video/x33vw9_tutoriel-de-youtubeur-dl-des-video_tech",
+ "file": "x33vw9.mp4"
+ },
+ {
+ "name": "Metacafe",
+ "add_ie": ["Youtube"],
+ "url": "http://metacafe.com/watch/yt-_aUehQsCQtM/the_electric_company_short_i_pbs_kids_go/",
+ "file": "_aUehQsCQtM.flv"
+ },
+ {
+ "name": "BlipTV",
+ "md5": "b2d849efcf7ee18917e4b4d9ff37cafe",
+ "url": "http://blip.tv/cbr/cbr-exclusive-gotham-city-imposters-bats-vs-jokerz-short-3-5796352",
+ "file": "5779306.m4v"
+ },
+ {
+ "name": "XVideos",
+ "md5": "1d0c835822f0a71a7bf011855db929d0",
+ "url": "http://www.xvideos.com/video939581/funny_porns_by_s_-1",
+ "file": "939581.flv"
+ },
+ {
+ "name": "Vimeo",
+ "md5": "8879b6cc097e987f02484baf890129e5",
+ "url": "http://vimeo.com/56015672",
+ "file": "56015672.mp4",
+ "info_dict": {
+ "title": "youtube-dl test video - ★ \" ' 幸 / \\ ä ↭ 𝕐",
+ "uploader": "Filippo Valsorda",
+ "uploader_id": "user7108434",
+ "upload_date": "20121220",
+ "description": "This is a test case for youtube-dl.\nFor more information, see github.com/rg3/youtube-dl\nTest chars: ★ \" ' 幸 / \\ ä ↭ 𝕐"
+ }
+ },
+ {
+ "name": "Soundcloud",
+ "md5": "ebef0a451b909710ed1d7787dddbf0d7",
+ "url": "http://soundcloud.com/ethmusic/lostin-powers-she-so-heavy",
+ "file": "62986583.mp3"
+ },
+ {
+ "name": "StanfordOpenClassroom",
+ "md5": "544a9468546059d4e80d76265b0443b8",
+ "url": "http://openclassroom.stanford.edu/MainFolder/VideoPage.php?course=PracticalUnix&video=intro-environment&speed=100",
+ "file": "PracticalUnix_intro-environment.mp4"
+ },
+ {
+ "name": "XNXX",
+ "md5": "0831677e2b4761795f68d417e0b7b445",
+ "url": "http://video.xnxx.com/video1135332/lida_naked_funny_actress_5_",
+ "file": "1135332.flv"
+ },
+ {
+ "name": "Youku",
+ "url": "http://v.youku.com/v_show/id_XNDgyMDQ2NTQw.html",
+ "file": "XNDgyMDQ2NTQw_part00.flv",
+ "md5": "ffe3f2e435663dc2d1eea34faeff5b5b",
+ "params": { "test": false }
+ },
+ {
+ "name": "NBA",
+ "url": "http://www.nba.com/video/games/nets/2012/12/04/0021200253-okc-bkn-recap.nba/index.html",
+ "file": "0021200253-okc-bkn-recap.nba.mp4",
+ "md5": "c0edcfc37607344e2ff8f13c378c88a4"
+ },
+ {
+ "name": "JustinTV",
+ "url": "http://www.twitch.tv/thegamedevhub/b/296128360",
+ "file": "296128360.flv",
+ "md5": "ecaa8a790c22a40770901460af191c9a"
+ },
+ {
+ "name": "MyVideo",
+ "url": "http://www.myvideo.de/watch/8229274/bowling_fail_or_win",
+ "file": "8229274.flv",
+ "md5": "2d2753e8130479ba2cb7e0a37002053e"
+ },
+ {
+ "name": "Escapist",
+ "url": "http://www.escapistmagazine.com/videos/view/the-escapist-presents/6618-Breaking-Down-Baldurs-Gate",
+ "file": "6618-Breaking-Down-Baldurs-Gate.flv",
+ "md5": "c6793dbda81388f4264c1ba18684a74d",
+ "skip": "Fails with timeout on Travis"
+ },
+ {
+ "name": "GooglePlus",
+ "url": "https://plus.google.com/u/0/108897254135232129896/posts/ZButuJc6CtH",
+ "file": "ZButuJc6CtH.flv"
+ },
+ {
+ "name": "FunnyOrDie",
+ "url": "http://www.funnyordie.com/videos/0732f586d7/heart-shaped-box-literal-video-version",
+ "file": "0732f586d7.mp4",
+ "md5": "f647e9e90064b53b6e046e75d0241fbd"
+ },
+ {
+ "name": "TweetReel",
+ "url": "http://tweetreel.com/?77smq",
+ "file": "77smq.mov",
+ "md5": "56b4d9ca9de467920f3f99a6d91255d6",
+ "info_dict": {
+ "uploader": "itszero",
+ "uploader_id": "itszero",
+ "upload_date": "20091225",
+ "description": "Installing Gentoo Linux on Powerbook G4, it turns out the sleep indicator becomes HDD activity indicator :D"
+ }
+ },
+ {
+ "name": "Steam",
+ "url": "http://store.steampowered.com/video/105600/",
+ "playlist": [
+ {
+ "file": "81300.flv",
+ "md5": "f870007cee7065d7c76b88f0a45ecc07",
+ "info_dict": {
+ "title": "Terraria 1.1 Trailer"
+ }
+ },
+ {
+ "file": "80859.flv",
+ "md5": "61aaf31a5c5c3041afb58fb83cbb5751",
+ "info_dict": {
+ "title": "Terraria Trailer"
+ }
+ }
+ ]
+ },
+ {
+ "name": "Ustream",
+ "url": "http://www.ustream.tv/recorded/20274954",
+ "file": "20274954.flv",
+ "md5": "088f151799e8f572f84eb62f17d73e5c",
+ "info_dict": {
+ "title": "Young Americans for Liberty February 7, 2012 2:28 AM"
+ }
+ },
+ {
+ "name": "InfoQ",
+ "url": "http://www.infoq.com/presentations/A-Few-of-My-Favorite-Python-Things",
+ "file": "12-jan-pythonthings.mp4",
+ "info_dict": {
+ "title": "A Few of My Favorite [Python] Things"
+ },
+ "params": {
+ "skip_download": true
+ }
+ }
+]