|
- #!/usr/bin/env python3
- import itertools
- import os.path
- import subprocess
-
-
- def test(input, lines):
- p = subprocess.Popen([os.path.join(os.path.dirname(__file__), '.make-and-exec-binaries', 'youtube-extract-rapid'], text = False, stdin = subprocess.PIPE, stdout = subprocess.PIPE)
- stdout, stderr = p.communicate(input)
- assert not stderr
- stdout = stdout.split(b'\n')
- assert stdout[-1] == b'' and stdout[:-1] == lines, f'Got {stdout!r} instead of {lines!r} from {input!r}'
-
-
- def is_id_char(c):
- return b'0' <= c <= b'9' or b'a' <= c <= b'z' or b'A' <= c <= b'Z' or c == b'_' or c == b'-'
-
-
- def bytes_range(a, b):
- # Yields every char between a and b (inclusive) as a bytes object
- return map(lambda x: bytes([x]), range(ord(a), ord(b) + 1))
-
-
- test(b'', [])
- test(b'short\n', [])
- test(b'01234567890', [b'v 01234567890'])
- test(b'01234567890\n', [b'v 01234567890'])
-
- # Videos
- input = []
- for a in map(lambda x: bytes.fromhex(f'{x:02x}'), range(256)):
- if is_id_char(a):
- continue
- for b in map(lambda x: bytes.fromhex(f'{x:02x}'), range(256)):
- if is_id_char(b):
- continue
- input.append(a + b'0aA_-1bB_-2' + b)
- test(b''.join(input), [b'v 0aA_-1bB_-2'] * len(input))
-
- # Channels
- test(b'0123456789abcdeFGHIJ_-', [b'c 0123456789abcdeFGHIJ_-'])
- test(b'UC0123456789abcdeFGHIJ_-', [b'c UC0123456789abcdeFGHIJ_-'])
-
- # Pure playlists
- playlists = [
- b'0123456789ABCDEF',
- b'PL0123456789ABCDEF',
- b'0123456789abcdefghijABCDEFGHIJ_-',
- b'PL0123456789abcdefghijABCDEFGHIJ_-',
- b'RDAMVM0123456789abcdeFGHIJ_-',
- b'RDGMEM0123456789abcdeFGHIJ_-',
- b'RDAO0123456789abcdeFGHIJ_-',
- b'RDEM0123456789abcdeFGHIJ_-',
- b'RDKM0123456789abcdeFGHIJ_-',
- ]
- for playlist in playlists:
- test(playlist, [b'p ' + playlist])
-
- # Music playlist madness
- for prefix in (b'RDCLAK5uy_', b'RDTMAK5uy_', b'OLAK5uy_'):
- for c in bytes_range(b'k', b'n'):
- test(prefix + c + b'0123456789abcdefghijABCDEFGHIJ_-', [b'p ' + prefix + c + b'0123456789abcdefghijABCDEFGHIJ_-'])
-
- # Playlists with video IDs
- for prefix in (b'RD', b'UL', b'EL', b'CL', b'SL', b'LP', b'RDMM', b'RDQM', b'RDEM', b'RDLV', b'RDHC'):
- test(prefix + b'0aA_-1bB_-2', [b'p ' + prefix + b'0aA_-1bB_-2', b'v 0aA_-1bB_-2'])
- for a, b in itertools.product(bytes_range(b'0', b'4'), bytes_range(b'0', b'9')):
- playlist = b'RD' + a + b + b'0aA_-1bB_-2'
- test(playlist, [b'p ' + playlist, b'v 0aA_-1bB_-2'])
- playlist = b'RDGMEM' + b'0123456789abcdeFGHIJ_-' + b'VM0aA_-1bB_-2'
- test(playlist, [b'p ' + playlist, b'v 0aA_-1bB_-2'])
-
- # Playlists with channel IDs
- for prefix in (b'UU', b'LL', b'FL', b'PU', b'UUSH'):
- test(prefix + b'0123456789abcdeFGHIJ_-', [b'p ' + prefix + b'0123456789abcdeFGHIJ_-', b'c 0123456789abcdeFGHIJ_-'])
- test(b'RDCMUC0123456789abcdeFGHIJ_-', [b'p RDCMUC0123456789abcdeFGHIJ_-', b'c UC0123456789abcdeFGHIJ_-'])
-
- # Some particular unrecognised IDs
- ids = [
- b'0123456789ABCDEG',
- b'PL0123456789ABCDEG',
- b'RDCLAK5uy_j0123456789abcdefghijABCDEFGHIJ_-',
- b'RDCLAK5uy_o0123456789abcdefghijABCDEFGHIJ_-',
- ]
- for id_ in ids:
- test(id_, [b'? ' + id_])
-
- # Buffer rollover
- BUFFER_SIZE = 1024 * 1024
- for offset in range(-11, 1):
- test(b'?' * (BUFFER_SIZE + offset) + b'0aA_-1bB_-2', [b'v 0aA_-1bB_-2'])
-
- # Max length exceedance
- MAX_RESULT_SIZE = 1024
- for length in range(MAX_RESULT_SIZE + 1, MAX_RESULT_SIZE + 15):
- test(b'0' * length, [])
|