升级 NUPACK 4.1 并支持混合材料设计
This commit is contained in:
parent
5daa60a464
commit
c6189d857d
33 changed files with 5830 additions and 466 deletions
|
|
@ -3,7 +3,7 @@ import time
|
|||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from service.account import AccountStore
|
||||
from service.account import AccountStore, DEFAULT_TRASH_RETENTION_SECONDS
|
||||
|
||||
|
||||
def user(user_id):
|
||||
|
|
@ -48,7 +48,7 @@ class AccountStoreTest(unittest.TestCase):
|
|||
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):
|
||||
def test_share_can_expire_and_be_deleted(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"])
|
||||
|
|
@ -57,6 +57,7 @@ class AccountStoreTest(unittest.TestCase):
|
|||
|
||||
self.store.update_share("alice", share["share_id"], active=False)
|
||||
self.assertIsNone(self.store.resolve_share(share["share_id"]))
|
||||
self.assertIsNone(self.store.get_share_for_owner("alice", 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)
|
||||
|
|
@ -67,6 +68,13 @@ class AccountStoreTest(unittest.TestCase):
|
|||
)
|
||||
self.assertIsNone(self.store.resolve_share(expiring["share_id"]))
|
||||
|
||||
def test_create_share_reuses_existing_active_link(self):
|
||||
self.store.create_job("job-share-once", self.alice, self.payload, status="success")
|
||||
first = self.store.create_share("alice", "job-share-once", expires_in=604800)
|
||||
second = self.store.create_share("alice", "job-share-once", expires_in=604800)
|
||||
self.assertEqual(first["share_id"], second["share_id"])
|
||||
self.assertEqual(len(self.store.list_shares("alice")), 1)
|
||||
|
||||
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")
|
||||
|
|
@ -93,6 +101,86 @@ class AccountStoreTest(unittest.TestCase):
|
|||
self.store.update_job("job-3", "canceled", error={"message": "canceled"})
|
||||
self.assertTrue(self.store.delete_job("alice", "job-3"))
|
||||
|
||||
def test_deleted_job_moves_to_trash_and_deletes_shares(self):
|
||||
self.assertEqual(self.store.trash_retention_seconds(), DEFAULT_TRASH_RETENTION_SECONDS)
|
||||
self.store.create_job("job-trash", self.alice, self.payload, status="success", result={"ok": True})
|
||||
share = self.store.create_share("alice", "job-trash")
|
||||
|
||||
self.assertTrue(self.store.delete_job("alice", "job-trash"))
|
||||
self.assertIsNone(self.store.get_job("alice", "job-trash"))
|
||||
self.assertEqual(self.store.list_jobs("alice")["total"], 0)
|
||||
self.assertIsNone(self.store.resolve_share(share["share_id"]))
|
||||
self.assertIsNone(self.store.get_share_for_owner("alice", share["share_id"]))
|
||||
self.assertEqual(self.store.list_shares("alice"), [])
|
||||
|
||||
trash = self.store.list_all_jobs({"deleted": "1"})
|
||||
self.assertEqual(trash["total"], 1)
|
||||
self.assertEqual(trash["items"][0]["job_id"], "job-trash")
|
||||
self.assertIsNotNone(trash["items"][0]["deleted_at"])
|
||||
self.assertAlmostEqual(
|
||||
trash["items"][0]["purge_after"] - trash["items"][0]["deleted_at"],
|
||||
DEFAULT_TRASH_RETENTION_SECONDS,
|
||||
delta=1,
|
||||
)
|
||||
|
||||
def test_initialize_removes_legacy_shares_for_trashed_jobs(self):
|
||||
self.store.create_job("job-legacy", self.alice, self.payload, status="success")
|
||||
share = self.store.create_share("alice", "job-legacy")
|
||||
with self.store._connect() as connection:
|
||||
connection.execute(
|
||||
"UPDATE jobs SET deleted_at=?,purge_after=? WHERE job_id=?",
|
||||
(time.time(), time.time() + 86400, "job-legacy"),
|
||||
)
|
||||
self.store._initialized = False
|
||||
self.store.initialize()
|
||||
self.assertIsNone(self.store.get_share_for_owner("alice", share["share_id"]))
|
||||
self.assertEqual(self.store.list_shares("alice"), [])
|
||||
|
||||
def test_restore_and_permanent_delete_complete_trash_lifecycle(self):
|
||||
self.store.create_job("job-live", self.alice, self.payload, status="success")
|
||||
self.assertFalse(self.store.permanently_delete_job("job-live"))
|
||||
|
||||
self.store.create_job("job-restore", self.alice, self.payload, status="success")
|
||||
self.store.delete_job("alice", "job-restore")
|
||||
self.assertTrue(self.store.restore_job("job-restore"))
|
||||
self.assertIsNotNone(self.store.get_job("alice", "job-restore"))
|
||||
self.assertEqual(self.store.list_all_jobs({"deleted": "1"})["total"], 0)
|
||||
|
||||
self.store.delete_job("alice", "job-restore")
|
||||
self.assertTrue(self.store.permanently_delete_job("job-restore"))
|
||||
self.assertFalse(self.store.permanently_delete_job("job-restore"))
|
||||
self.assertIsNone(self.store.get_job("alice", "job-restore", include_deleted=True))
|
||||
|
||||
def test_retention_setting_and_expired_job_purge(self):
|
||||
self.assertEqual(self.store.set_trash_retention_days(3.5), int(3.5 * 86400))
|
||||
self.assertEqual(self.store.trash_retention_seconds(), int(3.5 * 86400))
|
||||
with self.assertRaises(ValueError):
|
||||
self.store.set_trash_retention_days(0)
|
||||
|
||||
self.store.create_job("job-expired", self.alice, self.payload, status="success")
|
||||
self.store.delete_job("alice", "job-expired")
|
||||
with self.store._connect() as connection:
|
||||
connection.execute(
|
||||
"UPDATE jobs SET purge_after=? WHERE job_id=?",
|
||||
(time.time() - 1, "job-expired"),
|
||||
)
|
||||
self.assertEqual(self.store.purge_expired_jobs(), 1)
|
||||
self.assertIsNone(self.store.get_job("alice", "job-expired", include_deleted=True))
|
||||
|
||||
def test_admin_listing_includes_all_users_and_supports_filters(self):
|
||||
self.store.create_job("alice-job", self.alice, self.payload, status="running")
|
||||
bob_payload = {**self.payload, "workflow": "design"}
|
||||
self.store.create_job("bob-job", self.bob, bob_payload, status="success")
|
||||
|
||||
listing = self.store.list_all_jobs({"limit": 10})
|
||||
self.assertEqual(listing["total"], 2)
|
||||
self.assertEqual({item["user_id"] for item in listing["items"]}, {"alice", "bob"})
|
||||
self.assertTrue(all("username" in item for item in listing["items"]))
|
||||
|
||||
filtered = self.store.list_all_jobs({"q": self.bob["email"], "workflow": "design"})
|
||||
self.assertEqual(filtered["total"], 1)
|
||||
self.assertEqual(filtered["items"][0]["job_id"], "bob-job")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue