Fix: bt2: correctly handle empty result of bt_field_enumeration_unsigned_get_mapping_...
authorSimon Marchi <simon.marchi@efficios.com>
Mon, 21 Oct 2024 18:20:01 +0000 (14:20 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Mon, 4 Nov 2024 16:17:44 +0000 (11:17 -0500)
When calling `_EnumerationFieldClassConst.mappings_for_value()` and the
result is empty (no matching mappings), we get:

      File "/home/smarchi/build/babeltrace/src/bindings/python/bt2/build/build_lib/bt2/field_class.py", line 240, in mappings_for_value
        return [self[label] for label in labels]
                                         ^^^^^^
    TypeError: 'NoneType' object is not iterable

Here's what happens:

 - When the input value matches no mappings, the library sets the array
   output parameter to `NULL`.
 - The SWIG argout typemap checks the array output parameter value to
   choose between returning a list or `None`.  So in this case, we return
   the tuple `(__BT_FUNC_STATUS_OK, None)`.
 - Back in the Python side, we try to iterate over `None`.

Fix this by checking the status in the typemap to see if the call
succeeded.

Add a corresponding test.

Change-Id: If1c7de435c27b9c37b67b66a7b8384480ac654e1
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/13385
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
src/bindings/python/bt2/bt2/native_bt_field_class.i
tests/bindings/python/bt2/test_field_class.py

index 72aaa9ca29ba118dd16ccb311bad7d824cf9189c..cfcd2234e8af7967e8a47cc77cd2578c69f23595 100644 (file)
@@ -14,7 +14,7 @@
 
 %typemap(argout)
        (bt_field_class_enumeration_mapping_label_array *labels, uint64_t *count) {
-       if (*$1) {
+       if (result == __BT_FUNC_STATUS_OK) {
                PyObject *py_label_list = PyList_New(*$2);
                uint64_t i;
 
index cb011a6e8c7ee511dfb987362f4128b795d971c8..c000424f8f0e7dcf22f8bfa98cf6ee04c70ab4ec 100644 (file)
@@ -388,6 +388,11 @@ class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
         expected_labels = set(["a", "c"])
         self.assertEqual(labels, expected_labels)
 
+    def test_find_by_value_none_found(self):
+        self._fc.add_mapping("a", self._ranges1)
+        mappings = self._fc.mappings_for_value(999999)
+        self.assertEqual(mappings, [])
+
 
 class UnsignedEnumerationFieldClassTestCase(
     _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
This page took 0.04253 seconds and 4 git commands to generate.