123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- # Copyright Materialize, Inc. and contributors. All rights reserved.
- #
- # Use of this software is governed by the Business Source License
- # included in the LICENSE file at the root of this repository.
- #
- # As of the Change Date specified in that file, in accordance with
- # the Business Source License, use of this software will be governed
- # by the Apache License, Version 2.0.
- """
- Run SQLancer against Materialize: Automated testing to find logic bugs in
- database systems: https://github.com/sqlancer/sqlancer
- """
- import argparse
- import random
- from threading import Thread
- from materialize import spawn
- from materialize.mzcompose.composition import (
- Composition,
- Service,
- WorkflowArgumentParser,
- )
- from materialize.mzcompose.services.materialized import Materialized
- SERVICES = [
- # Auto-restart so we can keep testing even after we ran into a panic
- Materialized(restart="on-failure", default_replication_factor=2),
- Service(
- "sqlancer",
- {
- "mzbuild": "sqlancer",
- },
- ),
- ]
- def print_logs(container_id: str) -> None:
- spawn.runv(["docker", "logs", "-f", container_id])
- def workflow_default(c: Composition, parser: WorkflowArgumentParser) -> None:
- parser.add_argument("--runtime", default=600, type=int)
- parser.add_argument("--num-tries", default=100000, type=int)
- parser.add_argument("--num-threads", default=4, type=int)
- parser.add_argument("--seed", default=None, type=int)
- parser.add_argument("--qpg", default=True, action=argparse.BooleanOptionalAction)
- parser.add_argument("--oracle", default="NOREC", type=str)
- args = parser.parse_args()
- c.up("materialized")
- c.sql(
- "ALTER SYSTEM SET max_tables TO 1000",
- user="mz_system",
- port=6877,
- )
- c.sql(
- "ALTER SYSTEM SET max_materialized_views TO 1000",
- user="mz_system",
- port=6877,
- )
- seed = args.seed or random.randint(0, 2**31)
- print("--- Run in progress")
- result = c.run(
- "sqlancer",
- "--random-seed",
- f"{seed}",
- "--host",
- "materialized",
- "--port",
- "6875",
- "--username",
- "materialize",
- "--timeout-seconds",
- f"{args.runtime}",
- "--num-tries",
- f"{args.num_tries}",
- "--num-threads",
- f"{args.num_threads}",
- "--qpg-enable",
- f"{args.qpg}",
- "--random-string-generation",
- "ALPHANUMERIC_SPECIALCHAR",
- "materialize",
- "--oracle",
- args.oracle,
- check=False,
- detach=True,
- capture=True,
- )
- container_id = result.stdout.strip()
- # Print logs in a background thread so that we get immediate output in CI,
- # and also when running SQLancer locally
- thread = Thread(target=print_logs, args=(container_id,))
- thread.start()
- # At the same time capture the logs to analyze for finding new issues
- stdout = spawn.capture(["docker", "logs", "-f", container_id])
- in_assertion = False
- for line in stdout.splitlines():
- if line.startswith("--java.lang.AssertionError: "):
- in_assertion = True
- print(f"--- [SQLancer] {line.removeprefix('--java.lang.AssertionError: ')}")
- elif line == "":
- in_assertion = False
- elif in_assertion:
- print(line)
- print(f"--- {result.stdout.splitlines()[-1]}")
|