The documentation for the _add_input_port API functions state that there
must be no other input port with the same name. Ditto for output ports.
This patch adds some precondition checks for that. A failed assertion looks
like this:
04-09 16:29:23.968
2961462 2961462 F LIB/COMPONENT-SINK bt_self_component_sink_add_input_port@component-sink.c:132 Babeltrace 2 library precondition not satisfied; error is:
04-09 16:29:23.968
2961462 2961462 F LIB/COMPONENT-SINK bt_self_component_sink_add_input_port@component-sink.c:132 Input port name is not unique: name="bob", comp-addr=0x60c000001e40, comp-name="mon sink", comp-log-level=NONE, comp-class-type=SINK, comp-class-name="MySink", comp-class-partial-descr=""
04-09 16:29:23.968
2961462 2961462 F LIB/COMPONENT-SINK bt_self_component_sink_add_input_port@component-sink.c:132 Aborting...
Equivalent checks are added to the Python bindings, as well as tests.
Change-Id: I12f5a16b6b5efc46f2b50f27e338cc57b8487ff6
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/3387
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Tested-by: jenkins <jenkins@lttng.org>
def _add_output_port(self, name, user_data=None):
utils._check_str(name)
def _add_output_port(self, name, user_data=None):
utils._check_str(name)
+
+ if name in self._output_ports:
+ raise ValueError(
+ 'source component `{}` already contains an output port named `{}`'.format(
+ self.name, name
+ )
+ )
+
fn = native_bt.self_component_source_add_output_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
fn = native_bt.self_component_source_add_output_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
def _add_output_port(self, name, user_data=None):
utils._check_str(name)
def _add_output_port(self, name, user_data=None):
utils._check_str(name)
+
+ if name in self._output_ports:
+ raise ValueError(
+ 'filter component `{}` already contains an output port named `{}`'.format(
+ self.name, name
+ )
+ )
+
fn = native_bt.self_component_filter_add_output_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
fn = native_bt.self_component_filter_add_output_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
def _add_input_port(self, name, user_data=None):
utils._check_str(name)
def _add_input_port(self, name, user_data=None):
utils._check_str(name)
+
+ if name in self._input_ports:
+ raise ValueError(
+ 'filter component `{}` already contains an input port named `{}`'.format(
+ self.name, name
+ )
+ )
+
fn = native_bt.self_component_filter_add_input_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
fn = native_bt.self_component_filter_add_input_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
def _add_input_port(self, name, user_data=None):
utils._check_str(name)
def _add_input_port(self, name, user_data=None):
utils._check_str(name)
+
+ if name in self._input_ports:
+ raise ValueError(
+ 'sink component `{}` already contains an input port named `{}`'.format(
+ self.name, name
+ )
+ )
+
fn = native_bt.self_component_sink_add_input_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
fn = native_bt.self_component_sink_add_input_port
comp_status, self_port_ptr = fn(self._bt_ptr, name, user_data)
utils._handle_func_status(
struct bt_port *port = NULL;
BT_ASSERT_PRE_NO_ERROR();
struct bt_port *port = NULL;
BT_ASSERT_PRE_NO_ERROR();
+ BT_ASSERT_PRE_OUTPUT_PORT_NAME_UNIQUE(comp, name);
/* bt_component_add_output_port() logs details and errors */
status = bt_component_add_output_port(comp, name, user_data, &port);
/* bt_component_add_output_port() logs details and errors */
status = bt_component_add_output_port(comp, name, user_data, &port);
struct bt_component *comp = (void *) self_comp;
BT_ASSERT_PRE_NO_ERROR();
struct bt_component *comp = (void *) self_comp;
BT_ASSERT_PRE_NO_ERROR();
+ BT_ASSERT_PRE_INPUT_PORT_NAME_UNIQUE(comp, name);
/* bt_component_add_input_port() logs details/errors */
status = bt_component_add_input_port(comp, name, user_data, &port);
/* bt_component_add_input_port() logs details/errors */
status = bt_component_add_input_port(comp, name, user_data, &port);
struct bt_component *comp = (void *) self_comp;
BT_ASSERT_PRE_NO_ERROR();
struct bt_component *comp = (void *) self_comp;
BT_ASSERT_PRE_NO_ERROR();
+ BT_ASSERT_PRE_INPUT_PORT_NAME_UNIQUE(comp, name);
/* bt_component_add_input_port() logs details/errors */
status = bt_component_add_input_port(comp, name, user_data, &port);
/* bt_component_add_input_port() logs details/errors */
status = bt_component_add_input_port(comp, name, user_data, &port);
struct bt_port *port = NULL;
BT_ASSERT_PRE_NO_ERROR();
struct bt_port *port = NULL;
BT_ASSERT_PRE_NO_ERROR();
+ BT_ASSERT_PRE_OUTPUT_PORT_NAME_UNIQUE(comp, name);
/* bt_component_add_output_port() logs details and errors */
status = bt_component_add_output_port(comp, name, user_data, &port);
/* bt_component_add_output_port() logs details and errors */
status = bt_component_add_output_port(comp, name, user_data, &port);
BT_PORT_TYPE_OUTPUT, name, user_data, port);
}
BT_PORT_TYPE_OUTPUT, name, user_data, port);
}
+BT_HIDDEN
+bool bt_component_port_name_is_unique(GPtrArray *ports, const char *name)
+{
+ guint i;
+ bool unique;
+
+ for (i = 0; i < ports->len; i++) {
+ struct bt_port *port = g_ptr_array_index(ports, i);
+
+ if (strcmp(port->name->str, name) == 0) {
+ unique = false;
+ goto end;
+ }
+ }
+
+ unique = true;
+
+end:
+ return unique;
+}
+
BT_HIDDEN
enum bt_component_class_port_connected_method_status
bt_component_port_connected(
BT_HIDDEN
enum bt_component_class_port_connected_method_status
bt_component_port_connected(
#include "component-class.h"
#include "port.h"
#include "component-class.h"
#include "port.h"
+#define BT_ASSERT_PRE_INPUT_PORT_NAME_UNIQUE(comp, name) \
+ BT_ASSERT_PRE(bt_component_port_name_is_unique(comp->input_ports, name), \
+ "Input port name is not unique: name=\"%s\", %![comp-]c", name, comp);
+
+#define BT_ASSERT_PRE_OUTPUT_PORT_NAME_UNIQUE(comp, name) \
+ BT_ASSERT_PRE(bt_component_port_name_is_unique(comp->output_ports, name), \
+ "Output port name is not unique: name=\"%s\", %![comp-]c", name, comp);
+
typedef void (*bt_component_destroy_listener_func)(
struct bt_component *class, void *data);
typedef void (*bt_component_destroy_listener_func)(
struct bt_component *class, void *data);
struct bt_component *component, const char *name,
void *user_data, struct bt_port **port);
struct bt_component *component, const char *name,
void *user_data, struct bt_port **port);
+BT_HIDDEN
+bool bt_component_port_name_is_unique(GPtrArray *ports, const char *name);
+
BT_HIDDEN
void bt_component_remove_port(struct bt_component *component,
struct bt_port *port);
BT_HIDDEN
void bt_component_remove_port(struct bt_component *component,
struct bt_port *port);
self.assertEqual(len(comp.output_ports), 1)
self.assertIs(type(comp.output_ports['out']), bt2_port._OutputPortConst)
self.assertEqual(len(comp.output_ports), 1)
self.assertIs(type(comp.output_ports['out']), bt2_port._OutputPortConst)
+ # Test adding output port with duplicate name to source.
+ def test_src_add_output_port_dup_name_raises(self):
+ class MySource(
+ bt2._UserSourceComponent, message_iterator_class=bt2._UserMessageIterator
+ ):
+ def __init__(comp_self, config, params, obj):
+ comp_self._add_output_port('out')
+
+ with self.assertRaisesRegex(
+ ValueError,
+ "source component `comp` already contains an output port named `out`",
+ ):
+ comp_self._add_output_port('out')
+
+ nonlocal seen
+ seen = True
+
+ seen = False
+ self._create_comp(MySource)
+ self.assertTrue(seen)
+
def test_flt_add_output_port(self):
class MyFilter(
bt2._UserFilterComponent, message_iterator_class=bt2._UserMessageIterator
def test_flt_add_output_port(self):
class MyFilter(
bt2._UserFilterComponent, message_iterator_class=bt2._UserMessageIterator
comp = self._create_comp(MyFilter)
self.assertEqual(len(comp.output_ports), 1)
comp = self._create_comp(MyFilter)
self.assertEqual(len(comp.output_ports), 1)
+ # Test adding output port with duplicate name to filter.
+ def test_flt_add_output_port_dup_name_raises(self):
+ class MyFilter(
+ bt2._UserFilterComponent, message_iterator_class=bt2._UserMessageIterator
+ ):
+ def __init__(comp_self, config, params, obj):
+ comp_self._add_output_port('out')
+
+ with self.assertRaisesRegex(
+ ValueError,
+ "filter component `comp` already contains an output port named `out`",
+ ):
+ comp_self._add_output_port('out')
+
+ nonlocal seen
+ seen = True
+
+ seen = False
+ self._create_comp(MyFilter)
+ self.assertTrue(seen)
+
def test_flt_add_input_port(self):
class MyFilter(
bt2._UserFilterComponent, message_iterator_class=bt2._UserMessageIterator
def test_flt_add_input_port(self):
class MyFilter(
bt2._UserFilterComponent, message_iterator_class=bt2._UserMessageIterator
self.assertEqual(len(comp.input_ports), 1)
self.assertIs(type(comp.input_ports['in']), bt2_port._InputPortConst)
self.assertEqual(len(comp.input_ports), 1)
self.assertIs(type(comp.input_ports['in']), bt2_port._InputPortConst)
+ # Test adding input port with duplicate name to filter.
+ def test_flt_add_input_port_dup_name_raises(self):
+ class MyFilter(
+ bt2._UserFilterComponent, message_iterator_class=bt2._UserMessageIterator
+ ):
+ def __init__(comp_self, config, params, obj):
+ comp_self._add_input_port('in')
+
+ with self.assertRaisesRegex(
+ ValueError,
+ "filter component `comp` already contains an input port named `in`",
+ ):
+ comp_self._add_input_port('in')
+
+ nonlocal seen
+ seen = True
+
+ seen = False
+ self._create_comp(MyFilter)
+ self.assertTrue(seen)
+
def test_sink_add_input_port(self):
class MySink(bt2._UserSinkComponent):
def __init__(comp_self, config, params, obj):
def test_sink_add_input_port(self):
class MySink(bt2._UserSinkComponent):
def __init__(comp_self, config, params, obj):
comp = self._create_comp(MySink)
self.assertEqual(len(comp.input_ports), 1)
comp = self._create_comp(MySink)
self.assertEqual(len(comp.input_ports), 1)
+ # Test adding input port with duplicate name to sink.
+ def test_sink_add_input_port_dup_name_raises(self):
+ class MySink(bt2._UserSinkComponent):
+ def __init__(comp_self, config, params, obj):
+ comp_self._add_input_port('in')
+
+ with self.assertRaisesRegex(
+ ValueError,
+ "sink component `comp` already contains an input port named `in`",
+ ):
+ comp_self._add_input_port('in')
+
+ nonlocal seen
+ seen = True
+
+ def _user_consume(self):
+ pass
+
+ seen = False
+ self._create_comp(MySink)
+ self.assertTrue(seen)
+
def test_user_src_output_ports_getitem(self):
class MySource(
bt2._UserSourceComponent, message_iterator_class=bt2._UserMessageIterator
def test_user_src_output_ports_getitem(self):
class MySource(
bt2._UserSourceComponent, message_iterator_class=bt2._UserMessageIterator