Changeset: 2708b772e8db for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2708b772e8db Added Files: clients/iotclient/tests/datatypesinsertstests.py Removed Files: clients/iotclient/tests/datatypestests.py Modified Files: clients/iotclient/src/Streams/datatypes.py clients/iotclient/tests/main.py Branch: iot Log Message:
Added nullable constants verification tests diffs (truncated from 511 to 300 lines): diff --git a/clients/iotclient/src/Streams/datatypes.py b/clients/iotclient/src/Streams/datatypes.py --- a/clients/iotclient/src/Streams/datatypes.py +++ b/clients/iotclient/src/Streams/datatypes.py @@ -16,12 +16,12 @@ LITTLE_ENDIAN_ALIGNMENT = '<' # for now NIL_STRING = "\200" NIL_UUID = "00000000-0000-0000-0000-000000000000" -INT8_MIN = 0x80 -INT16_MIN = 0x8000 -INT32_MIN = 0x80000000 -INT64_MIN = 0x8000000000000000 -INT64_MAX = 0xFFFFFFFFFFFFFFFF -INT128_MIN = 0x80000000000000000000000000000000 +INT8_MIN = -128 +INT16_MIN = -32768 +INT32_MIN = -2147483648 +INT64_MIN = -9223372036854775808 +INT64_MAX = +9223372036854775807 +INT128_MIN = -340282366920938463463374607431768211456 FLOAT_NAN = struct.unpack('f', '\xff\xff\x7f\xff')[0] DOUBLE_NAN = struct.unpack('d', '\xff\xff\xff\xff\xff\xff\xef\xff')[0] @@ -370,6 +370,8 @@ class BooleanType(StreamDataType): return INT8_MIN def process_next_value(self, entry, counter, parameters, errors): + if entry == self.get_nullable_constant(): + return self.get_nullable_constant() if bool(entry): return 1 return 0 @@ -464,10 +466,10 @@ class HugeIntegerType(NumberBaseType): schema[self._column_name]['type'] = 'integer' def get_nullable_constant(self): - return INT128_MIN + return 0x80000000000000000000000000000000 def process_next_value(self, entry, counter, parameters, errors): - return [entry & INT64_MAX, (entry >> 64) & INT64_MAX] + return [entry & 0xFFFFFFFFFFFFFFFF, (entry >> 64) & 0xFFFFFFFFFFFFFFFF] def pack_parsed_values(self, extracted_values, counter, parameters): extracted_values = list(itertools.chain(*extracted_values)) @@ -536,9 +538,10 @@ class DecimalType(NumberBaseType): .get(self._pack_sym) def check_value_precision(self, value, text): - number_digits = int(math.ceil(math.log10(abs(value)))) - if number_digits > self._precision: - raise Exception('Too many digits on %s: %s > %s!' % (text, number_digits, self._precision)) + if value != self._nullable_constant: + number_digits = int(math.ceil(math.log10(abs(value)))) + if number_digits > self._precision: + raise Exception('Too many digits on %s: %s > %s!' % (text, number_digits, self._precision)) def add_json_schema_entry(self, schema): super(DecimalType, self).add_json_schema_entry(schema) @@ -552,7 +555,7 @@ class DecimalType(NumberBaseType): if self._pack_sym != 'Q': return int(entry) else: - return [int(entry) & INT64_MAX, (int(entry) >> 64) & INT64_MAX] + return [int(entry) & 0xFFFFFFFFFFFFFFFF, (int(entry) >> 64) & 0xFFFFFFFFFFFFFFFF] def pack_parsed_values(self, extracted_values, counter, parameters): if self._pack_sym == 'Q': @@ -647,7 +650,7 @@ class DateType(BaseDateTimeType): # Sto def pack_next_value(self, parsed, counter, parameters, errors): if parsed is None: - return INT32_MIN + return 0x80000000 day0 = copy.deepcopy(parsed).replace(year=1, month=1, day=1) # the minyear in python is 1, but for the representation is 0, so why the add return int((parsed - day0).days) + 366 @@ -682,7 +685,7 @@ class TimeType(BaseDateTimeType): # Sto def pack_next_value(self, parsed, counter, parameters, errors): if parsed is None: - return INT32_MIN + return 0x80000000 hour0 = copy.deepcopy(parsed).replace(hour=0, minute=0, second=0, microsecond=0) delta = parsed - hour0 return int(delta.total_seconds()) * 1000 + int(delta.microseconds) / 1000 @@ -726,7 +729,7 @@ class TimestampType(BaseDateTimeType): def pack_next_value(self, parsed, counter, parameters, errors): if parsed is None: - return [0, INT32_MIN] + return [0, 0x80000000] hour0 = copy.deepcopy(parsed).replace(hour=0, minute=0, second=0, microsecond=0) day0 = copy.deepcopy(parsed).replace(year=1, month=1, day=1) days = int((parsed - day0).days) + 366 diff --git a/clients/iotclient/tests/datatypestests.py b/clients/iotclient/tests/datatypesinsertstests.py rename from clients/iotclient/tests/datatypestests.py rename to clients/iotclient/tests/datatypesinsertstests.py --- a/clients/iotclient/tests/datatypestests.py +++ b/clients/iotclient/tests/datatypesinsertstests.py @@ -170,6 +170,7 @@ class UUIDTest(BaseStringText): def runTest(self): super(UUIDTest, self).runTest() + class BooleanTest(DataTypesTest): def __init__(self, mapi_connection, number_inserts, temp_path): @@ -396,3 +397,304 @@ class TimestampWithTimezoneTest(BaseStri def get_next_batch(self, number_inserts): return [faker.iso8601(tzinfo=timezone(faker.timezone())) for _ in xrange(number_inserts)] + + +class NullablesTest(unittest.TestCase): + __metaclass__ = ABCMeta + + def __init__(self, mapi_connection, temp_path): + super(NullablesTest, self).__init__() + self._mapi_connection = mapi_connection + self._data_type = self.get_data_type() + self._temp_path = os.path.join(temp_path, self._data_type.replace(' ', '_')) + self._data_type = self.get_data_type() + + @abstractmethod + def get_data_type(self): + return 'none' + + @abstractmethod + def get_null_value(self): + return 'none' + + def runTest(self): + try: + self._mapi_connection.execute("DROP TABLE sql_insert;") + self._mapi_connection.execute("DROP TABLE binary_insert;") + except: + pass + + self._mapi_connection.execute("CREATE TABLE sql_insert (val " + self.get_data_type() + ");") + self._mapi_connection.execute("CREATE TABLE binary_insert (val " + self.get_data_type() + ");") + + # make the null value sql insert + self._mapi_connection.execute("INSERT INTO sql_insert VALUES (null);") + + # make the null value binary insert + with open(self._temp_path, 'w+b') as fp: + fp.write(self.get_null_value()) + fp.flush() + self._mapi_connection.execute("COPY BINARY INTO binary_insert FROM ('" + self._temp_path + "');") + + cursor = self._mapi_connection.cursor() + cursor.execute("SELECT val FROM sql_insert;") + sql_inserts = cursor.fetchall() + cursor.execute("SELECT val FROM binary_insert;") + binary_inserts = cursor.fetchall() + + self._mapi_connection.execute("DROP TABLE sql_insert;") + self._mapi_connection.execute("DROP TABLE binary_insert;") + + try: + os.remove(self._temp_path) + except: + pass + self.assertListEqual(sql_inserts, binary_inserts) # the lists must be equal!! + + +class NullableTextTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableTextTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'clob' + + def get_null_value(self): + serializer = TextType(**{'name': 'val', 'type': 'clob'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + +class NullableURLTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableURLTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'url' + + def get_null_value(self): + serializer = URLType(**{'name': 'val', 'type': 'url'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + @unittest.skip("Data conversion problem") + def runTest(self): + super(NullableURLTest, self).runTest() + + +class NullableINetTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableINetTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'inet' + + def get_null_value(self): + serializer = INetType(**{'name': 'val', 'type': 'inet'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + @unittest.skip("Data conversion problem") + def runTest(self): + super(NullableINetTest, self).runTest() + + +class NullableUUIDTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableUUIDTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'uuid' + + def get_null_value(self): + serializer = UUIDType(**{'name': 'val', 'type': 'uuid'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + @unittest.skip("Data conversion problem") + def runTest(self): + super(NullableUUIDTest, self).runTest() + + +class NullableBooleanTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableBooleanTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'boolean' + + def get_null_value(self): + serializer = BooleanType(**{'name': 'val', 'type': 'boolean'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + +class NullableTinyIntegerTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableTinyIntegerTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'tinyint' + + def get_null_value(self): + serializer = SmallIntegerType(**{'name': 'val', 'type': 'tinyint'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + +class NullableSmallIntegerTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableSmallIntegerTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'smallint' + + def get_null_value(self): + serializer = SmallIntegerType(**{'name': 'val', 'type': 'smallint'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + +class NullableIntegerTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableIntegerTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'integer' + + def get_null_value(self): + serializer = SmallIntegerType(**{'name': 'val', 'type': 'integer'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + +class NullableBigIntegerTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableBigIntegerTest, self).__init__(mapi_connection, temp_path) + + def get_data_type(self): + return 'bigint' + + def get_null_value(self): + serializer = SmallIntegerType(**{'name': 'val', 'type': 'bigint'}) + return serializer.process_values([serializer.get_nullable_constant()]) + + +class NullableHugeIntegerTest(NullablesTest): + + def __init__(self, mapi_connection, temp_path): + super(NullableHugeIntegerTest, self).__init__(mapi_connection, temp_path) + _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list