mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 21:13:36 +00:00
This is helpful now, but it will also reduce confusion when we extend this tool to also look at openapi schemas.
122 lines
3.1 KiB
Python
Executable File
122 lines
3.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from typing import Any, Callable, Dict, List, Optional
|
|
|
|
import orjson
|
|
|
|
TOOLS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.insert(0, os.path.dirname(TOOLS_DIR))
|
|
ROOT_DIR = os.path.dirname(TOOLS_DIR)
|
|
|
|
EVENTS_JS = "frontend_tests/node_tests/lib/events.js"
|
|
|
|
# check for the venv
|
|
from tools.lib import sanity_check
|
|
|
|
sanity_check.check_venv(__file__)
|
|
|
|
USAGE = """
|
|
|
|
This program reads in fixture data for our
|
|
node tests, and then it validates the fixture
|
|
data with checkers from event_schema.py (which
|
|
are the same Python functions we use to validate
|
|
events in test_events.py).
|
|
|
|
It currently takes no arguments.
|
|
"""
|
|
|
|
parser = argparse.ArgumentParser(usage=USAGE)
|
|
parser.parse_args()
|
|
|
|
# We can eliminate the django dependency in event_schema,
|
|
# but unfortunately it"s coupled to modules like validate.py
|
|
# and topic.py.
|
|
import django
|
|
|
|
os.environ["DJANGO_SETTINGS_MODULE"] = "zproject.test_settings"
|
|
django.setup()
|
|
|
|
from zerver.lib import event_schema
|
|
|
|
SKIP_LIST = [
|
|
# The event_schema checker for user_status is overly strict.
|
|
"user_status__revoke_away",
|
|
"user_status__set_away",
|
|
"user_status__set_status_text",
|
|
]
|
|
|
|
|
|
def get_event_checker(
|
|
event: Dict[str, Any]
|
|
) -> Optional[Callable[[str, Dict[str, Any]], None]]:
|
|
name = "check_" + event["type"]
|
|
if "op" in event:
|
|
name += "_" + event["op"]
|
|
|
|
"""
|
|
In our backend tests we always want check_foo
|
|
to be the "main" API, but often _check_foo actually
|
|
conforms to validator name/event pattern better
|
|
than check_foo (which may layer on some more custom
|
|
checks). We can clean that up eventually, but now
|
|
we just work around it here in this younger tooling.
|
|
"""
|
|
for n in ["_" + name, name]:
|
|
if hasattr(event_schema, n):
|
|
return getattr(event_schema, n)
|
|
return None
|
|
|
|
|
|
def check_event(name: str, event: Dict[str, Any]) -> None:
|
|
event["id"] = 1
|
|
checker = get_event_checker(event)
|
|
if checker is not None:
|
|
try:
|
|
checker(name, event)
|
|
except AssertionError:
|
|
print(f"\n{EVENTS_JS} has bad data for {name}:\n\n")
|
|
raise
|
|
else:
|
|
print(f"NEED SCHEMA: {name}")
|
|
|
|
|
|
def read_fixtures() -> Dict[str, Any]:
|
|
cmd = [
|
|
"node",
|
|
os.path.join(TOOLS_DIR, "node_lib/dump_fixtures.js"),
|
|
]
|
|
schema = subprocess.check_output(cmd)
|
|
return orjson.loads(schema)
|
|
|
|
|
|
def verify_fixtures_are_sorted(names: List[str]) -> None:
|
|
for i in range(1, len(names)):
|
|
if names[i] < names[i - 1]:
|
|
raise Exception(
|
|
f"""
|
|
Please keep your fixtures in order within
|
|
your events.js file. The following
|
|
key is out of order
|
|
|
|
{names[i]}
|
|
"""
|
|
)
|
|
|
|
|
|
def run() -> None:
|
|
fixtures = read_fixtures()
|
|
verify_fixtures_are_sorted(list(fixtures.keys()))
|
|
for name, event in fixtures.items():
|
|
if name in SKIP_LIST:
|
|
print(f"skip {name}")
|
|
continue
|
|
check_event(name, event)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run()
|