beeref/tests/fileio/test_sql.py

322 lines
12 KiB
Python
Raw Normal View History

2021-03-26 18:55:08 +00:00
import os.path
import tempfile
2021-03-26 18:55:08 +00:00
from unittest.mock import MagicMock, patch
from PyQt6 import QtGui
import pytest
2021-03-26 18:55:08 +00:00
from beeref.fileio.errors import BeeFileIOError
2021-03-26 18:55:08 +00:00
from beeref.fileio.sql import SQLiteIO
from beeref.items import BeePixmapItem
from beeref.scene import BeeGraphicsScene
from ..base import BeeTestCase
class SQLiteIOTestCase(BeeTestCase):
def setUp(self):
self.scene_mock = MagicMock()
self.io = SQLiteIO(':memory:', self.scene_mock, create_new=True)
2021-03-26 18:55:08 +00:00
def test_ẁrite_meta_application_id(self):
self.io.write_meta()
result = self.io.fetchone('PRAGMA application_id')
assert result[0] == SQLiteIO.APPLICATION_ID
def test_ẁrite_meta_user_version(self):
self.io.write_meta()
result = self.io.fetchone('PRAGMA user_version')
assert result[0] == SQLiteIO.USER_VERSION
def test_ẁrite_meta_foreign_keys(self):
self.io.write_meta()
result = self.io.fetchone('PRAGMA foreign_keys')
assert result[0] == 1
def test_create_schema_on_new_when_create_new(self):
self.io.create_schema_on_new()
result = self.io.fetchone(
'SELECT COUNT(*) FROM sqlite_master '
'WHERE type="table" AND name NOT LIKE "sqlite_%"')
assert result[0] == 2
self.scene_mock.clear_save_ids.assert_called_once()
2021-03-26 18:55:08 +00:00
def test_create_schema_on_new_when_not_create_new(self):
self.io.create_new = False
self.io.create_schema_on_new()
result = self.io.fetchone(
'SELECT COUNT(*) FROM sqlite_master '
'WHERE type="table" AND name NOT LIKE "sqlite_%"')
assert result[0] == 0
self.scene_mock.clear_save_ids.assert_not_called()
2021-03-26 18:55:08 +00:00
def test_readonly_doesnt_allow_write(self):
scene = BeeGraphicsScene(None)
with tempfile.TemporaryDirectory() as dirname:
fname = os.path.join(dirname, 'test.bee')
with open(fname, 'w') as f:
f.write('foobar')
io = SQLiteIO(fname, scene, readonly=True)
with pytest.raises(BeeFileIOError) as exinfo:
io.write()
assert exinfo.value.filename == fname
with open(fname, 'r') as f:
f.read() == 'foobar'
2021-03-26 18:55:08 +00:00
class SQLiteIOWriteTestCase(BeeTestCase):
def setUp(self):
self.scene = BeeGraphicsScene(None)
self.io = SQLiteIO(':memory:', self.scene, create_new=True)
def test_calls_create_schema_on_new(self):
with patch.object(self.io, 'create_schema_on_new') as crmock:
with patch.object(self.io, 'fetchall'):
with patch.object(self.io, 'exmany'):
self.io.write()
crmock.assert_called_once()
def test_calls_write_meta(self):
with patch.object(self.io, 'write_meta') as metamock:
with patch.object(self.io, 'fetchall'):
with patch.object(self.io, 'exmany'):
self.io.write()
metamock.assert_called_once()
def test_inserts_new_item(self):
2021-03-28 09:06:04 +00:00
item = BeePixmapItem(QtGui.QImage(), filename='bee.jpg')
self.scene.addItem(item)
2021-03-26 18:55:08 +00:00
item.setScale(1.3)
item.setPos(44, 55)
item.setZValue(0.22)
2021-04-05 17:07:31 +00:00
item.setRotation(33)
2021-04-10 17:35:47 +00:00
item.do_flip()
2021-03-26 18:55:08 +00:00
item.pixmap_to_bytes = MagicMock(return_value=b'abc')
self.io.write()
assert item.save_id == 1
result = self.io.fetchone(
2021-04-10 17:35:47 +00:00
'SELECT x, y, z, scale, rotation, flip, filename, type, '
2021-03-28 09:06:04 +00:00
'sqlar.data, sqlar.name '
2021-03-26 18:55:08 +00:00
'FROM items '
2021-03-27 14:37:03 +00:00
'INNER JOIN sqlar on sqlar.item_id = items.id')
2021-03-26 18:55:08 +00:00
assert result[0] == 44.0
assert result[1] == 55.0
assert result[2] == 0.22
assert result[3] == 1.3
2021-04-05 17:07:31 +00:00
assert result[4] == 33
2021-04-10 17:35:47 +00:00
assert result[5] == -1
assert result[6] == 'bee.jpg'
assert result[7] == 'pixmap'
assert result[8] == b'abc'
assert result[9] == '0001-bee.png'
2021-03-28 09:06:04 +00:00
def test_inserts_new_item_without_filename(self):
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
self.io.write()
assert item.save_id == 1
result = self.io.fetchone(
'SELECT filename, sqlar.name FROM items '
'INNER JOIN sqlar on sqlar.item_id = items.id')
assert result[0] is None
assert result[1] == '0001.png'
2021-03-26 18:55:08 +00:00
def test_updates_existing_item(self):
item = BeePixmapItem(QtGui.QImage(), filename='bee.png')
self.scene.addItem(item)
2021-03-26 18:55:08 +00:00
item.setScale(1.3)
item.setPos(44, 55)
item.setZValue(0.22)
2021-04-05 17:07:31 +00:00
item.setRotation(33)
2021-03-26 18:55:08 +00:00
item.save_id = 1
item.pixmap_to_bytes = MagicMock(return_value=b'abc')
self.io.write()
item.setScale(0.7)
item.setPos(20, 30)
item.setZValue(0.33)
2021-04-05 17:07:31 +00:00
item.setRotation(100)
2021-04-10 17:35:47 +00:00
item.do_flip()
2021-03-26 18:55:08 +00:00
item.filename = 'new.png'
item.pixmap_to_bytes.return_value = b'updated'
self.io.create_new = False
self.io.write()
assert self.io.fetchone('SELECT COUNT(*) from items') == (1,)
result = self.io.fetchone(
2021-04-10 17:35:47 +00:00
'SELECT x, y, z, scale, rotation, flip, filename, sqlar.data '
2021-03-26 18:55:08 +00:00
'FROM items '
2021-03-27 14:37:03 +00:00
'INNER JOIN sqlar on sqlar.item_id = items.id')
2021-03-26 18:55:08 +00:00
assert result[0] == 20
assert result[1] == 30
assert result[2] == 0.33
assert result[3] == 0.7
2021-04-05 17:07:31 +00:00
assert result[4] == 100
2021-04-10 17:35:47 +00:00
assert result[5] == -1
assert result[6] == 'new.png'
assert result[7] == b'abc'
2021-03-26 18:55:08 +00:00
def test_removes_nonexisting_item(self):
item = BeePixmapItem(QtGui.QImage(), filename='bee.png')
item.setScale(1.3)
item.setPos(44, 55)
self.scene.addItem(item)
self.io.write()
self.scene.removeItem(item)
self.io.create_new = False
self.io.write()
assert self.io.fetchone('SELECT COUNT(*) from items') == (0,)
2021-03-27 14:37:03 +00:00
assert self.io.fetchone('SELECT COUNT(*) from sqlar') == (0,)
2021-03-26 18:55:08 +00:00
def test_update_recovers_from_borked_file(self):
item = BeePixmapItem(QtGui.QImage(), filename='bee.png')
self.scene.addItem(item)
with tempfile.TemporaryDirectory() as dirname:
fname = os.path.join(dirname, 'test.bee')
with open(fname, 'w') as f:
f.write('foobar')
2021-03-26 18:55:08 +00:00
io = SQLiteIO(fname, self.scene, create_new=False)
io.write()
result = io.fetchone('SELECT COUNT(*) FROM items')
assert result[0] == 1
def test_updates_progress(self):
2021-04-13 15:08:23 +00:00
worker = MagicMock(canceled=False)
io = SQLiteIO(':memory:', self.scene, create_new=True,
2021-04-13 15:08:23 +00:00
worker=worker)
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
io.write()
2021-04-13 15:08:23 +00:00
worker.begin_processing.emit.assert_called_once_with(1)
worker.progress.emit.assert_called_once_with(0)
worker.finished.emit.assert_called_once_with(':memory:', [])
def test_canceled(self):
worker = MagicMock(canceled=True)
io = SQLiteIO(':memory:', self.scene, create_new=True,
worker=worker)
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
io.write()
worker.begin_processing.emit.assert_called_once_with(2)
worker.progress.emit.assert_called_once_with(0)
worker.finished.emit.assert_called_once_with(':memory:', [])
class SQLiteIOReadTestCase(BeeTestCase):
2021-03-26 18:55:08 +00:00
def setUp(self):
self.scene = BeeGraphicsScene(None)
def test_reads_readonly(self):
with tempfile.TemporaryDirectory() as dirname:
fname = os.path.join(dirname, 'test.bee')
io = SQLiteIO(fname, self.scene, create_new=True)
io.create_schema_on_new()
2021-04-05 17:07:31 +00:00
io.ex('INSERT INTO items '
2021-04-10 17:35:47 +00:00
'(type, x, y, z, scale, rotation, flip, filename) '
'VALUES (?, ?, ?, ?, ?, ?, ?, ?) ',
('pixmap', 22.2, 33.3, 0.22, 3.4, 45, -1, 'bee.png'))
io.ex('INSERT INTO sqlar (item_id, data) VALUES (?, ?)',
2021-03-28 09:06:04 +00:00
(1, self.imgdata3x3))
io.connection.commit()
del(io)
io = SQLiteIO(fname, self.scene, readonly=True)
io.read()
2021-04-13 15:08:23 +00:00
item, selected = self.scene.items_to_add.get()
assert selected is False
assert item.save_id == 1
assert item.pos().x() == 22.2
assert item.pos().y() == 33.3
assert item.zValue() == 0.22
2021-03-28 20:45:16 +00:00
assert item.scale() == 3.4
2021-04-05 17:07:31 +00:00
assert item.rotation() == 45
2021-04-10 17:35:47 +00:00
assert item.flip() == -1
assert item.filename == 'bee.png'
assert item.width == 3
assert item.height == 3
2021-04-13 15:08:23 +00:00
assert self.scene.items_to_add.empty() is True
def test_updates_progress(self):
2021-04-13 15:08:23 +00:00
worker = MagicMock(canceled=False)
io = SQLiteIO(':memory:', self.scene, create_new=True,
2021-04-13 15:08:23 +00:00
worker=worker)
io.create_schema_on_new()
io.ex('INSERT INTO items (type, x, y, z, scale, filename) '
'VALUES (?, ?, ?, ?, ?, ?) ',
('pixmap', 0, 0, 0, 1, 'bee.png'))
io.ex('INSERT INTO sqlar (item_id, data) VALUES (?, ?)', (1, b''))
io.connection.commit()
io.read()
2021-04-13 15:08:23 +00:00
worker.begin_processing.emit.assert_called_once_with(1)
worker.progress.emit.assert_called_once_with(0)
worker.finished.emit.assert_called_once_with(':memory:', [])
def test_canceled(self):
worker = MagicMock(canceled=True)
io = SQLiteIO(':memory:', self.scene, create_new=True,
worker=worker)
io.create_schema_on_new()
io.ex('INSERT INTO items (type, x, y, z, scale, filename) '
'VALUES (?, ?, ?, ?, ?, ?) ',
('pixmap', 0, 0, 0, 1, 'bee.png'))
io.ex('INSERT INTO sqlar (item_id, data) VALUES (?, ?)', (1, b''))
io.ex('INSERT INTO items (type, x, y, z, scale, filename) '
'VALUES (?, ?, ?, ?, ?, ?) ',
('pixmap', 50, 50, 0, 1, 'bee2.png'))
io.ex('INSERT INTO sqlar (item_id, data) VALUES (?, ?)', (1, b''))
io.connection.commit()
io.read()
worker.begin_processing.emit.assert_called_once_with(2)
worker.progress.emit.assert_called_once_with(0)
worker.finished.emit.assert_called_once_with('', [])
def test_raises_error_when_file_borked(self):
with tempfile.TemporaryDirectory() as dirname:
fname = os.path.join(dirname, 'test.bee')
with open(fname, 'w') as f:
f.write('foobar')
io = SQLiteIO(fname, self.scene, readonly=True)
with pytest.raises(BeeFileIOError) as exinfo:
io.read()
assert exinfo.value.filename == fname
2021-04-13 15:08:23 +00:00
def test_emits_error_message_when_file_borked(self):
with tempfile.TemporaryDirectory() as dirname:
fname = os.path.join(dirname, 'test.bee')
with open(fname, 'w') as f:
f.write('foobar')
worker = MagicMock()
io = SQLiteIO(fname, self.scene, readonly=True, worker=worker)
io.read()
worker.finished.emit.assert_called_once()
args = worker.finished.emit.call_args_list[0][0]
assert args[0] == ''
assert len(args[1]) == 1
def test_reads_raises_error_when_file_empty(self):
with tempfile.TemporaryDirectory() as dirname:
fname = os.path.join(dirname, 'test.bee')
io = SQLiteIO(fname, self.scene, readonly=True)
with pytest.raises(BeeFileIOError) as exinfo:
io.read()
assert exinfo.value.filename == fname
# should not create a file on reading!
assert os.path.isfile(fname) is False