From 689c841341be1bb3cbd887b3acefcaecb063a3de Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Thu, 25 Mar 2021 18:36:11 +0530 Subject: [PATCH 1/3] test: add text compliance tests --- test/test_suite.py | 72 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/test/test_suite.py b/test/test_suite.py index bebfd01b..55b89dff 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -27,7 +27,7 @@ from sqlalchemy import exists from sqlalchemy import Boolean from sqlalchemy import String -from sqlalchemy.types import Integer +from sqlalchemy.types import Integer, Text from sqlalchemy.testing import requires from google.api_core.datetime_helpers import DatetimeWithNanoseconds @@ -47,6 +47,7 @@ from sqlalchemy.testing.suite.test_select import ExistsTest as _ExistsTest from sqlalchemy.testing.suite.test_types import BooleanTest as _BooleanTest from sqlalchemy.testing.suite.test_types import IntegerTest as _IntegerTest +from sqlalchemy.testing.suite.test_types import TextTest as _TextTest from sqlalchemy.testing.suite.test_types import ( # noqa: F401, F403 DateTest as _DateTest, @@ -509,3 +510,72 @@ def _literal_round_trip(self, type_, input_, output, filter_=None): if filter_ is not None: value = filter_(value) assert value in output + + +class TextTest(_TextTest): + @pytest.mark.skip("Spanner throws an error") + def test_text_empty_strings(self, connection): + """ + SPANNER OVERRIDE: + + Spanner DBAPI throws an error when cleanup tried to + rollback the connection after the test executed successfully. + The error is `ValueError: Transaction is already rolled back`. + """ + pass + + @pytest.mark.skip("Spanner throws an error") + def test_text_null_strings(self, connection): + """ + SPANNER OVERRIDE: + + Spanner DBAPI throws an error when cleanup tried to + rollback the connection after the test executed successfully. + The error is `ValueError: Transaction is already rolled back`. + """ + pass + + @pytest.mark.skip("Spanner doesn't support non-ascii characters") + def test_literal_non_ascii(self): + pass + + def test_literal_quoting(self): + """ + SPANNER OVERRIDE: + + The original test string is : \"""some 'text' hey "hi there" that's text\""" + + Spanner doesn't support string which contains `'s` in strings and throws a + syntax error, e.g.: `'''hey that's text'''` + Override the method and change the input data. + """ + data = """some "text" hey "hi there" that is text""" + self._literal_round_trip(Text, [data], [data]) + + def test_literal_backslashes(self): + """ + SPANNER OVERRIDE: + Spanner supports `\\` backslash to represent valid escape sequence, but + for `'\'` Spanner throws an error `400 Syntax error: Illegal escape sequence`. + See: https://cloud.google.com/spanner/docs/lexical#string_and_bytes_literals + """ + input_data = r"backslash one \\ backslash \\\\ two end" + output_data = r"backslash one \ backslash \\ two end" + + self._literal_round_trip(Text, [input_data], [output_data]) + + def test_text_roundtrip(self): + """ + SPANNER OVERRIDE: + + Cloud Spanner doesn't support the tables with an empty primary key + when column has defined NOT NULL - following insertions will fail with + `400 id must not be NULL in table date_table`. + Overriding the tests and adding a manual primary key value to avoid the same + failures and deleting the table at the end. + """ + text_table = self.tables.text_table + + config.db.execute(text_table.insert(), {"id": 1, "text_data": "some text"}) + row = config.db.execute(select([text_table.c.text_data])).first() + eq_(row, ("some text",)) From 679a4e237d8bc8d9bcd496739965132d51417f86 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Wed, 5 May 2021 16:32:11 +0530 Subject: [PATCH 2/3] test: enable skipped test --- test/test_suite.py | 55 +++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/test/test_suite.py b/test/test_suite.py index 3d76c23e..30625aad 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -43,7 +43,8 @@ from sqlalchemy import LargeBinary from sqlalchemy import Boolean from sqlalchemy import String -from sqlalchemy.types import Integer, Text +from sqlalchemy.types import Integer +from sqlalchemy.types import Text from sqlalchemy.types import Numeric from sqlalchemy.testing import requires @@ -847,27 +848,37 @@ class QuotedNameArgumentTest(_QuotedNameArgumentTest): class TextTest(_TextTest): - @pytest.mark.skip("Spanner throws an error") def test_text_empty_strings(self, connection): """ SPANNER OVERRIDE: - Spanner DBAPI throws an error when cleanup tried to - rollback the connection after the test executed successfully. - The error is `ValueError: Transaction is already rolled back`. + Cloud Spanner doesn't support the tables with an empty primary key + when column has defined NOT NULL - following insertions will fail with + `400 id must not be NULL in table date_table`. + Overriding the tests and adding a manual primary key value to avoid the same + failures. """ - pass + text_table = self.tables.text_table + + connection.execute(text_table.insert(), {"id": 1, "text_data": None}) + row = connection.execute(select([text_table.c.text_data])).first() + eq_(row, (None,)) - @pytest.mark.skip("Spanner throws an error") def test_text_null_strings(self, connection): """ SPANNER OVERRIDE: - Spanner DBAPI throws an error when cleanup tried to - rollback the connection after the test executed successfully. - The error is `ValueError: Transaction is already rolled back`. + Cloud Spanner doesn't support the tables with an empty primary key + when column has defined NOT NULL - following insertions will fail with + `400 id must not be NULL in table date_table`. + Overriding the tests and adding a manual primary key value to avoid the same + failures. """ - pass + text_table = self.tables.text_table + + connection.execute(text_table.insert(), {"id": 1, "text_data": ""}) + row = connection.execute(select([text_table.c.text_data])).first() + eq_(row, ("",)) @pytest.mark.skip("Spanner doesn't support non-ascii characters") def test_literal_non_ascii(self): @@ -879,19 +890,23 @@ def test_literal_quoting(self): The original test string is : \"""some 'text' hey "hi there" that's text\""" - Spanner doesn't support string which contains `'s` in strings and throws a - syntax error, e.g.: `'''hey that's text'''` - Override the method and change the input data. + Spanner throws a syntax error for not representing non-alphanumeric characters + in string as a raw string. + Override the method to change input data into raw string. """ - data = """some "text" hey "hi there" that is text""" - self._literal_round_trip(Text, [data], [data]) + input_data = r"""some 'text' hey \"hi there\" that's text""" + output_data = """some 'text' hey "hi there" that's text""" + self._literal_round_trip(Text, [input_data], [output_data]) def test_literal_backslashes(self): """ SPANNER OVERRIDE: - Spanner supports `\\` backslash to represent valid escape sequence, but - for `'\'` Spanner throws an error `400 Syntax error: Illegal escape sequence`. - See: https://cloud.google.com/spanner/docs/lexical#string_and_bytes_literals + + Cloud spanner supports prefixed backslash to escape non-alphanumeric characters + in string. + Override the method to add additional escape before using it to generate a SQL + statement. See: + https://cloud.google.com/spanner/docs/lexical#string_and_bytes_literals """ input_data = r"backslash one \\ backslash \\\\ two end" output_data = r"backslash one \ backslash \\ two end" @@ -906,7 +921,7 @@ def test_text_roundtrip(self): when column has defined NOT NULL - following insertions will fail with `400 id must not be NULL in table date_table`. Overriding the tests and adding a manual primary key value to avoid the same - failures and deleting the table at the end. + failures. """ text_table = self.tables.text_table From 737ed45e8a290a0bda3be721e10b88682c3f5bd6 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Wed, 5 May 2021 17:37:55 +0530 Subject: [PATCH 3/3] test: nit --- test/test_suite.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_suite.py b/test/test_suite.py index 30625aad..b6015938 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -860,9 +860,9 @@ def test_text_empty_strings(self, connection): """ text_table = self.tables.text_table - connection.execute(text_table.insert(), {"id": 1, "text_data": None}) + connection.execute(text_table.insert(), {"id": 1, "text_data": ""}) row = connection.execute(select([text_table.c.text_data])).first() - eq_(row, (None,)) + eq_(row, ("",)) def test_text_null_strings(self, connection): """ @@ -876,9 +876,9 @@ def test_text_null_strings(self, connection): """ text_table = self.tables.text_table - connection.execute(text_table.insert(), {"id": 1, "text_data": ""}) + connection.execute(text_table.insert(), {"id": 1, "text_data": None}) row = connection.execute(select([text_table.c.text_data])).first() - eq_(row, ("",)) + eq_(row, (None,)) @pytest.mark.skip("Spanner doesn't support non-ascii characters") def test_literal_non_ascii(self):