2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2025-12-17 17:47:13 +00:00
Files
troggle/core/TESTS/test_drawings.py

197 lines
8.0 KiB
Python

import os
import pathlib
import tempfile
from django.test import TestCase
import settings
from troggle.parsers import drawings
from troggle.core.models.survex import DrawingFile
from troggle.core.models.wallets import Wallet
from troggle.core.models.survex import SingleScan
from troggle.core.models.troggle import DataIssue
class DrawingsPathlibTests(TestCase):
def test_load_drawings_creates_expected_entries(self):
with tempfile.TemporaryDirectory() as td:
# create a small tree
p = pathlib.Path(td)
(p / 'one.pdf').write_text('pdf')
(p / 'two.txt').write_text('txt')
sub = p / 'dir'
sub.mkdir()
(sub / 'three.png').write_text('png')
sub2 = p / 'dir2'
sub2.mkdir()
(sub2 / 'abc.th2').write_text('th2')
(sub2 / 'abc.th').write_text('th')
# point the module at our tempdir
settings.DRAWINGS_DATA = td
drawings.load_drawings_files()
# all files should be present
self.assertTrue(DrawingFile.objects.filter(dwgpath='one.pdf').exists())
self.assertTrue(DrawingFile.objects.filter(dwgpath='two.txt').exists())
self.assertTrue(DrawingFile.objects.filter(dwgpath='dir/three.png').exists())
self.assertTrue(DrawingFile.objects.filter(dwgpath='dir2/abc.th2').exists())
self.assertTrue(DrawingFile.objects.filter(dwgpath='dir2/abc.th').exists())
def test_hidden_and_backup_skipped(self):
with tempfile.TemporaryDirectory() as td:
p = pathlib.Path(td)
(p / '.hidden').write_text('hid')
(p / 'file~').write_text('bak')
settings.DRAWINGS_DATA = td
drawings.load_drawings_files()
# Should not import hidden or backup files
self.assertFalse(DrawingFile.objects.filter(dwgpath='.hidden').exists())
self.assertFalse(DrawingFile.objects.filter(dwgpath='file~').exists())
def test_no_extension_file(self):
with tempfile.TemporaryDirectory() as td:
p = pathlib.Path(td)
(p / 'noext').write_text('data')
settings.DRAWINGS_DATA = td
drawings.load_drawings_files()
self.assertTrue(DrawingFile.objects.filter(dwgpath='noext').exists())
def test_git_dir_skipped(self):
with tempfile.TemporaryDirectory() as td:
p = pathlib.Path(td)
g = p / '.git'
g.mkdir()
(g / 'secret.txt').write_text('top secret')
settings.DRAWINGS_DATA = td
drawings.load_drawings_files()
self.assertFalse(DrawingFile.objects.filter(dwgpath='.git/secret.txt').exists())
def test_bulk_create_chunks(self):
# Create more than chunk size files to ensure bulk_create is called in multiple chunks
count = 800
with tempfile.TemporaryDirectory() as td:
p = pathlib.Path(td)
for i in range(count):
(p / f'file{i}.txt').write_text('x')
settings.DRAWINGS_DATA = td
drawings.load_drawings_files()
self.assertEqual(DrawingFile.objects.count(), count)
def test_parse_tunnel_links_wallet_and_scan(self):
# Create a wallet and a singlescan, then ensure parse_tnl_file links them
w = Wallet.objects.create(fpath='x', walletname='2025#20')
ss = SingleScan.objects.create(ffile='x', name='notes.jpg', wallet=w)
df = DrawingFile.objects.create(dwgpath='tst.th', dwgname='tst')
drawings.parse_tnl_file(df, '2025#20/notes.jpg')
self.assertIn(w, df.dwgwallets.all())
self.assertIn(ss, df.scans.all())
def test_findwalletimage_logs_missing_scan(self):
# Wallet exists but no scan inside. Should create a DataIssue
w = Wallet.objects.create(fpath='x', walletname='2026#01')
df = DrawingFile.objects.create(dwgpath='tst2.th2', dwgname='tst2')
drawings.findwalletimage(df, '2026#01/missing.jpg')
di = DataIssue.objects.filter(parser='Therion', message__contains='not actually found')
self.assertTrue(di.exists())
def test_drawing_reference_multiple_creates_dataissue(self):
df1 = DrawingFile.objects.create(dwgpath='ref1', dwgname='shared')
df2 = DrawingFile.objects.create(dwgpath='ref2', dwgname='shared')
dfmain = DrawingFile.objects.create(dwgpath='main', dwgname='main')
drawings.parse_tnl_file(dfmain, 'shared')
di = DataIssue.objects.filter(parser='Tunnel', message__contains="files named 'shared'")
self.assertTrue(di.exists())
def test_drawing_reference_single_no_dataissue(self):
DrawingFile.objects.create(dwgpath='ref3', dwgname='unique')
dfmain = DrawingFile.objects.create(dwgpath='main2', dwgname='main2')
drawings.parse_tnl_file(dfmain, 'unique')
di = DataIssue.objects.filter(parser='Tunnel', message__contains="files named 'unique'")
self.assertFalse(di.exists())
def test_extension_helpers_and_constants(self):
# Helpers should recognise supported/image suffixes (case-insensitive)
self.assertTrue(drawings._is_supported_suffix('.png'))
self.assertTrue(drawings._is_supported_suffix('.xml'))
self.assertTrue(drawings._is_supported_suffix('.TH'))
self.assertFalse(drawings._is_supported_suffix(''))
self.assertFalse(drawings._is_supported_suffix('.exe'))
self.assertTrue(drawings._is_image_suffix('.png'))
self.assertTrue(drawings._is_image_suffix('.JPEG'))
self.assertFalse(drawings._is_image_suffix('.xml'))
self.assertFalse(drawings._is_image_suffix(''))
# Constants should include expected values and be consistent
self.assertIn('.png', drawings.IMAGE_EXTS)
self.assertEqual(set(drawings.IMAGE_LIKE_EXTS), set(drawings.IMAGE_EXTS))
self.assertIn('.th', drawings.SUPPORTED_EXTENSIONS)
self.assertIn('.png', drawings.SUPPORTED_EXTENSIONS)
def test_fetch_drawingfiles_by_paths_chunks(self):
# Create more items than typical SQLite parameter limit to ensure chunking
count = 1200
rel_paths = []
objs = []
for i in range(count):
rel = f'bigdir/file{i}.txt'
rel_paths.append(rel)
objs.append(DrawingFile(dwgpath=rel, dwgname=f'name{i}'))
# Bulk create them efficiently
DrawingFile.objects.bulk_create(objs)
mapping = drawings.fetch_drawingfiles_by_paths(rel_paths, chunk_size=500)
self.assertEqual(len(mapping), count)
# Spot-check a few entries
self.assertIn('bigdir/file0.txt', mapping)
self.assertIn(f'bigdir/file{count-1}.txt', mapping)
def test_assign_wallets_for_model_assigns_and_returns_wallets(self):
w = Wallet.objects.create(fpath='x', walletname='2025#20')
df = DrawingFile.objects.create(dwgpath='assign.th', dwgname='assign')
res = drawings._assign_wallets_for_model(df, '2025#20', parser_label='AssignTest')
self.assertTrue(res)
self.assertIn(w, df.dwgwallets.all())
def test_assign_wallets_for_model_creates_dataissue_on_missing(self):
df = DrawingFile.objects.create(dwgpath='missing.th', dwgname='missing')
drawings._assign_wallets_for_model(df, 'NONEXISTENT', parser_label='AssignMissing')
di = DataIssue.objects.filter(parser='AssignMissing', message__contains='not found')
self.assertTrue(di.exists())
def test_assign_wallets_for_model_records_dataissue_on_exception(self):
# Patch Wallet.objects.filter to raise an exception
from unittest.mock import patch
df = DrawingFile.objects.create(dwgpath='err.th', dwgname='err')
with patch('troggle.core.models.wallets.Wallet.objects.filter') as mock_filter:
mock_filter.side_effect = RuntimeError('boom')
drawings._assign_wallets_for_model(df, 'WHATEVER', parser_label='AssignError')
di = DataIssue.objects.filter(parser='AssignError', message__contains='Exception')
self.assertTrue(di.exists())