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.
 
 
 

96 lines
3.1 KiB

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