From ba28b16bc3615df0ba6493bad227a75b2f9a64f6 Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 31 Oct 2025 12:57:25 -0500 Subject: [PATCH 1/5] Fix some annoyances with the smoketests --- smoketests/__init__.py | 7 +++++-- smoketests/__main__.py | 18 +++++++++++++----- smoketests/config.toml | 1 - smoketests/tests/replication.py | 15 ++++++--------- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/smoketests/__init__.py b/smoketests/__init__.py index 71e8cf46576..0880ef52a51 100644 --- a/smoketests/__init__.py +++ b/smoketests/__init__.py @@ -22,7 +22,7 @@ exe_suffix = ".exe" if sys.platform == "win32" else "" SPACETIME_BIN = STDB_DIR / ("target/debug/spacetime" + exe_suffix) TEMPLATE_TARGET_DIR = STDB_DIR / "target/_stdbsmoketests" -STDB_CONFIG = TEST_DIR / "config.toml" +BASE_STDB_CONFIG_PATH = TEST_DIR / "config.toml" # the contents of files for the base smoketest project template TEMPLATE_LIB_RS = open(STDB_DIR / "crates/cli/templates/basic-rust/server/src/lib.rs").read() @@ -50,6 +50,9 @@ # default value can be overridden by `--compose-file` flag COMPOSE_FILE = "./docker-compose.yml" +# this will be initialized by main() +STDB_CONFIG = None + # we need to late-bind the output stream to allow unittests to capture stdout/stderr. class CapturableHandler(logging.StreamHandler): @@ -253,7 +256,7 @@ def publish_module(self, domain=None, *, clear=True, capture_stderr=True, num_re @classmethod def reset_config(cls): - shutil.copy(STDB_CONFIG, cls.config_path) + cls.config_path.write_text(STDB_CONFIG) def fingerprint(self): # Fetch the server's fingerprint; required for `identity list`. diff --git a/smoketests/__main__.py b/smoketests/__main__.py index 54f6897c420..305a75481d2 100644 --- a/smoketests/__main__.py +++ b/smoketests/__main__.py @@ -7,11 +7,12 @@ import re import fnmatch import json -from . import TEST_DIR, SPACETIME_BIN, exe_suffix, build_template_target +from . import TEST_DIR, SPACETIME_BIN, BASE_STDB_CONFIG_PATH, exe_suffix, build_template_target import smoketests import sys import logging import itertools +import tempfile def check_docker(): docker_ps = smoketests.run_cmd("docker", "ps", "--format=json") @@ -112,16 +113,23 @@ def main(): subprocess.Popen(["docker", "logs", "-f", docker_container]) smoketests.HAVE_DOCKER = True + config_file = tempfile.NamedTemporaryFile(mode="w+b", suffix=".toml", buffering=0) + config_file.write(BASE_STDB_CONFIG_PATH.read_bytes()) + config_file.flush() + if args.remote_server is not None: - smoketests.spacetime("--config-path", TEST_DIR / 'config.toml', "server", "edit", "localhost", "--url", args.remote_server, "--yes") + smoketests.spacetime("--config-path", config_file.name, "server", "edit", "localhost", "--url", args.remote_server, "--yes") smoketests.REMOTE_SERVER = True if args.spacetime_login: - smoketests.spacetime("--config-path", TEST_DIR / 'config.toml', "logout") - smoketests.spacetime("--config-path", TEST_DIR / 'config.toml', "login") + smoketests.spacetime("--config-path", config_file.name, "logout") + smoketests.spacetime("--config-path", config_file.name, "login") smoketests.USE_SPACETIME_LOGIN = True else: - smoketests.new_identity(TEST_DIR / 'config.toml') + smoketests.new_identity(config_file.name) + + config_file.seek(0) + smoketests.STDB_CONFIG = config_file.read().decode() if not args.skip_dotnet: smoketests.HAVE_DOTNET = check_dotnet() diff --git a/smoketests/config.toml b/smoketests/config.toml index 3bc097d0d79..9ddb25aaef5 100644 --- a/smoketests/config.toml +++ b/smoketests/config.toml @@ -1,5 +1,4 @@ default_server = "localhost" -spacetimedb_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiJjMjAwMTU3NGEwMjgyNDRjNzZhNTE1MjU1NGMzY2ZjMWJiNmIzNzZlNjY4YmU1Yjg2MzE0MDAyYWRmOTMyYWVlIiwic3ViIjoiYzYwOWJkYjUtMDAyNS00YzZkLWIyZTktOGYyODEwM2IzNWUzIiwiaXNzIjoibG9jYWxob3N0IiwiYXVkIjpbInNwYWNldGltZWRiIl0sImlhdCI6MTc1NjkwOTQ3NywiZXhwIjpudWxsfQ.t6Aobx9fTe6kwvq7H01-2RO7vdK4SjQB7Uw-Lh4Daz0lG43WzIw3oVG_65txqlsFSkpx40wYElByj4jMolutpA" [[server_configs]] nickname = "localhost" diff --git a/smoketests/tests/replication.py b/smoketests/tests/replication.py index 5fd1e24a03b..d23224800fc 100644 --- a/smoketests/tests/replication.py +++ b/smoketests/tests/replication.py @@ -226,20 +226,17 @@ def setUpClass(cls): super().setUpClass() cls.root_config = cls.project_path / "root_config" - def tearDown(self): - # Ensure containers that were brought down during a test are back up. - self.docker.compose("up", "-d") - super().tearDown() - - # TODO: This function seems to run even when `--docker` is not passed, leading to errors unless `-x replication` is passed, due to the docker-related code below. - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - + def setUp(self): self.docker = DockerManager(COMPOSE_FILE) self.root_token = self.docker.generate_root_token() self.cluster = Cluster(self.docker, self) + def tearDown(self): + # Ensure containers that were brought down during a test are back up. + self.docker.compose("up", "-d") + super().tearDown() + def add_me_as_admin(self): """Add the current user as an admin account""" db_owner_id = str(self.spacetime("login", "show")).split()[-1] From 8d19d37c768f66e86cd4ae82e112e18c1dfd8b0e Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 31 Oct 2025 13:05:08 -0500 Subject: [PATCH 2/5] Remove very old test template --- smoketests/tests/template | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 smoketests/tests/template diff --git a/smoketests/tests/template b/smoketests/tests/template deleted file mode 100644 index c773961e631..00000000000 --- a/smoketests/tests/template +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -if [ "$DESCRIBE_TEST" = 1 ] ; then - echo "NO DESCRIPTION FOR THIS TEST!" - exit -fi - -set -euox pipefail - -source "./test/lib.include" - -run_test cargo run identity new --no-domain -IDENT=$(grep IDENTITY "$TEST_OUT" | awk '{print $2}') -EMAIL="$(random_string)@clockworklabs.io" -TOKEN=$(grep token "$HOME/.spacetime/config.toml" | awk '{print $3}' | tr -d \') - -reset_config - -run_test cargo run identity add "$IDENT" "$TOKEN" -run_test cargo run identity set-default "$IDENT" -[ "$IDENT" == "$(grep IDENTITY "$TEST_OUT" | awk '{print $2}')" ] - -reset_config - -run_test cargo run identity new --no-domain - -run_test cargo run publish -ADDRESS="$(grep "reated new database" "$TEST_OUT" | awk 'NF>1{print $NF}')" From 6bc837e0c6f8ea28dec6d838ca1215bfb46548bd Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 31 Oct 2025 13:08:30 -0500 Subject: [PATCH 3/5] Use with block --- smoketests/__main__.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/smoketests/__main__.py b/smoketests/__main__.py index 305a75481d2..33b76ec223b 100644 --- a/smoketests/__main__.py +++ b/smoketests/__main__.py @@ -113,23 +113,23 @@ def main(): subprocess.Popen(["docker", "logs", "-f", docker_container]) smoketests.HAVE_DOCKER = True - config_file = tempfile.NamedTemporaryFile(mode="w+b", suffix=".toml", buffering=0) - config_file.write(BASE_STDB_CONFIG_PATH.read_bytes()) - config_file.flush() - - if args.remote_server is not None: - smoketests.spacetime("--config-path", config_file.name, "server", "edit", "localhost", "--url", args.remote_server, "--yes") - smoketests.REMOTE_SERVER = True - - if args.spacetime_login: - smoketests.spacetime("--config-path", config_file.name, "logout") - smoketests.spacetime("--config-path", config_file.name, "login") - smoketests.USE_SPACETIME_LOGIN = True - else: - smoketests.new_identity(config_file.name) - - config_file.seek(0) - smoketests.STDB_CONFIG = config_file.read().decode() + with tempfile.NamedTemporaryFile(mode="w+b", suffix=".toml", buffering=0) as config_file: + config_file.write(BASE_STDB_CONFIG_PATH.read_bytes()) + config_file.flush() + + if args.remote_server is not None: + smoketests.spacetime("--config-path", config_file.name, "server", "edit", "localhost", "--url", args.remote_server, "--yes") + smoketests.REMOTE_SERVER = True + + if args.spacetime_login: + smoketests.spacetime("--config-path", config_file.name, "logout") + smoketests.spacetime("--config-path", config_file.name, "login") + smoketests.USE_SPACETIME_LOGIN = True + else: + smoketests.new_identity(config_file.name) + + config_file.seek(0) + smoketests.STDB_CONFIG = config_file.read().decode() if not args.skip_dotnet: smoketests.HAVE_DOTNET = check_dotnet() From ee91921ffeb12c7007922d59fd529fc5c025b8cc Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 31 Oct 2025 13:38:14 -0500 Subject: [PATCH 4/5] Fix --- smoketests/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smoketests/__init__.py b/smoketests/__init__.py index 0880ef52a51..a51b29e2cf9 100644 --- a/smoketests/__init__.py +++ b/smoketests/__init__.py @@ -51,7 +51,7 @@ COMPOSE_FILE = "./docker-compose.yml" # this will be initialized by main() -STDB_CONFIG = None +STDB_CONFIG = '' # we need to late-bind the output stream to allow unittests to capture stdout/stderr. class CapturableHandler(logging.StreamHandler): From 87119a03313832db90553eaa19632de8858250c6 Mon Sep 17 00:00:00 2001 From: Noa Date: Mon, 3 Nov 2025 10:50:54 -0600 Subject: [PATCH 5/5] Fix config generation --- smoketests/__init__.py | 3 ++- smoketests/__main__.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/smoketests/__init__.py b/smoketests/__init__.py index a51b29e2cf9..a912e262eef 100644 --- a/smoketests/__init__.py +++ b/smoketests/__init__.py @@ -237,7 +237,6 @@ def log_records(self, n): return list(map(json.loads, logs.splitlines())) def publish_module(self, domain=None, *, clear=True, capture_stderr=True, num_replicas=None, break_clients=False): - print("publishing module", self.publish_module) publish_output = self.spacetime( "publish", *[domain] if domain is not None else [], @@ -256,6 +255,8 @@ def publish_module(self, domain=None, *, clear=True, capture_stderr=True, num_re @classmethod def reset_config(cls): + if not STDB_CONFIG: + raise Exception("config toml has not been initialized yet") cls.config_path.write_text(STDB_CONFIG) def fingerprint(self): diff --git a/smoketests/__main__.py b/smoketests/__main__.py index 33b76ec223b..6161dc5a7aa 100644 --- a/smoketests/__main__.py +++ b/smoketests/__main__.py @@ -13,6 +13,8 @@ import logging import itertools import tempfile +from pathlib import Path +import shutil def check_docker(): docker_ps = smoketests.run_cmd("docker", "ps", "--format=json") @@ -94,13 +96,10 @@ def main(): try: os.symlink(update_bin_name, SPACETIME_BIN) except OSError: - import shutil shutil.copyfile(SPACETIME_BIN.with_name(update_bin_name), SPACETIME_BIN) os.environ["SPACETIME_SKIP_CLIPPY"] = "1" - build_template_target() - if args.docker: # have docker logs print concurrently with the test output if args.compose_file: @@ -113,9 +112,9 @@ def main(): subprocess.Popen(["docker", "logs", "-f", docker_container]) smoketests.HAVE_DOCKER = True - with tempfile.NamedTemporaryFile(mode="w+b", suffix=".toml", buffering=0) as config_file: - config_file.write(BASE_STDB_CONFIG_PATH.read_bytes()) - config_file.flush() + with tempfile.NamedTemporaryFile(mode="w+b", suffix=".toml", buffering=0, delete_on_close=False) as config_file: + with BASE_STDB_CONFIG_PATH.open("rb") as src, config_file.file as dst: + shutil.copyfileobj(src, dst) if args.remote_server is not None: smoketests.spacetime("--config-path", config_file.name, "server", "edit", "localhost", "--url", args.remote_server, "--yes") @@ -128,8 +127,9 @@ def main(): else: smoketests.new_identity(config_file.name) - config_file.seek(0) - smoketests.STDB_CONFIG = config_file.read().decode() + smoketests.STDB_CONFIG = Path(config_file.name).read_text() + + build_template_target() if not args.skip_dotnet: smoketests.HAVE_DOTNET = check_dotnet()