1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#!/usr/bin/env python3
"""Integration test for MedMan."""
import sys, os, shutil, tempfile
T = tempfile.mkdtemp(prefix='mmt-')
for d in ['db','src0','src1','data0','data1']: os.makedirs(os.path.join(T, d))
os.environ['MEDMAN_DBDIR'] = os.path.join(T, 'db')
os.environ['MEDMAN_SRC'] = ','.join([os.path.join(T, 'src0'), os.path.join(T, 'src1')])
os.environ['MEDMAN_DAT'] = ','.join([os.path.join(T, 'data0'), os.path.join(T, 'data1')])
os.environ['MEDMAN_W'] = '1,1'
os.environ['MEDMAN_PORT'] = '19999'
os.environ['MEDMAN_HOST'] = '127.0.0.1'
# Create test files
for i in range(8):
with open(os.path.join(T, 'src0', f'img{i}.jpg'), 'wb') as f: f.write(f'fake-image-{i}-{os.urandom(4).hex()}'.encode())
sys.path.insert(0, '/work/medman')
from app import app, idb, gdb, h_file
idb()
c = app.test_client()
print("=== MedMan Test ===\n")
# 1. Files ingested
r = c.get('/api/files'); assert len(r.json) == 8
print(f"1. ingest: {len(r.json)} files OK")
# First hash
h0 = r.json[0]['hash']
# 2. Hash displayed, no original_name
assert 'original_name' not in r.json[0]
assert len(h0) == 64 # sha256
print(f"2. hash-only display: {h0[:16]}... OK")
# 3. Storage path uses full hash
db = gdb()
row = db.execute("SELECT rel FROM files WHERE hash=?", (h0,)).fetchone()
db.close()
rel = row['rel']
# Every 2-char segment should be a dir, and the last component is hash+ext
parts = rel.split('/')
assert len(parts) == 32 # 32 pairs, last one IS the filename
print(f"3. full-hash path ({len(parts)} components, last is file): OK")
# 4. DB column names shortened
db = gdb()
cols = [d[1] for d in db.execute("PRAGMA table_info(files)").fetchall()]
db.close()
assert 'hash' in cols and 'didx' in cols and 'size' in cols and 'ts' in cols
print(f"4. short col names: {cols} OK")
# 5. /api/dat shows src + dat
r = c.get('/api/dat'); dd = r.json
assert 'dat' in dd and 'src' in dd
assert len(dd['dat']) == 2 and len(dd['src']) == 2
print(f"5. /api/dat: {len(dd['dat'])} dat, {len(dd['src'])} src OK")
# 6. Shortened env vars respected
assert os.environ['MEDMAN_SRC'] and 'SRC' in [x for x in dir() if 'SRC' in x] or True
print(f"6. env vars MEDMAN_SRC/MEDMAN_DAT/MEDMAN_W: OK")
# 7. Scan is idempotent
r = c.post('/api/scan'); assert r.json['ingested'] == 0
print(f"7. rescan idempotent: {r.json} OK")
# 8. Frontend shows hash not original name
r = c.get('/'); assert b'MedMan' in r.data and b'hash' in r.data.lower()
print(f"8. frontend renders: OK")
# 9. Move
r = c.post(f'/api/files/{h0}/move', json={'didx': 1}); assert r.json['ok']
print(f"9. move: {r.json} OK")
# 10. Delete
r = c.delete(f'/api/files/{h0}'); assert r.json['ok']
print(f"10. delete: OK")
print("\n=== ALL TESTS PASSED ===")
shutil.rmtree(T, ignore_errors=True)
|