import json import tempfile import threading import unittest import urllib.request import urllib.error from pathlib import Path from spatial_lab.server import make_server from spatial_lab.project import Project,write_json from spatial_lab.examples import small_project class ViewerServer(unittest.TestCase): def setUp(self): self.tmp=tempfile.TemporaryDirectory();self.path=Path(self.tmp.name)/'study.json';write_json(self.path,small_project());self.server=make_server(self.path,0);self.thread=threading.Thread(target=self.server.serve_forever,daemon=True);self.thread.start();self.url=f'http://127.0.0.1:{self.server.server_port}' def tearDown(self):self.server.shutdown();self.server.server_close();self.thread.join();self.tmp.cleanup() def get(self,path):return urllib.request.urlopen(self.url+path) def test_bundle_live_changes_and_etag(self): with self.get('/api/bundle') as r:a=json.load(r);tag=r.headers['ETag'] with self.assertRaises(urllib.error.HTTPError) as caught:urllib.request.urlopen(urllib.request.Request(self.url+'/api/bundle',headers={'If-None-Match':tag})) self.assertEqual(caught.exception.code,304);caught.exception.close() Project(self.path).apply([{'action':'set_parameter','name':'height','value':12}]) with self.get('/api/bundle') as r:b=json.load(r) self.assertNotEqual(a['project_hash'],b['project_hash']) def test_error_does_not_silently_serve_stale_geometry(self): with self.get('/api/bundle') as r:json.load(r) self.path.write_text('{bad json') with self.assertRaises(urllib.error.HTTPError) as caught:self.get('/api/bundle') self.assertEqual(caught.exception.code,422);error=json.load(caught.exception);caught.exception.close();self.assertTrue(error['stale']);self.assertIn('error',error) def test_no_arbitrary_file_access(self): with self.assertRaises(urllib.error.HTTPError) as caught:self.get('/../../etc/passwd') self.assertEqual(caught.exception.code,404);caught.exception.close() def test_viewer_and_download(self): with self.get('/') as r:self.assertIn(b'viewport',r.read()) with self.get('/export.bundle.json') as r:self.assertIn('attachment',r.headers['Content-Disposition']);self.assertEqual(json.load(r)['schema'],'spatial-lab.bundle/1') if __name__=='__main__':unittest.main()