diff --git a/artiq/test/test_client.py b/artiq/test/test_client.py new file mode 100644 index 000000000..f3110d150 --- /dev/null +++ b/artiq/test/test_client.py @@ -0,0 +1,91 @@ +"""Tests for artiq_client functionality""" + +import subprocess +import sys +import os +import unittest +from tempfile import TemporaryDirectory +from pygit2 import init_repository, Signature + +EXPERIMENT_CONTENT = """ +from artiq.experiment import * +class EmptyExperiment(EnvExperiment): + def build(self): + pass + def run(self): + print("test content") +""" + +DDB_CONTENT = """ +device_db = {} +""" + + +def get_env(): + env = os.environ.copy() + env["PYTHONUNBUFFERED"] = "1" + return env + + +class TestClient(unittest.TestCase): + def setUp(self): + self.tmp_dir = TemporaryDirectory(prefix="test") + self.tmp_empty_dir = TemporaryDirectory(prefix="empty_repo") + self.exp_name = "experiment.py" + self.exp_path = os.path.join(self.tmp_dir.name, self.exp_name) + self.device_db_path = os.path.join(self.tmp_dir.name, "device_db.py") + with open(self.exp_path, "w") as f: + f.write(EXPERIMENT_CONTENT) + with open(self.device_db_path, "w") as f: + f.write(DDB_CONTENT) + + def start_master(self, *args): + self.master = subprocess.Popen([sys.executable, "-m", "artiq.frontend.artiq_master", "--device-db", + self.device_db_path, *args], encoding="utf8", env=get_env(), + text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + while self.master.stdout.readline().strip() != "ARTIQ master is now ready.": + pass + + def check_and_terminate_master(self): + while not ("test content" in self.master.stdout.readline()): + pass + self.run_client("terminate") + self.assertEqual(self.master.wait(), 0) + self.master.stdout.close() + + @staticmethod + def run_client(*args): + subprocess.run([sys.executable, "-m", "artiq.frontend.artiq_client", *args], check=True, + capture_output=True, env=get_env(), text=True, encoding="utf8").check_returncode() + + def test_submit_outside_repo(self): + self.start_master("-r", self.tmp_empty_dir.name) + self.run_client("submit", self.exp_path) + self.check_and_terminate_master() + + def test_submit_by_content(self): + self.start_master("-r", self.tmp_empty_dir.name) + self.run_client("submit", self.exp_path, "--content") + self.check_and_terminate_master() + + def test_submit_by_file_repo(self): + self.start_master("-r", self.tmp_dir.name) + self.run_client("submit", self.exp_name, "-R") + self.check_and_terminate_master() + + def test_submit_by_git_repo(self): + repo = init_repository(self.tmp_dir.name) + repo.index.add_all() + repo.index.write() + tree = repo.index.write_tree() + signature = Signature("Test", "test@example.com") + commit_msg = "Commit message" + repo.create_commit("HEAD", signature, signature, commit_msg, tree, []) + + self.start_master("-r", self.tmp_dir.name, "-g") + self.run_client("submit", self.exp_name, "-R") + self.check_and_terminate_master() + + def tearDown(self): + self.tmp_dir.cleanup() + self.tmp_empty_dir.cleanup() diff --git a/flake.nix b/flake.nix index 2b2ae17fe..2d28f6079 100644 --- a/flake.nix +++ b/flake.nix @@ -144,7 +144,9 @@ ]; # FIXME: automatically propagate lld_11 llvm_11 dependencies - checkInputs = [ pkgs.lld_11 pkgs.llvm_11 libartiq-support pkgs.lit outputcheck ]; + # cacert is required in the check stage only, as certificates are to be + # obtained from system elsewhere + checkInputs = [ pkgs.lld_11 pkgs.llvm_11 libartiq-support pkgs.lit outputcheck pkgs.cacert ]; checkPhase = '' python -m unittest discover -v artiq.test