From 06346e19464c376c0c2ca13ef4218559f9df4212 Mon Sep 17 00:00:00 2001 From: JF Date: Tue, 9 Jul 2019 14:56:21 -0700 Subject: added a docker dev environment Signed-off-by: Jan Friedli --- test/test.py | 103 ++++++++++++++++++++++++++++++++++++ test/test_api.py | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 test/test.py create mode 100644 test/test_api.py (limited to 'test') diff --git a/test/test.py b/test/test.py new file mode 100644 index 0000000..34245d9 --- /dev/null +++ b/test/test.py @@ -0,0 +1,103 @@ +import unittest +import tempfile +import shutil +import io +import os + +import main + + +class Mat2WebTestCase(unittest.TestCase): + def setUp(self): + os.environ.setdefault('MAT2_ALLOW_ORIGIN_WHITELIST', 'origin1.gnu origin2.gnu') + app = main.create_app() + self.upload_folder = tempfile.mkdtemp() + app.config.update( + TESTING=True, + UPLOAD_FOLDER=self.upload_folder + ) + self.app = app.test_client() + + def tearDown(self): + shutil.rmtree(self.upload_folder) + + def test_get_root(self): + rv = self.app.get('/') + self.assertIn(b'mat2-web', rv.data) + + def test_check_mimetypes(self): + rv = self.app.get('/') + self.assertIn(b'.torrent', rv.data) + self.assertIn(b'.ods', rv.data) + + def test_get_download_dangerous_file(self): + rv = self.app.get('/download/1337/\..\filename') + self.assertEqual(rv.status_code, 302) + + def test_get_download_without_key_file(self): + rv = self.app.get('/download/non_existant') + self.assertEqual(rv.status_code, 404) + + def test_get_download_nonexistant_file(self): + rv = self.app.get('/download/1337/non_existant') + self.assertEqual(rv.status_code, 302) + + def test_get_upload_without_file(self): + rv = self.app.post('/') + self.assertEqual(rv.status_code, 302) + + def test_get_upload_empty_file(self): + rv = self.app.post('/', + data=dict( + file=(io.BytesIO(b""), 'test.pdf'), + ), follow_redirects=False) + self.assertEqual(rv.status_code, 302) + + def test_get_upload_empty_file_redir(self): + rv = self.app.post('/', + data=dict( + file=(io.BytesIO(b""), 'test.pdf'), + ), follow_redirects=True) + self.assertIn(b'The type application/pdf is not supported', + rv.data) + self.assertEqual(rv.status_code, 200) + + def test_get_upload_no_file_name(self): + rv = self.app.post('/', + data=dict( + file=(io.BytesIO(b"aaa")), + ), follow_redirects=True) + self.assertIn(b'No file part', rv.data) + self.assertEqual(rv.status_code, 200) + + def test_get_upload_harmless_file(self): + rv = self.app.post('/', + data=dict( + file=(io.BytesIO(b"Some text"), 'test.txt'), + ), follow_redirects=True) + self.assertIn(b'/download/4c2e9e6da31a64c70623619c449a040968cdbea85945bf384fa30ed2d5d24fa3/test.cleaned.txt', rv.data) + self.assertEqual(rv.status_code, 200) + self.assertNotIn('Access-Control-Allow-Origin', rv.headers) + + rv = self.app.get('/download/4c2e9e6da31a64c70623619c449a040968cdbea85945bf384fa30ed2d5d24fa3/test.cleaned.txt') + self.assertEqual(rv.status_code, 200) + + rv = self.app.get('/download/4c2e9e6da31a64c70623619c449a040968cdbea85945bf384fa30ed2d5d24fa3/test.cleaned.txt') + self.assertEqual(rv.status_code, 302) + + def test_upload_wrong_hash(self): + rv = self.app.post('/', + data=dict( + file=(io.BytesIO(b"Some text"), 'test.txt'), + ), follow_redirects=True) + self.assertIn(b'/download/4c2e9e6da31a64c70623619c449a040968cdbea85945bf384fa30ed2d5d24fa3/test.cleaned.txt', + rv.data) + self.assertEqual(rv.status_code, 200) + + rv = self.app.get('/download/70623619c449a040968cdbea85945bf384fa30ed2d5d24fa3/test.cleaned.txt') + self.assertEqual(rv.status_code, 302) + + +if __name__ == '__main__': + unittest.main() + diff --git a/test/test_api.py b/test/test_api.py new file mode 100644 index 0000000..d913cc4 --- /dev/null +++ b/test/test_api.py @@ -0,0 +1,155 @@ +import unittest +import tempfile +import shutil +import json +import os + +import main + + +class Mat2APITestCase(unittest.TestCase): + def setUp(self): + os.environ.setdefault('MAT2_ALLOW_ORIGIN_WHITELIST', 'origin1.gnu origin2.gnu') + app = main.create_app() + self.upload_folder = tempfile.mkdtemp() + app.config.update( + TESTING=True, + UPLOAD_FOLDER=self.upload_folder + ) + self.app = app.test_client() + + def tearDown(self): + shutil.rmtree(self.upload_folder) + if os.environ.get('MAT2_ALLOW_ORIGIN_WHITELIST'): + del os.environ['MAT2_ALLOW_ORIGIN_WHITELIST'] + + def test_api_upload_valid(self): + request = self.app.post('/api/upload', + data='{"file_name": "test_name.jpg", ' + '"file": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAf' + 'FcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="}', + headers={'content-type': 'application/json'} + ) + self.assertEqual(request.headers['Content-Type'], 'application/json') + self.assertEqual(request.headers['Access-Control-Allow-Origin'], 'origin1.gnu') + self.assertEqual(request.status_code, 200) + + data = json.loads(request.data.decode('utf-8')) + expected = { + 'output_filename': 'test_name.cleaned.jpg', + 'key': '81a541f9ebc0233d419d25ed39908b16f82be26a783f32d56c381559e84e6161', + 'meta': { + 'BitDepth': 8, + 'ColorType': 'RGB with Alpha', + 'Compression': 'Deflate/Inflate', + 'Filter': 'Adaptive', + 'Interlace': 'Noninterlaced' + }, + 'meta_after': {}, + 'download_link': 'http://localhost/api/download/' + '81a541f9ebc0233d419d25ed39908b16f82be26a783f32d56c381559e84e6161/test_name.cleaned.jpg' + } + self.assertEqual(data, expected) + + def test_api_upload_missing_params(self): + request = self.app.post('/api/upload', + data='{"file_name": "test_name.jpg"}', + headers={'content-type': 'application/json'} + ) + self.assertEqual(request.headers['Content-Type'], 'application/json') + + self.assertEqual(request.status_code, 400) + error = json.loads(request.data.decode('utf-8'))['message'] + self.assertEqual(error['file'], 'Post parameter is not specified: file') + + request = self.app.post('/api/upload', + data='{"file_name": "test_name.jpg", "file": "invalid base46 string"}', + headers={'content-type': 'application/json'} + ) + self.assertEqual(request.headers['Content-Type'], 'application/json') + + self.assertEqual(request.status_code, 400) + error = json.loads(request.data.decode('utf-8'))['message'] + self.assertEqual(error, 'Failed decoding file: Incorrect padding') + + def test_api_not_supported(self): + request = self.app.post('/api/upload', + data='{"file_name": "test_name.pdf", ' + '"file": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAf' + 'FcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="}', + headers={'content-type': 'application/json'} + ) + self.assertEqual(request.headers['Content-Type'], 'application/json') + self.assertEqual(request.status_code, 415) + + error = json.loads(request.data.decode('utf-8'))['message'] + self.assertEqual(error, 'The type application/pdf is not supported') + + def test_api_supported_extensions(self): + rv = self.app.get('/api/extension') + self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.headers['Content-Type'], 'application/json') + self.assertEqual(rv.headers['Access-Control-Allow-Origin'], 'origin1.gnu') + + extensions = json.loads(rv.data.decode('utf-8')) + self.assertIn('.pot', extensions) + self.assertIn('.asc', extensions) + self.assertIn('.png', extensions) + self.assertIn('.zip', extensions) + + def test_api_cors_not_set(self): + del os.environ['MAT2_ALLOW_ORIGIN_WHITELIST'] + app = main.create_app() + app.config.update( + TESTING=True + ) + app = app.test_client() + + rv = app.get('/api/extension') + self.assertEqual(rv.headers['Access-Control-Allow-Origin'], '*') + + def test_api_cors(self): + rv = self.app.get('/api/extension') + self.assertEqual(rv.headers['Access-Control-Allow-Origin'], 'origin1.gnu') + + rv = self.app.get('/api/extension', headers={'Origin': 'origin2.gnu'}) + self.assertEqual(rv.headers['Access-Control-Allow-Origin'], 'origin2.gnu') + + rv = self.app.get('/api/extension', headers={'Origin': 'origin1.gnu'}) + self.assertEqual(rv.headers['Access-Control-Allow-Origin'], 'origin1.gnu') + + def test_api_download(self): + request = self.app.post('/api/upload', + data='{"file_name": "test_name.jpg", ' + '"file": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAf' + 'FcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="}', + headers={'content-type': 'application/json'} + ) + self.assertEqual(request.status_code, 200) + data = json.loads(request.data.decode('utf-8')) + + request = self.app.get('http://localhost/api/download/' + '81a541f9ebc0233d419d25ed39908b16f82be26a783f32d56c381559e84e6161/test name.cleaned.jpg') + self.assertEqual(request.status_code, 400) + error = json.loads(request.data.decode('utf-8'))['message'] + self.assertEqual(error, 'Insecure filename') + + request = self.app.get('http://localhost/api/download/' + '81a541f9ebc0233d419d25ed39908b16f82be26a783f32d56c381559e84e6161/' + 'wrong_file_name.jpg') + self.assertEqual(request.status_code, 404) + error = json.loads(request.data.decode('utf-8'))['message'] + self.assertEqual(error, 'File not found') + + request = self.app.get('http://localhost/api/download/81a541f9e/test_name.cleaned.jpg') + self.assertEqual(request.status_code, 400) + + error = json.loads(request.data.decode('utf-8'))['message'] + self.assertEqual(error, 'The file hash does not match') + + request = self.app.get(data['download_link']) + self.assertEqual(request.status_code, 200) + + +if __name__ == '__main__': + unittest.main() -- cgit v1.3