np_app/service/test_account.py
2026-07-26 03:00:54 +08:00

98 lines
4.1 KiB
Python

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()