The little things give you away... A collection of various small helper stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

97 lines
3.2 KiB

  1. #!/usr/bin/env python3
  2. import itertools
  3. import os.path
  4. import subprocess
  5. def test(input, lines):
  6. 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)
  7. stdout, stderr = p.communicate(input)
  8. assert not stderr
  9. stdout = stdout.split(b'\n')
  10. assert stdout[-1] == b'' and stdout[:-1] == lines, f'Got {stdout!r} instead of {lines!r} from {input!r}'
  11. def is_id_char(c):
  12. return b'0' <= c <= b'9' or b'a' <= c <= b'z' or b'A' <= c <= b'Z' or c == b'_' or c == b'-'
  13. def bytes_range(a, b):
  14. # Yields every char between a and b (inclusive) as a bytes object
  15. return map(lambda x: bytes([x]), range(ord(a), ord(b) + 1))
  16. test(b'', [])
  17. test(b'short\n', [])
  18. test(b'01234567890', [b'v 01234567890'])
  19. test(b'01234567890\n', [b'v 01234567890'])
  20. # Videos
  21. input = []
  22. for a in map(lambda x: bytes.fromhex(f'{x:02x}'), range(256)):
  23. if is_id_char(a):
  24. continue
  25. for b in map(lambda x: bytes.fromhex(f'{x:02x}'), range(256)):
  26. if is_id_char(b):
  27. continue
  28. input.append(a + b'0aA_-1bB_-2' + b)
  29. test(b''.join(input), [b'v 0aA_-1bB_-2'] * len(input))
  30. # Channels
  31. test(b'0123456789abcdeFGHIJ_-', [b'c 0123456789abcdeFGHIJ_-'])
  32. test(b'UC0123456789abcdeFGHIJ_-', [b'c UC0123456789abcdeFGHIJ_-'])
  33. # Pure playlists
  34. playlists = [
  35. b'0123456789ABCDEF',
  36. b'PL0123456789ABCDEF',
  37. b'0123456789abcdefghijABCDEFGHIJ_-',
  38. b'PL0123456789abcdefghijABCDEFGHIJ_-',
  39. b'RDAMVM0123456789abcdeFGHIJ_-',
  40. b'RDGMEM0123456789abcdeFGHIJ_-',
  41. b'RDAO0123456789abcdeFGHIJ_-',
  42. b'RDEM0123456789abcdeFGHIJ_-',
  43. b'RDKM0123456789abcdeFGHIJ_-',
  44. ]
  45. for playlist in playlists:
  46. test(playlist, [b'p ' + playlist])
  47. # Music playlist madness
  48. for prefix in (b'RDCLAK5uy_', b'RDTMAK5uy_', b'OLAK5uy_'):
  49. for c in bytes_range(b'k', b'n'):
  50. test(prefix + c + b'0123456789abcdefghijABCDEFGHIJ_-', [b'p ' + prefix + c + b'0123456789abcdefghijABCDEFGHIJ_-'])
  51. # Playlists with video IDs
  52. 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'):
  53. test(prefix + b'0aA_-1bB_-2', [b'p ' + prefix + b'0aA_-1bB_-2', b'v 0aA_-1bB_-2'])
  54. for a, b in itertools.product(bytes_range(b'0', b'4'), bytes_range(b'0', b'9')):
  55. playlist = b'RD' + a + b + b'0aA_-1bB_-2'
  56. test(playlist, [b'p ' + playlist, b'v 0aA_-1bB_-2'])
  57. playlist = b'RDGMEM' + b'0123456789abcdeFGHIJ_-' + b'VM0aA_-1bB_-2'
  58. test(playlist, [b'p ' + playlist, b'v 0aA_-1bB_-2'])
  59. # Playlists with channel IDs
  60. for prefix in (b'UU', b'LL', b'FL', b'PU', b'UUSH'):
  61. test(prefix + b'0123456789abcdeFGHIJ_-', [b'p ' + prefix + b'0123456789abcdeFGHIJ_-', b'c 0123456789abcdeFGHIJ_-'])
  62. test(b'RDCMUC0123456789abcdeFGHIJ_-', [b'p RDCMUC0123456789abcdeFGHIJ_-', b'c UC0123456789abcdeFGHIJ_-'])
  63. # Some particular unrecognised IDs
  64. ids = [
  65. b'0123456789ABCDEG',
  66. b'PL0123456789ABCDEG',
  67. b'RDCLAK5uy_j0123456789abcdefghijABCDEFGHIJ_-',
  68. b'RDCLAK5uy_o0123456789abcdefghijABCDEFGHIJ_-',
  69. ]
  70. for id_ in ids:
  71. test(id_, [b'? ' + id_])
  72. # Buffer rollover
  73. BUFFER_SIZE = 1024 * 1024
  74. for offset in range(-11, 1):
  75. test(b'?' * (BUFFER_SIZE + offset) + b'0aA_-1bB_-2', [b'v 0aA_-1bB_-2'])
  76. # Max length exceedance
  77. MAX_RESULT_SIZE = 1024
  78. for length in range(MAX_RESULT_SIZE + 1, MAX_RESULT_SIZE + 15):
  79. test(b'0' * length, [])