From: Philippe Proulx Date: Sat, 29 Jun 2019 15:28:34 +0000 (-0400) Subject: test_{field,value}.py: add comments X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=21368027963fcb93c2b5c7587fc9e47922f4cb45 test_{field,value}.py: add comments Those files contain code which is very similar. It should be a single helper base class eventually, but this patch only adds comments to both files to clarify the usage of some classes and methods. Signed-off-by: Philippe Proulx Change-Id: I15d8d4e1d8d3444491b9f01deb6d2cdcc5d406d1 Reviewed-on: https://review.lttng.org/c/babeltrace/+/1584 Tested-by: jenkins Reviewed-by: Francis Deslauriers --- diff --git a/tests/bindings/python/bt2/test_field.py b/tests/bindings/python/bt2/test_field.py index a22d3f4a..015be10e 100644 --- a/tests/bindings/python/bt2/test_field.py +++ b/tests/bindings/python/bt2/test_field.py @@ -120,56 +120,90 @@ def _create_struct_array_field(tc, length): return packet.context_field[field_name] +# Base class for numeric field test cases. +# +# To be compatible with this base class, a derived class must, in its +# setUp() method: +# +# * Set `self._def` to a field object with an arbitrary value. +# * Set `self._def_value` to the equivalent value of `self._def`. class _TestNumericField: + # Tries the binary operation `op`: + # + # 1. Between `self._def`, which is a field object, and `rhs`. + # 2. Between `self._def_value`, which is the raw value of + # `self._def`, and `rhs`. + # + # Returns the results of 1. and 2. + # + # If there's an exception while performing 1. or 2., asserts that + # both operations raised exceptions, that both exceptions have the + # same type, and returns `None` for both results. def _binop(self, op, rhs): - rexc = None - rvexc = None + type_rexc = None + type_rvexc = None comp_value = rhs + # try with field object try: r = op(self._def, rhs) except Exception as e: - rexc = e + type_rexc = type(e) + # try with value try: rv = op(self._def_value, comp_value) except Exception as e: - rvexc = e + type_rvexc = type(e) - if rexc is not None or rvexc is not None: + if type_rexc is not None or type_rvexc is not None: # at least one of the operations raised an exception: in # this case both operations should have raised the same # type of exception (division by zero, bit shift with a # floating point number operand, etc.) - self.assertIs(type(rexc), type(rvexc)) + self.assertIs(type_rexc, type_rvexc) return None, None return r, rv + # Tries the unary operation `op`: + # + # 1. On `self._def`, which is a field object. + # 2. On `self._def_value`, which is the value of `self._def`. + # + # Returns the results of 1. and 2. + # + # If there's an exception while performing 1. or 2., asserts that + # both operations raised exceptions, that both exceptions have the + # same type, and returns `None` for both results. def _unaryop(self, op): - rexc = None - rvexc = None + type_rexc = None + type_rvexc = None + # try with field object try: r = op(self._def) except Exception as e: - rexc = e + type_rexc = type(e) + # try with value try: rv = op(self._def_value) except Exception as e: - rvexc = e + type_rvexc = type(e) - if rexc is not None or rvexc is not None: + if type_rexc is not None or type_rvexc is not None: # at least one of the operations raised an exception: in # this case both operations should have raised the same # type of exception (division by zero, bit shift with a # floating point number operand, etc.) - self.assertIs(type(rexc), type(rvexc)) + self.assertIs(type_rexc, type_rvexc) return None, None return r, rv + # Tests that the unary operation `op` gives results with the same + # type for both `self._def` and `self._def_value`. def _test_unaryop_type(self, op): r, rv = self._unaryop(op) @@ -178,6 +212,9 @@ class _TestNumericField: self.assertIsInstance(r, type(rv)) + # Tests that the unary operation `op` gives results with the same + # value for both `self._def` and `self._def_value`. This uses the + # __eq__() operator of `self._def`. def _test_unaryop_value(self, op): r, rv = self._unaryop(op) @@ -186,16 +223,22 @@ class _TestNumericField: self.assertEqual(r, rv) + # Tests that the unary operation `op`, when applied to `self._def`, + # does not change its underlying BT object address. def _test_unaryop_addr_same(self, op): addr_before = self._def.addr self._unaryop(op) self.assertEqual(self._def.addr, addr_before) + # Tests that the unary operation `op`, when applied to `self._def`, + # does not change its value. def _test_unaryop_value_same(self, op): value_before = copy.copy(self._def_value) self._unaryop(op) self.assertEqual(self._def, value_before) + # Tests that the binary operation `op` gives results with the same + # type for both `self._def` and `self._def_value`. def _test_binop_type(self, op, rhs): r, rv = self._binop(op, rhs) @@ -208,6 +251,9 @@ class _TestNumericField: else: self.assertIsInstance(r, type(rv)) + # Tests that the binary operation `op` gives results with the same + # value for both `self._def` and `self._def_value`. This uses the + # __eq__() operator of `self._def`. def _test_binop_value(self, op, rhs): r, rv = self._binop(op, rhs) @@ -216,17 +262,36 @@ class _TestNumericField: self.assertEqual(r, rv) + # Tests that the binary operation `op`, when applied to `self._def`, + # does not change its underlying BT object address. def _test_binop_lhs_addr_same(self, op, rhs): addr_before = self._def.addr r, rv = self._binop(op, rhs) self.assertEqual(self._def.addr, addr_before) + # Tests that the binary operation `op`, when applied to `self._def`, + # does not change its value. @unittest.skip('copy is not implemented') def _test_binop_lhs_value_same(self, op, rhs): value_before = copy.copy(self._def) r, rv = self._binop(op, rhs) self.assertEqual(self._def, value_before) + # The methods below which take the `test_cb` and/or `op` parameters + # are meant to be used with one of the _test_binop_*() functions + # above as `test_cb` and a binary operator function as `op`. + # + # For example: + # + # self._test_binop_rhs_pos_int(self._test_binop_value, + # operator.add) + # + # This tests that a numeric field object added to a positive integer + # value gives a result with the expected value. + # + # `vint` and `vfloat` mean a signed integer value object and a real + # value object. + def _test_binop_invalid_unknown(self, op): if op in _COMP_BINOPS: self.skipTest('not testing') @@ -482,6 +547,11 @@ class _TestNumericField: self.assertTrue(self._def != None) # noqa: E711 +# This is a list of binary operators used for +# _inject_numeric_testing_methods(). +# +# Each entry is a pair of binary operator name (used as part of the +# created testing method's name) and operator function. _BINOPS = ( ('lt', operator.lt), ('le', operator.le), @@ -516,6 +586,11 @@ _BINOPS = ( ) +# This is a list of unary operators used for +# _inject_numeric_testing_methods(). +# +# Each entry is a pair of unary operator name (used as part of the +# created testing method's name) and operator function. _UNARYOPS = ( ('neg', operator.neg), ('pos', operator.pos), @@ -532,6 +607,20 @@ _UNARYOPS = ( ) +# This function injects a bunch of testing methods to a numeric +# field test case. +# +# It is meant to be used like this: +# +# _inject_numeric_testing_methods(MyNumericFieldTestCase) +# +# This function injects: +# +# * One testing method for each _TestNumericField._test_binop_*() +# method, for each binary operator in the _BINOPS tuple. +# +# * One testing method for each _TestNumericField._test_unaryop*() +# method, for each unary operator in the _UNARYOPS tuple. def _inject_numeric_testing_methods(cls): def test_binop_name(suffix): return 'test_binop_{}_{}'.format(name, suffix) diff --git a/tests/bindings/python/bt2/test_value.py b/tests/bindings/python/bt2/test_value.py index 6f66930e..a56f2c1e 100644 --- a/tests/bindings/python/bt2/test_value.py +++ b/tests/bindings/python/bt2/test_value.py @@ -25,6 +25,9 @@ import copy import bt2 +# The value object classes explicitly do not implement the copy methods, +# raising `NotImplementedError`, just in case we decide to implement +# them someday. class _TestCopySimple: def test_copy(self): with self.assertRaises(NotImplementedError): @@ -41,56 +44,90 @@ _COMP_BINOPS = ( ) +# Base class for numeric value test cases. +# +# To be compatible with this base class, a derived class must, in its +# setUp() method: +# +# * Set `self._def` to a value object with an arbitrary raw value. +# * Set `self._def_value` to the equivalent raw value of `self._def`. class _TestNumericValue(_TestCopySimple): + # Tries the binary operation `op`: + # + # 1. Between `self._def`, which is a value object, and `rhs`. + # 2. Between `self._def_value`, which is the raw value of + # `self._def`, and `rhs`. + # + # Returns the results of 1. and 2. + # + # If there's an exception while performing 1. or 2., asserts that + # both operations raised exceptions, that both exceptions have the + # same type, and returns `None` for both results. def _binop(self, op, rhs): - rexc = None - rvexc = None + type_rexc = None + type_rvexc = None comp_value = rhs + # try with value object try: r = op(self._def, rhs) except Exception as e: - rexc = e + type_rexc = type(e) + # try with raw value try: rv = op(self._def_value, comp_value) except Exception as e: - rvexc = e + type_rvexc = type(e) - if rexc is not None or rvexc is not None: + if type_rexc is not None or type_rvexc is not None: # at least one of the operations raised an exception: in # this case both operations should have raised the same # type of exception (division by zero, bit shift with a # floating point number operand, etc.) - self.assertIs(type(rexc), type(rvexc)) + self.assertIs(type_rexc, type_rvexc) return None, None return r, rv + # Tries the unary operation `op`: + # + # 1. On `self._def`, which is a value object. + # 2. On `self._def_value`, which is the raw value of `self._def`. + # + # Returns the results of 1. and 2. + # + # If there's an exception while performing 1. or 2., asserts that + # both operations raised exceptions, that both exceptions have the + # same type, and returns `None` for both results. def _unaryop(self, op): - rexc = None - rvexc = None + type_rexc = None + type_rvexc = None + # try with value object try: r = op(self._def) except Exception as e: - rexc = e + type_rexc = type(e) + # try with raw value try: rv = op(self._def_value) except Exception as e: - rvexc = e + type_rvexc = type(e) - if rexc is not None or rvexc is not None: + if type_rexc is not None or type_rvexc is not None: # at least one of the operations raised an exception: in # this case both operations should have raised the same # type of exception (division by zero, bit shift with a # floating point number operand, etc.) - self.assertIs(type(rexc), type(rvexc)) + self.assertIs(type_rexc, type_rvexc) return None, None return r, rv + # Tests that the unary operation `op` gives results with the same + # type for both `self._def` and `self._def_value`. def _test_unaryop_type(self, op): r, rv = self._unaryop(op) @@ -99,6 +136,9 @@ class _TestNumericValue(_TestCopySimple): self.assertIsInstance(r, type(rv)) + # Tests that the unary operation `op` gives results with the same + # value for both `self._def` and `self._def_value`. This uses the + # __eq__() operator of `self._def`. def _test_unaryop_value(self, op): r, rv = self._unaryop(op) @@ -107,16 +147,22 @@ class _TestNumericValue(_TestCopySimple): self.assertEqual(r, rv) + # Tests that the unary operation `op`, when applied to `self._def`, + # does not change its underlying BT object address. def _test_unaryop_addr_same(self, op): addr_before = self._def.addr self._unaryop(op) self.assertEqual(self._def.addr, addr_before) + # Tests that the unary operation `op`, when applied to `self._def`, + # does not change its value. def _test_unaryop_value_same(self, op): value_before = self._def.__class__(self._def) self._unaryop(op) self.assertEqual(self._def, value_before) + # Tests that the binary operation `op` gives results with the same + # type for both `self._def` and `self._def_value`. def _test_binop_type(self, op, rhs): r, rv = self._binop(op, rhs) @@ -129,6 +175,9 @@ class _TestNumericValue(_TestCopySimple): else: self.assertIsInstance(r, type(rv)) + # Tests that the binary operation `op` gives results with the same + # value for both `self._def` and `self._def_value`. This uses the + # __eq__() operator of `self._def`. def _test_binop_value(self, op, rhs): r, rv = self._binop(op, rhs) @@ -137,25 +186,41 @@ class _TestNumericValue(_TestCopySimple): self.assertEqual(r, rv) + # Tests that the binary operation `op`, when applied to `self._def`, + # does not change its underlying BT object address. def _test_binop_lhs_addr_same(self, op, rhs): addr_before = self._def.addr r, rv = self._binop(op, rhs) self.assertEqual(self._def.addr, addr_before) + # Tests that the binary operation `op`, when applied to `self._def`, + # does not change its value. def _test_binop_lhs_value_same(self, op, rhs): value_before = self._def.__class__(self._def) r, rv = self._binop(op, rhs) self.assertEqual(self._def, value_before) + # The methods below which take the `test_cb` and `op` parameters + # are meant to be used with one of the _test_binop_*() functions + # above as `test_cb` and a binary operator function as `op`. + # + # For example: + # + # self._test_binop_rhs_pos_int(self._test_binop_value, + # operator.add) + # + # This tests that a numeric value object added to a positive integer + # raw value gives a result with the expected value. + # + # `vint` and `vfloat` mean a signed integer value object and a real + # value object. + def _test_binop_invalid_unknown(self, op): if op in _COMP_BINOPS: self.skipTest('not testing') - class A: - pass - with self.assertRaises(TypeError): - op(self._def, A()) + op(self._def, object()) def _test_binop_invalid_none(self, op): if op in _COMP_BINOPS: @@ -396,6 +461,11 @@ class _TestNumericValue(_TestCopySimple): self.assertTrue(self._def != None) +# This is a list of binary operators used for +# _inject_numeric_testing_methods(). +# +# Each entry is a pair of binary operator name (used as part of the +# created testing method's name) and operator function. _BINOPS = ( ('lt', operator.lt), ('le', operator.le), @@ -430,6 +500,11 @@ _BINOPS = ( ) +# This is a list of unary operators used for +# _inject_numeric_testing_methods(). +# +# Each entry is a pair of unary operator name (used as part of the +# created testing method's name) and operator function. _UNARYOPS = ( ('neg', operator.neg), ('pos', operator.pos), @@ -446,6 +521,23 @@ _UNARYOPS = ( ) +# This function injects a bunch of testing methods to a numeric +# value test case. +# +# It is meant to be used like this: +# +# _inject_numeric_testing_methods(MyNumericValueTestCase) +# +# If `has_neg` is true, then the function injects testing methods which +# involve operations with a negative value. +# +# This function injects: +# +# * One testing method for each _TestNumericValue._test_binop_*() +# method, for each binary operator in the _BINOPS tuple. +# +# * One testing method for each _TestNumericValue._test_unaryop*() +# method, for each unary operator in the _UNARYOPS tuple. def _inject_numeric_testing_methods(cls, has_neg=True): def test_binop_name(suffix): return 'test_binop_{}_{}'.format(name, suffix)