owenrusk.dev

errands

small jobs the runtime does for the studio.

git clone https://owenrusk.dev/errands.git

errands / tests/test_vault.py -rw-r--r-- · 3082 bytes

 1 import json
 2 import subprocess
 3 import tempfile
 4 import unittest
 5 from pathlib import Path
 6 
 7 from errands import settings, vault
 8 
 9 ITEMS = [
10     {"name": "stillwater api", "login": {"username": "papermoth", "password": "not-a-real-token"}, "notes": None},
11     {"name": "wifi", "login": None, "notes": "office network: see the sticker on the router"},
12     {"name": "stillwater api (old)", "login": {"username": "papermoth", "password": "older"}, "notes": None},
13 ]
14 
15 
16 class FakeBw:
17     def __init__(self):
18         self.calls = []
19         self.stale = set()
20 
21     def __call__(self, args, **kwargs):
22         self.calls.append(args[1:])
23         session = (kwargs.get("env") or {}).get("BW_SESSION")
24         if session in self.stale:
25             raise subprocess.CalledProcessError(1, args, "", "Vault is locked.")
26         if args[1] == "unlock":
27             out = "session-key"
28         elif args[1:3] == ["list", "items"]:
29             out = json.dumps(ITEMS)
30         else:
31             raise AssertionError(args)
32         return subprocess.CompletedProcess(args, 0, stdout=out + "\n", stderr="")
33 
34 
35 class VaultTest(unittest.TestCase):
36     def setUp(self):
37         self.dir = tempfile.TemporaryDirectory()
38         self.state = settings.STATE
39         settings.STATE = Path(self.dir.name)
40         self.bw = FakeBw()
41         self.vault = vault.Vault(self.bw)
42 
43     def tearDown(self):
44         settings.STATE = self.state
45         self.dir.cleanup()
46 
47     def test_exact_name_only(self):
48         self.assertEqual(self.vault.password("stillwater api"), "not-a-real-token")
49         self.assertEqual(self.vault.username("stillwater api"), "papermoth")
50 
51     def test_unlocks_once(self):
52         self.vault.password("stillwater api")
53         self.vault.password("stillwater api")
54         self.assertEqual(sum(1 for call in self.bw.calls if call[0] == "unlock"), 1)
55 
56     def test_session_outlives_the_process(self):
57         self.vault.password("stillwater api")
58         again = vault.Vault(self.bw)
59         again.password("stillwater api")
60         self.assertEqual(sum(1 for call in self.bw.calls if call[0] == "unlock"), 1)
61         self.assertEqual((settings.STATE / "bw-session").stat().st_mode & 0o777, 0o600)
62 
63     def test_looks_in_every_folder(self):
64         self.vault.password("stillwater api")
65         self.assertIn(["list", "items", "--search", "stillwater api"], self.bw.calls)
66 
67     def test_note(self):
68         self.assertEqual(self.vault.note("wifi"), "office network: see the sticker on the router")
69         self.assertEqual(self.vault.note("stillwater api"), "")
70 
71     def test_stale_session(self):
72         self.vault.password("stillwater api")
73         self.bw.stale.add("session-key")
74         with self.assertRaises(subprocess.CalledProcessError):
75             # the fake hands out the same key, so the second try fails too and gives up.
76             self.vault.password("stillwater api")
77         self.assertEqual(sum(1 for call in self.bw.calls if call[0] == "unlock"), 2)
78 
79     def test_missing(self):
80         with self.assertRaises(LookupError):
81             self.vault.password("nothing like it")