This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
More tests for the simple_* methods #16596
Merged
Merged
Changes from 7 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
42e21a4
Basic upsert tests.
clokep 3da39af
Add basic upsert_many tests.
clokep a5348d5
Test insert_many and update_many.
clokep 0edc67c
Add tests for delete_many.
clokep 6252b31
Test select_many_batch.
clokep 926780c
Add tests for not having iterables.
clokep 7ac4899
Newsfragment
clokep ff58a47
Test simple_upsert_many with multiple rows.
clokep 80a7f75
Avoid double space.
clokep 9f3ba06
Clarify variable name.
clokep 98b28b4
Add tests for emulated upserts.
clokep 85928cf
Add postgres tests.
clokep 1fa8fcc
Lint
clokep 5172d8b
Fix-up asserts.
clokep e4957d6
Add tests for no values.
clokep File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Improve tests of the SQL generator. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ | |
|
||
from collections import OrderedDict | ||
from typing import Generator | ||
from unittest.mock import Mock | ||
from unittest.mock import Mock, call | ||
|
||
from twisted.internet import defer | ||
|
||
|
@@ -55,6 +55,8 @@ def runWithConnection(func, *args, **kwargs): # type: ignore[no-untyped-def] | |
engine = create_engine(sqlite_config) | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fake_engine = Mock(wraps=engine) | ||
fake_engine.in_transaction.return_value = False | ||
fake_engine.module.OperationalError = engine.module.OperationalError | ||
fake_engine.module.DatabaseError = engine.module.DatabaseError | ||
|
||
db = DatabasePool(Mock(), Mock(config=sqlite_config), fake_engine) | ||
db._db_pool = self.db_pool | ||
|
@@ -91,6 +93,33 @@ def test_insert_3cols(self) -> Generator["defer.Deferred[object]", object, None] | |
"INSERT INTO tablename (colA, colB, colC) VALUES(?, ?, ?)", (1, 2, 3) | ||
) | ||
|
||
@defer.inlineCallbacks | ||
def test_insert_many(self) -> Generator["defer.Deferred[object]", object, None]: | ||
yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_insert_many( | ||
table="tablename", | ||
keys=( | ||
"col1", | ||
"col2", | ||
), | ||
values=[ | ||
( | ||
"val1", | ||
"val2", | ||
), | ||
("val3", "val4"), | ||
], | ||
desc="", | ||
) | ||
) | ||
|
||
# TODO Test postgres variant. | ||
|
||
self.mock_txn.executemany.assert_called_with( | ||
"INSERT INTO tablename (col1, col2) VALUES(?, ?)", | ||
[("val1", "val2"), ("val3", "val4")], | ||
) | ||
|
||
@defer.inlineCallbacks | ||
def test_select_one_1col(self) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 1 | ||
|
@@ -160,6 +189,54 @@ def test_select_list(self) -> Generator["defer.Deferred[object]", object, None]: | |
"SELECT colA FROM tablename WHERE keycol = ?", ["A set"] | ||
) | ||
|
||
@defer.inlineCallbacks | ||
def test_select_many_batch( | ||
self, | ||
) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 3 | ||
self.mock_txn.fetchall.side_effect = [[(1,), (2,)], [(3,)]] | ||
|
||
ret = yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_select_many_batch( | ||
table="tablename", | ||
column="col1", | ||
iterable=("val1", "val2", "val3"), | ||
retcols=("col2",), | ||
keyvalues={"col3": "val4"}, | ||
batch_size=2, | ||
) | ||
) | ||
|
||
self.mock_txn.execute.assert_has_calls( | ||
[ | ||
call( | ||
"SELECT col2 FROM tablename WHERE col1 = ANY(?) AND col3 = ?", | ||
[["val1", "val2"], "val4"], | ||
), | ||
call( | ||
"SELECT col2 FROM tablename WHERE col1 = ANY(?) AND col3 = ?", | ||
[["val3"], "val4"], | ||
), | ||
], | ||
) | ||
self.assertEqual([(1,), (2,), (3,)], ret) | ||
|
||
def test_select_many_no_iterable(self) -> None: | ||
self.mock_txn.rowcount = 3 | ||
self.mock_txn.fetchall.side_effect = [(1,), (2,)] | ||
|
||
ret = self.datastore.db_pool.simple_select_many_txn( | ||
self.mock_txn, | ||
table="tablename", | ||
column="col1", | ||
iterable=(), | ||
retcols=("col2",), | ||
keyvalues={"col3": "val4"}, | ||
) | ||
|
||
self.mock_txn.execute.assert_not_called() | ||
self.assertEqual([], ret) | ||
|
||
@defer.inlineCallbacks | ||
def test_update_one_1col(self) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 1 | ||
|
@@ -196,6 +273,37 @@ def test_update_one_4cols( | |
[3, 4, 1, 2], | ||
) | ||
|
||
@defer.inlineCallbacks | ||
def test_update_many(self) -> Generator["defer.Deferred[object]", object, None]: | ||
yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_update_many( | ||
table="tablename", | ||
key_names=("col1", "col2"), | ||
key_values=[("val1", "val2")], | ||
value_names=("col3",), | ||
value_values=[("val3",)], | ||
desc="", | ||
) | ||
) | ||
|
||
self.mock_txn.executemany.assert_called_with( | ||
"UPDATE tablename SET col3 = ? WHERE col1 = ? AND col2 = ?", | ||
[("val3", "val1", "val2"), ("val3", "val1", "val2")], | ||
) | ||
|
||
# key_values and value_values must be the same length. | ||
with self.assertRaises(ValueError): | ||
yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_update_many( | ||
table="tablename", | ||
key_names=("col1", "col2"), | ||
key_values=[("val1", "val2")], | ||
value_names=("col3",), | ||
value_values=[], | ||
desc="", | ||
) | ||
) | ||
|
||
@defer.inlineCallbacks | ||
def test_delete_one(self) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 1 | ||
|
@@ -209,3 +317,163 @@ def test_delete_one(self) -> Generator["defer.Deferred[object]", object, None]: | |
self.mock_txn.execute.assert_called_with( | ||
"DELETE FROM tablename WHERE keycol = ?", ["Go away"] | ||
) | ||
|
||
@defer.inlineCallbacks | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess twisted/trial doesn't let you write test methods using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They do, but I think not on our lowest bound. I started testing it and got into some dependency hell and stopped. |
||
def test_delete_many(self) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 2 | ||
|
||
result = yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_delete_many( | ||
table="tablename", | ||
column="col1", | ||
iterable=("val1", "val2"), | ||
keyvalues={"col2": "val3"}, | ||
desc="", | ||
) | ||
) | ||
|
||
self.mock_txn.execute.assert_called_with( | ||
"DELETE FROM tablename WHERE col1 = ANY(?) AND col2 = ?", | ||
[["val1", "val2"], "val3"], | ||
) | ||
self.assertEqual(result, 2) | ||
|
||
@defer.inlineCallbacks | ||
def test_delete_many_no_iterable( | ||
self, | ||
) -> Generator["defer.Deferred[object]", object, None]: | ||
result = yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_delete_many( | ||
table="tablename", | ||
column="col1", | ||
iterable=(), | ||
keyvalues={"col2": "val3"}, | ||
desc="", | ||
) | ||
) | ||
|
||
self.mock_txn.execute.assert_not_called() | ||
self.assertEqual(result, 0) | ||
|
||
@defer.inlineCallbacks | ||
def test_delete_many_no_keyvalues( | ||
self, | ||
) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 2 | ||
|
||
result = yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_delete_many( | ||
table="tablename", | ||
column="col1", | ||
iterable=("val1", "val2"), | ||
keyvalues={}, | ||
desc="", | ||
) | ||
) | ||
|
||
self.mock_txn.execute.assert_called_with( | ||
"DELETE FROM tablename WHERE col1 = ANY(?)", [["val1", "val2"]] | ||
) | ||
self.assertEqual(result, 2) | ||
|
||
@defer.inlineCallbacks | ||
def test_upsert(self) -> Generator["defer.Deferred[object]", object, None]: | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.mock_txn.rowcount = 1 | ||
|
||
result = yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_upsert( | ||
table="tablename", | ||
keyvalues={"columnname": "oldvalue"}, | ||
values={"othercol": "newvalue"}, | ||
) | ||
) | ||
|
||
self.mock_txn.execute.assert_called_with( | ||
"INSERT INTO tablename (columnname, othercol) VALUES (?, ?) ON CONFLICT (columnname) DO UPDATE SET othercol=EXCLUDED.othercol", | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
["oldvalue", "newvalue"], | ||
) | ||
self.assertTrue(result) | ||
|
||
@defer.inlineCallbacks | ||
def test_upsert_with_insert( | ||
self, | ||
) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 1 | ||
|
||
result = yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_upsert( | ||
table="tablename", | ||
keyvalues={"columnname": "oldvalue"}, | ||
values={"othercol": "newvalue"}, | ||
insertion_values={"thirdcol": "insertionval"}, | ||
) | ||
) | ||
|
||
self.mock_txn.execute.assert_called_with( | ||
"INSERT INTO tablename (columnname, thirdcol, othercol) VALUES (?, ?, ?) ON CONFLICT (columnname) DO UPDATE SET othercol=EXCLUDED.othercol", | ||
["oldvalue", "insertionval", "newvalue"], | ||
) | ||
self.assertTrue(result) | ||
|
||
@defer.inlineCallbacks | ||
def test_upsert_with_where( | ||
self, | ||
) -> Generator["defer.Deferred[object]", object, None]: | ||
self.mock_txn.rowcount = 1 | ||
|
||
result = yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_upsert( | ||
table="tablename", | ||
keyvalues={"columnname": "oldvalue"}, | ||
values={"othercol": "newvalue"}, | ||
where_clause="thirdcol IS NULL", | ||
) | ||
) | ||
|
||
self.mock_txn.execute.assert_called_with( | ||
"INSERT INTO tablename (columnname, othercol) VALUES (?, ?) ON CONFLICT (columnname) WHERE thirdcol IS NULL DO UPDATE SET othercol=EXCLUDED.othercol", | ||
["oldvalue", "newvalue"], | ||
) | ||
self.assertTrue(result) | ||
|
||
@defer.inlineCallbacks | ||
def test_upsert_many(self) -> Generator["defer.Deferred[object]", object, None]: | ||
yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_upsert_many( | ||
table="tablename", | ||
key_names=["columnname"], | ||
key_values=[["oldvalue"]], | ||
value_names=["othercol"], | ||
value_values=[["newvalue"]], | ||
desc="", | ||
) | ||
) | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# TODO Test postgres variant. | ||
|
||
self.mock_txn.executemany.assert_called_with( | ||
"INSERT INTO tablename (columnname, othercol) VALUES (?, ?) ON CONFLICT (columnname) DO UPDATE SET othercol=EXCLUDED.othercol", | ||
[("oldvalue", "newvalue")], | ||
) | ||
|
||
@defer.inlineCallbacks | ||
def test_upsert_many_no_values( | ||
self, | ||
) -> Generator["defer.Deferred[object]", object, None]: | ||
yield defer.ensureDeferred( | ||
self.datastore.db_pool.simple_upsert_many( | ||
table="tablename", | ||
key_names=["columnname"], | ||
key_values=[["oldvalue"]], | ||
value_names=[], | ||
value_values=[], | ||
desc="", | ||
) | ||
) | ||
|
||
# TODO Test postgres variant. | ||
|
||
self.mock_txn.executemany.assert_called_with( | ||
"INSERT INTO tablename (columnname) VALUES (?) ON CONFLICT (columnname) DO NOTHING", | ||
[("oldvalue",)], | ||
) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's always at least 1 clause, so this is just a minor clean-up.