From 369a641f1015c085cfaca72f3b313f1dc27cbb42 Mon Sep 17 00:00:00 2001 From: maxwellflitton Date: Tue, 4 Feb 2025 14:04:40 +0000 Subject: [PATCH] updating tests --- docker-compose.yml | 5 +++ src/surrealdb/__init__.py | 1 - src/surrealdb/connections/async_http.py | 2 +- src/surrealdb/data/cbor.py | 24 +++--------- src/surrealdb/data/types/datetime.py | 18 ++++----- .../connections/invalidate/test_async_http.py | 34 +++++++++++++--- .../connections/invalidate/test_async_ws.py | 25 +++++++++--- .../invalidate/test_blocking_http.py | 36 ++++++++++++----- .../invalidate/test_blocking_ws.py | 39 +++++++++++++------ tests/unit_tests/data_types/test_datetimes.py | 18 +++++---- 10 files changed, 132 insertions(+), 70 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index e43d8ab8..97207000 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,7 @@ services: - SURREAL_PASS=root - SURREAL_INSECURE_FORWARD_ACCESS_ERRORS=true - SURREAL_LOG=debug + - SURREAL_CAPS_ALLOW_GUESTS=true ports: - 8000:8000 @@ -18,6 +19,7 @@ services: - SURREAL_USER=root - SURREAL_PASS=root - SURREAL_LOG=trace + - SURREAL_CAPS_ALLOW_GUESTS=true ports: - 8121:8000 @@ -28,6 +30,7 @@ services: - SURREAL_USER=root - SURREAL_PASS=root - SURREAL_LOG=trace + - SURREAL_CAPS_ALLOW_GUESTS=true ports: - 8120:8000 @@ -38,6 +41,7 @@ services: - SURREAL_USER=root - SURREAL_PASS=root - SURREAL_LOG=trace + - SURREAL_CAPS_ALLOW_GUESTS=true ports: - 8101:8000 @@ -48,5 +52,6 @@ services: - SURREAL_USER=root - SURREAL_PASS=root - SURREAL_LOG=trace + - SURREAL_CAPS_ALLOW_GUESTS=true ports: - 8111:8000 \ No newline at end of file diff --git a/src/surrealdb/__init__.py b/src/surrealdb/__init__.py index fa7357ac..10f1aa68 100644 --- a/src/surrealdb/__init__.py +++ b/src/surrealdb/__init__.py @@ -12,7 +12,6 @@ from surrealdb.data.types.geometry import Geometry from surrealdb.data.types.range import Range from surrealdb.data.types.record_id import RecordID -from surrealdb.data.types.datetime import DatetimeWrapper from surrealdb.data.types.datetime import IsoDateTimeWrapper class AsyncSurrealDBMeta(type): diff --git a/src/surrealdb/connections/async_http.py b/src/surrealdb/connections/async_http.py index 6501f5ad..efd7a126 100644 --- a/src/surrealdb/connections/async_http.py +++ b/src/surrealdb/connections/async_http.py @@ -101,7 +101,7 @@ async def authenticate(self) -> None: message = RequestMessage( self.id, RequestMethod.AUTHENTICATE, - token=token + token=self.token ) return await self._send(message, "authenticating") diff --git a/src/surrealdb/data/cbor.py b/src/surrealdb/data/cbor.py index 3802de27..c1125df6 100644 --- a/src/surrealdb/data/cbor.py +++ b/src/surrealdb/data/cbor.py @@ -1,6 +1,9 @@ +from datetime import datetime, timedelta, timezone + import cbor2 from surrealdb.data.types import constants +from surrealdb.data.types.datetime import IsoDateTimeWrapper from surrealdb.data.types.duration import Duration from surrealdb.data.types.future import Future from surrealdb.data.types.geometry import ( @@ -15,9 +18,6 @@ from surrealdb.data.types.range import BoundIncluded, BoundExcluded, Range from surrealdb.data.types.record_id import RecordID from surrealdb.data.types.table import Table -from surrealdb.data.types.datetime import DatetimeWrapper, IsoDateTimeWrapper -from datetime import datetime, timedelta, timezone -import pytz @cbor2.shareable_encoder @@ -68,14 +68,6 @@ def default_encoder(encoder, obj): elif isinstance(obj, Duration): tagged = cbor2.CBORTag(constants.TAG_DURATION, obj.get_seconds_and_nano()) - elif isinstance(obj, DatetimeWrapper): - if obj.dt.tzinfo is None: # Make sure it's timezone-aware - obj.dt = obj.dt.replace(tzinfo=timezone.utc) - - tagged = cbor2.CBORTag( - constants.TAG_DATETIME_COMPACT, - [int(obj.dt.timestamp()), obj.dt.microsecond * 1000] - ) elif isinstance(obj, IsoDateTimeWrapper): tagged = cbor2.CBORTag(constants.TAG_DATETIME, obj.dt) else: @@ -134,13 +126,7 @@ def tag_decoder(decoder, tag, shareable_index=None): seconds = tag.value[0] nanoseconds = tag.value[1] microseconds = nanoseconds // 1000 # Convert nanoseconds to microseconds - return DatetimeWrapper( - datetime.fromtimestamp(seconds) + timedelta(microseconds=microseconds) - ) - - elif tag.tag == constants.TAG_DATETIME: - dt_obj = datetime.fromisoformat(tag.value) - return DatetimeWrapper(dt_obj)# String (ISO 8601 datetime) + return datetime.fromtimestamp(seconds) + timedelta(microseconds=microseconds) else: raise BufferError("no decoder for tag", tag.tag) @@ -148,7 +134,7 @@ def tag_decoder(decoder, tag, shareable_index=None): def encode(obj): - return cbor2.dumps(obj, default=default_encoder) + return cbor2.dumps(obj, default=default_encoder, timezone=timezone.utc) def decode(data): diff --git a/src/surrealdb/data/types/datetime.py b/src/surrealdb/data/types/datetime.py index 3984eec7..cff8d2b1 100644 --- a/src/surrealdb/data/types/datetime.py +++ b/src/surrealdb/data/types/datetime.py @@ -1,14 +1,14 @@ -from datetime import datetime +# from datetime import datetime -class DatetimeWrapper: - - def __init__(self, dt: datetime): - self.dt = dt - - @staticmethod - def now() -> "DatetimeWrapper": - return DatetimeWrapper(datetime.now()) +# class DatetimeWrapper: +# +# def __init__(self, dt: datetime): +# self.dt = dt +# +# @staticmethod +# def now() -> "DatetimeWrapper": +# return DatetimeWrapper(datetime.now()) class IsoDateTimeWrapper: diff --git a/tests/unit_tests/connections/invalidate/test_async_http.py b/tests/unit_tests/connections/invalidate/test_async_http.py index 4e6df53e..0a038d8a 100644 --- a/tests/unit_tests/connections/invalidate/test_async_http.py +++ b/tests/unit_tests/connections/invalidate/test_async_http.py @@ -25,7 +25,17 @@ async def asyncSetUp(self): _ = await self.connection.signin(self.vars_params) _ = await self.connection.use(namespace=self.namespace, database=self.database_name) - async def test_invalidate(self): + async def test_run_test(self): + if os.environ.get("NO_GUEST_MODE") == "True": + await self.invalidate_test_for_no_guest_mode() + else: + await self.invalidate_with_guest_mode_on() + + async def invalidate_with_guest_mode_on(self): + """ + This test only works if the SURREAL_CAPS_ALLOW_GUESTS=false is set in the docker container + + """ outcome = await self.connection.query("SELECT * FROM user;") self.assertEqual(1, len(outcome)) outcome = await self.main_connection.query("SELECT * FROM user;") @@ -37,18 +47,30 @@ async def test_invalidate(self): self.assertEqual(0, len(outcome)) outcome = await self.main_connection.query("SELECT * FROM user;") self.assertEqual(1, len(outcome)) + await self.main_connection.query("DELETE user;") + + async def invalidate_test_for_no_guest_mode(self): + """ + This test asserts that there is an error thrown due to no guest mode being allowed + Only run this test if SURREAL_CAPS_ALLOW_GUESTS=false is set in the docker container + """ + outcome = await self.connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + outcome = await self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + + _ = await self.connection.invalidate() - ''' - # Exceptions are raised only when SurrealDB doesn't allow guest mode with self.assertRaises(Exception) as context: - _ = await self.connection.query("CREATE user:jaime SET name = 'Jaime';") + _ = await self.connection.query("SELECT * FROM user;") self.assertEqual( "IAM error: Not enough permissions" in str(context.exception), True ) - ''' - + outcome = await self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) await self.main_connection.query("DELETE user;") + if __name__ == "__main__": main() diff --git a/tests/unit_tests/connections/invalidate/test_async_ws.py b/tests/unit_tests/connections/invalidate/test_async_ws.py index efa4e5e9..1faf24c3 100644 --- a/tests/unit_tests/connections/invalidate/test_async_ws.py +++ b/tests/unit_tests/connections/invalidate/test_async_ws.py @@ -25,7 +25,13 @@ async def asyncSetUp(self): _ = await self.connection.signin(self.vars_params) _ = await self.connection.use(namespace=self.namespace, database=self.database_name) - async def test_invalidate(self): + async def test_run_test(self): + if os.environ.get("NO_GUEST_MODE") == "True": + await self.invalidate_test_for_no_guest_mode() + else: + await self.invalidate_with_guest_mode_on() + + async def invalidate_with_guest_mode_on(self): outcome = await self.connection.query("SELECT * FROM user;") self.assertEqual(1, len(outcome)) outcome = await self.main_connection.query("SELECT * FROM user;") @@ -37,16 +43,25 @@ async def test_invalidate(self): self.assertEqual(0, len(outcome)) outcome = await self.main_connection.query("SELECT * FROM user;") self.assertEqual(1, len(outcome)) + await self.main_connection.query("DELETE user;") + + async def invalidate_test_for_no_guest_mode(self): + outcome = await self.connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + outcome = await self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + + _ = await self.connection.invalidate() - ''' - # Exceptions are raised only when SurrealDB doesn't allow guest mode with self.assertRaises(Exception) as context: - _ = await self.connection.query("CREATE user:jaime SET name = 'Jaime';") + _ = await self.connection.query("SELECT * FROM user;") + self.assertEqual( "IAM error: Not enough permissions" in str(context.exception), True ) - ''' + outcome = await self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) await self.main_connection.query("DELETE user;") await self.main_connection.close() diff --git a/tests/unit_tests/connections/invalidate/test_blocking_http.py b/tests/unit_tests/connections/invalidate/test_blocking_http.py index b181cf33..d5294069 100644 --- a/tests/unit_tests/connections/invalidate/test_blocking_http.py +++ b/tests/unit_tests/connections/invalidate/test_blocking_http.py @@ -25,7 +25,13 @@ def setUp(self): _ = self.connection.signin(self.vars_params) _ = self.connection.use(namespace=self.namespace, database=self.database_name) - def test_invalidate(self): + def test_run_test(self): + if os.environ.get("NO_GUEST_MODE") == "True": + self.invalidate_test_for_no_guest_mode() + else: + self.invalidate_with_guest_mode_on() + + def invalidate_test_for_no_guest_mode(self): outcome = self.connection.query("SELECT * FROM user;") self.assertEqual(1, len(outcome)) outcome = self.main_connection.query("SELECT * FROM user;") @@ -33,20 +39,30 @@ def test_invalidate(self): _ = self.connection.invalidate() - outcome = self.connection.query("SELECT * FROM user;") - self.assertEqual(0, len(outcome)) - outcome = self.main_connection.query("SELECT * FROM user;") - self.assertEqual(1, len(outcome)) - - ''' - # Exceptions are raised only when SurrealDB doesn't allow guest mode with self.assertRaises(Exception) as context: - _ = self.connection.query("CREATE user:jaime SET name = 'Jaime';") + _ = self.connection.query("SELECT * FROM user;") + self.assertEqual( "IAM error: Not enough permissions" in str(context.exception), True ) - ''' + outcome = self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + + self.main_connection.query("DELETE user;") + + def invalidate_with_guest_mode_on(self): + outcome = self.connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + outcome = self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + + _ = self.connection.invalidate() + + outcome = self.connection.query("SELECT * FROM user;") + self.assertEqual(0, len(outcome)) + outcome = self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) self.main_connection.query("DELETE user;") diff --git a/tests/unit_tests/connections/invalidate/test_blocking_ws.py b/tests/unit_tests/connections/invalidate/test_blocking_ws.py index ad841d18..deb81623 100644 --- a/tests/unit_tests/connections/invalidate/test_blocking_ws.py +++ b/tests/unit_tests/connections/invalidate/test_blocking_ws.py @@ -1,5 +1,6 @@ -from unittest import main, TestCase import os +from unittest import main, TestCase + from surrealdb.connections.blocking_ws import BlockingWsSurrealConnection @@ -25,7 +26,13 @@ def setUp(self): _ = self.connection.signin(self.vars_params) _ = self.connection.use(namespace=self.namespace, database=self.database_name) - def test_invalidate(self): + def test_run_test(self): + if os.environ.get("NO_GUEST_MODE") == "True": + self.invalidate_test_for_no_guest_mode() + else: + self.invalidate_with_guest_mode_on() + + def invalidate_test_for_no_guest_mode(self): outcome = self.connection.query("SELECT * FROM user;") self.assertEqual(1, len(outcome)) outcome = self.main_connection.query("SELECT * FROM user;") @@ -33,20 +40,30 @@ def test_invalidate(self): _ = self.connection.invalidate() - outcome = self.connection.query("SELECT * FROM user;") - self.assertEqual(0, len(outcome)) - outcome = self.main_connection.query("SELECT * FROM user;") - self.assertEqual(1, len(outcome)) - - ''' - # Exceptions are raised only when SurrealDB doesn't allow guest mode with self.assertRaises(Exception) as context: - _ = self.connection.query("CREATE user:jaime SET name = 'Jaime';") + _ = self.connection.query("SELECT * FROM user;") + self.assertEqual( "IAM error: Not enough permissions" in str(context.exception), True ) - ''' + outcome = self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + + self.main_connection.query("DELETE user;") + + def invalidate_with_guest_mode_on(self): + outcome = self.connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + outcome = self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) + + _ = self.connection.invalidate() + + outcome = self.connection.query("SELECT * FROM user;") + self.assertEqual(0, len(outcome)) + outcome = self.main_connection.query("SELECT * FROM user;") + self.assertEqual(1, len(outcome)) self.main_connection.query("DELETE user;") self.main_connection.close() diff --git a/tests/unit_tests/data_types/test_datetimes.py b/tests/unit_tests/data_types/test_datetimes.py index 6fb45000..6416eae8 100644 --- a/tests/unit_tests/data_types/test_datetimes.py +++ b/tests/unit_tests/data_types/test_datetimes.py @@ -1,7 +1,8 @@ +import datetime from unittest import main, IsolatedAsyncioTestCase from surrealdb.connections.async_ws import AsyncWsSurrealConnection -from surrealdb.data.types.datetime import DatetimeWrapper, IsoDateTimeWrapper +from surrealdb.data.types.datetime import IsoDateTimeWrapper class TestAsyncWsSurrealConnectionDatetime(IsolatedAsyncioTestCase): @@ -26,20 +27,20 @@ async def asyncSetUp(self): await self.connection.query("DELETE datetime_tests;") async def test_datetime_wrapper(self): - now = DatetimeWrapper.now() + now = datetime.datetime.now() await self.connection.query( "CREATE datetime_tests:compact_test SET datetime = $compact_datetime;", params={"compact_datetime": now} ) compact_test_outcome = await self.connection.query("SELECT * FROM datetime_tests;") self.assertEqual( - type(compact_test_outcome[0]["datetime"]), - DatetimeWrapper + compact_test_outcome[0]["datetime"], + now ) # assert that the datetime returned from the DB is the same as the one serialized outcome = compact_test_outcome[0]["datetime"] - self.assertEqual(now.dt.isoformat(), outcome.dt.isoformat() + "+00:00") + self.assertEqual(now.isoformat(), outcome.isoformat()) await self.connection.query("DELETE datetime_tests;") await self.connection.close() @@ -47,6 +48,7 @@ async def test_datetime_wrapper(self): async def test_datetime_formats(self): iso_datetime = "2025-02-03T12:30:45.123456Z" # ISO 8601 datetime date = IsoDateTimeWrapper(iso_datetime) + iso_datetime_obj = datetime.datetime.fromisoformat(iso_datetime) # Insert records with different datetime formats await self.connection.query( @@ -55,12 +57,12 @@ async def test_datetime_formats(self): ) compact_test_outcome = await self.connection.query("SELECT * FROM datetime_tests;") self.assertEqual( - type(compact_test_outcome[0]["datetime"]), - DatetimeWrapper + str(compact_test_outcome[0]["datetime"]) + "+00:00", + str(iso_datetime_obj) ) # assert that the datetime returned from the DB is the same as the one serialized - date = compact_test_outcome[0]["datetime"].dt.isoformat() + date = compact_test_outcome[0]["datetime"].isoformat() self.assertEqual(date + "Z", iso_datetime) # Cleanup