import tempfile import time import unittest from pathlib import Path from service.account import AccountStore def user(user_id): return { "user_id": user_id, "username": user_id, "display_name": user_id.title(), "email": f"{user_id}@example.test", "groups": [], } class AccountStoreTest(unittest.TestCase): def setUp(self): self.temporary_directory = tempfile.TemporaryDirectory() self.store = AccountStore(Path(self.temporary_directory.name) / "account.sqlite3") self.alice = user("alice") self.bob = user("bob") self.payload = { "workflow": "analysis", "mode": "tube", "model": {"material": "rna", "celsius": 37, "sodium": 1, "magnesium": 0}, "strands": [{"name": "A", "sequence": "ACGU"}], "complexes_text": "A", "tube": {"max_size": 1}, "compute": ["mfe"], } def tearDown(self): self.temporary_directory.cleanup() def test_jobs_are_private_and_content_round_trips(self): result = {"workflow": "analysis", "complex_results": [{"name": "A"}]} self.store.create_job("job-1", self.alice, self.payload) self.store.update_job("job-1", "success", result=result, elapsed_seconds=1.25) self.assertIsNone(self.store.get_job(self.bob["user_id"], "job-1")) item = self.store.get_job(self.alice["user_id"], "job-1") self.assertEqual(item["payload"], self.payload) self.assertEqual(item["result"], result) self.assertEqual(item["elapsed_seconds"], 1.25) self.assertEqual(self.store.list_jobs("alice")["total"], 1) self.assertEqual(self.store.list_jobs("bob")["total"], 0) def test_share_can_expire_and_be_disabled(self): self.store.create_job("job-2", self.alice, self.payload, status="success", result={"ok": True}) share = self.store.create_share("alice", "job-2") resolved = self.store.resolve_share(share["share_id"]) self.assertEqual(resolved["job_id"], "job-2") self.assertEqual(resolved["result"], {"ok": True}) self.store.update_share("alice", share["share_id"], active=False) self.assertIsNone(self.store.resolve_share(share["share_id"])) self.assertIsNone(self.store.update_share("bob", share["share_id"], active=True)) expiring = self.store.create_share("alice", "job-2", expires_in=1) with self.store._connect() as connection: connection.execute( "UPDATE shares SET expires_at=? WHERE share_id=?", (time.time() - 1, expiring["share_id"]), ) self.assertIsNone(self.store.resolve_share(expiring["share_id"])) def test_running_job_can_be_shared_and_later_exposes_result(self): self.store.create_job("job-running", self.alice, self.payload, status="running") share = self.store.create_share("alice", "job-running") resolved = self.store.resolve_share(share["share_id"]) self.assertEqual(resolved["job_id"], "job-running") self.assertEqual(resolved["status"], "running") self.assertIsNone(resolved["result"]) self.store.update_job("job-running", "success", result={"ok": True}, elapsed_seconds=2.5) resolved = self.store.resolve_share(share["share_id"]) self.assertEqual(resolved["status"], "success") self.assertEqual(resolved["result"], {"ok": True}) self.assertEqual(resolved["elapsed_seconds"], 2.5) self.assertIsNone(self.store.update_share("bob", share["share_id"], active=False)) self.store.update_share("alice", share["share_id"], active=False) self.assertIsNone(self.store.resolve_share(share["share_id"])) def test_active_job_cannot_be_deleted(self): self.store.create_job("job-3", self.alice, self.payload) with self.assertRaises(ValueError): self.store.delete_job("alice", "job-3") self.store.update_job("job-3", "canceled", error={"message": "canceled"}) self.assertTrue(self.store.delete_job("alice", "job-3")) if __name__ == "__main__": unittest.main()