run_sql_parser_test.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from pathlib import Path
  2. import sys
  3. import time
  4. from watchdog.observers import Observer
  5. from watchdog.events import FileSystemEventHandler
  6. from watchdog.events import LoggingEventHandler
  7. import asyncio.subprocess as subprocess
  8. import asyncio
  9. from watchfiles import Change, awatch, watch
  10. from termcolor import colored
  11. from datetime import datetime
  12. import orjson
  13. import os
  14. import tempfile
  15. from tests_config import sql_parser_tests
  16. async def run_and_output(
  17. *args: str, timeout=5
  18. ) -> tuple[bytes, bytes]:
  19. p = await subprocess.create_subprocess_exec(
  20. *args,
  21. stdout=subprocess.PIPE,
  22. stderr=subprocess.PIPE,
  23. )
  24. stdout, stderr = await asyncio.wait_for(p.communicate(), timeout=timeout)
  25. return stdout, stderr
  26. async def rebuild() -> bool:
  27. stdout, _ = await run_and_output('xmake')
  28. if b"error" in stdout:
  29. print(stdout.decode("utf-8"))
  30. print(datetime.now(), "-" * 40)
  31. return False
  32. else:
  33. return True
  34. async def assert_sql(sql: str, expected: dict):
  35. stdout, stderr = await run_and_output('xmake', 'run', "sql-parser", sql)
  36. if b"error" in stdout:
  37. print(stdout.decode("utf-8"))
  38. print(datetime.now(), "-" * 40)
  39. print(f'other: {colored(stderr.decode("utf-8"), "yellow")}')
  40. assert False, "sql-parser error"
  41. try:
  42. output = orjson.loads(stdout)
  43. except Exception as e:
  44. output = {"error": e, "output": stdout.decode("utf-8")}
  45. open("/tmp/temp/test.py", "wb").write(
  46. f'"{sql}"\n\n'.encode("utf-8")
  47. + orjson.dumps(output, option=orjson.OPT_INDENT_2)
  48. + (b"\n\n" + stderr).replace(b"\n", b"\n# ")
  49. )
  50. assert (
  51. output == expected
  52. ), f"""{colored("sql-parser error", "red")}
  53. input: {colored(sql, "yellow")}
  54. expect: {colored(expected, "green")}
  55. actual: {colored(output, "red")}
  56. other: {colored(stderr.decode("utf-8"), "yellow")}
  57. """
  58. async def assert_sqls():
  59. for sql, excepted in sql_parser_tests:
  60. await assert_sql(sql, excepted)
  61. async def on_parser_modified():
  62. print(datetime.now(), colored("run parser tests...", "yellow"))
  63. try:
  64. await assert_sqls()
  65. except Exception as e:
  66. print(e)
  67. else:
  68. print(datetime.now(), colored("all parser tests right!", "green"))
  69. async def on_checker_modified():
  70. print(datetime.now(), colored("run checker tests...", "yellow"))
  71. stdout, stderr = await run_and_output('xmake', 'run', "sql-checker", "-f", "test.cpp", "-g", "2")
  72. print(stdout.decode("utf-8"))
  73. print(datetime.now(), colored("all checker tests right!", "green"))
  74. async def restart():
  75. async for _ in awatch(__file__):
  76. print("restart")
  77. os.execl("/bin/python", Path(__file__).as_posix(), Path(__file__).as_posix())
  78. async def watch_parser():
  79. async for changes in awatch("./src/parser.y", "./src/parser.l"):
  80. if await rebuild():
  81. await asyncio.wait_for(on_parser_modified(), 10)
  82. async def watch_checker():
  83. async for changes in awatch("./src/checker.cpp", "./src/checker.h"):
  84. if await rebuild():
  85. await on_checker_modified()
  86. async def main():
  87. await asyncio.gather(
  88. restart(),
  89. watch_parser(),
  90. watch_checker(),
  91. on_parser_modified(),
  92. on_checker_modified(),
  93. )
  94. if __name__ == "__main__":
  95. asyncio.run(main())