[PATCH v2] N-ary event operators

Casey Dahlin cdahlin at redhat.com
Thu Aug 13 04:53:53 BST 2009


This should address most of the issues. I might have missed some, and 
theres a few I'll need clarified. Go ahead and look though. (Also note
that the ChangeLog update is no longer complete).

=== modified file 'ChangeLog'
--- ChangeLog	2009-08-04 08:51:25 +0000
+++ ChangeLog	2009-08-13 00:01:12 +0000
@@ -1,3 +1,42 @@
+2009-08-11  Casey Dahlin  <cdahlin at redhat.com>
+
+	* init/event_operator.h (EventOperatorType): Change types from AND/OR
+	to ANY/ALL
+	(EventOperator): Get rid of node entry and add children list.
+	* init/event_operator.c (event_operator_subtree_environment): New
+	version of event_operator_environment that assumes we are not at the
+	root of the tree.
+	(event_operator_new): Initialize new children member instead of tree
+	node.
+	(event_operator_copy): Use recursive call to correctly copy N-ary tree
+	(event_operator_reset): Use recursive call to correctly reset N-ary
+	tree
+	(event_operator_events): Use recursive call to correctly get events
+	from N-ary tree.
+	(event_operator_handle): Use recursive call to correctly handle N-ary
+	tree.
+	(event_operator_update): Update based on all N children
+	(event_operator_match): Don't assert based on now-defunct node
+	(event_operator_add_child): New helper to add a child to a tree,
+	automatically collapsing it into its new parent if it is the same type.
+	(event_operator_destroy): Destroy children list head correctly.
+	(event_operator_environment): Use new
+	event_operator_subtree_environment to recursively collect environment
+	variables.
+	* init/parse_job.c (parse_on_operator): Change AND/OR to ANY/ALL.
+	Change tree adds to event_operator_add_child calls.
+	(parse_on_collect): Change tree adds to event_operator_add_child calls
+	* init/tests/test_event.c (test_pending_handle_jobs): Fix structural
+	assumptions about EventOperator.
+	(test_finish): Change AND/OR to ANY/ALL
+	* init/tests/test_event_operator.c (everywhere): Fix structural
+	assumptions about EventOperator.
+	(test_operator_add_child): New test for this new helper.
+	* init/tests/test_job_process.c (everywhere): Fix structural
+	assumptions about EventOperator
+	* init/tests/test_parse_job.c (everywhere): Fix structural assumptions
+	about EventOperator
+
  2009-08-04  Johan Kiviniemi  <johan at kiviniemi.name>

  	* conf/rc-sysinit.conf: Don't replace DEFAULT_RUNLEVEL with an

=== modified file 'init/event_operator.c'
--- init/event_operator.c	2009-06-23 09:29:35 +0000
+++ init/event_operator.c	2009-08-13 00:39:09 +0000
@@ -44,6 +44,11 @@
  #include "errors.h"


+static char **event_operator_subtree_environment (EventOperator *oper,
+		char ***env, const void *parent, size_t *len, const char *key,
+		char **evlist);
+
+
  /**
   * event_operator_new:
   * @parent: parent object for new operator,
@@ -85,7 +90,8 @@ event_operator_new (const void         *
  	if (! oper)
  		return NULL;

-	nih_tree_init (&oper->node);
+	nih_list_init (&oper->entry);
+	nih_list_init (&oper->children);

  	oper->type = type;
  	oper->value = FALSE;
@@ -163,30 +169,54 @@ event_operator_copy (const void
  		event_block (oper->event);
  	}

-	if (old_oper->node.left) {
-		child = event_operator_copy (
-			oper, (EventOperator *)old_oper->node.left);
+	NIH_LIST_FOREACH (&old_oper->children, iter) {
+		EventOperator *old_child = (EventOperator *)iter;
+		EventOperator *child;
+
+		child = event_operator_copy (oper, old_child);
  		if (! child) {
  			nih_free (oper);
  			return NULL;
  		}

-		nih_tree_add (&oper->node, &child->node, NIH_TREE_LEFT);
+		event_operator_add_child (oper, child);
  	}

+	return oper;
+}

-	if (old_oper->node.right) {
-		child = event_operator_copy (
-			oper, (EventOperator *)old_oper->node.right);
-		if (! child) {
-			nih_free (oper);
-			return NULL;
-		}
+/**
+ * event_operator_add_child:
+ * @oper: oper to add child to,
+ * @child: child to add.
+ *
+ * Makes @child a child of @oper. If @child and @oper are the same 
type, then
+ * @oper simply steals all of @child's children.
+ *
+ * @child may be referenced by the new parent, and if it is not, it is 
in an
+ * undefined state at the end of the operation. Consequently all other
+ * references to child should be dropped after this call.
+ **/
+void
+event_operator_add_child (EventOperator *oper, EventOperator *child)
+{
+	nih_assert (oper != NULL);
+	nih_assert (child != NULL);
+	nih_assert (oper->type != EVENT_MATCH);

-		nih_tree_add (&oper->node, &child->node, NIH_TREE_RIGHT);
+	if (child->type != oper->type) {
+		nih_ref (child, oper);
+		nih_list_add (&oper->children, &child->entry);
+		return;
  	}

-	return oper;
+	NIH_LIST_FOREACH_SAFE (&child->children, iter) {
+		EventOperator *grandchild = (EventOperator *)iter;
+
+		nih_ref (grandchild, oper);
+		nih_unref (grandchild, child);
+		nih_list_add (&oper->children, &grandchild->entry);
+	}
  }

  /**
@@ -209,7 +239,7 @@ event_operator_destroy (EventOperator *o
  	if (oper->event)
  		event_unblock (oper->event);

-	nih_tree_destroy (&oper->node);
+	nih_list_destroy (&oper->entry);

  	return 0;
  }
@@ -223,28 +253,29 @@ event_operator_destroy (EventOperator *o
   * when combined with the particular operation this represents.
   *
   * This may only be called if the type of @oper is EVENT_OR or EVENT_AND.
+ *
+ * If @oper is of type EVENT_OR the function will set its value to 
FALSE, then
+ * scan the children. If it finds one child with a value of TRUE it 
will set
+ * @oper's value to TRUE and return.
+ *
+ * For EVENT_AND the procedure is reversed. @oper is given a value of 
TRUE, and
+ * is changed to FALSE if one FALSE child is discovered.
   **/
  void
  event_operator_update (EventOperator *oper)
  {
-	EventOperator *left, *right;
-
  	nih_assert (oper != NULL);
-	nih_assert (oper->node.left != NULL);
-	nih_assert (oper->node.right != NULL);
+	nih_assert (oper->type != EVENT_MATCH);

-	left = (EventOperator *)oper->node.left;
-	right = (EventOperator *)oper->node.right;
+	oper->value = (oper->type == EVENT_AND) ? TRUE : FALSE;

-	switch (oper->type) {
-	case EVENT_OR:
-		oper->value = (left->value || right->value);
-		break;
-	case EVENT_AND:
-		oper->value = (left->value && right->value);
-		break;
-	default:
-		nih_assert_not_reached ();
+	NIH_LIST_FOREACH (&oper->children, iter) {
+		EventOperator *child = (EventOperator *)iter;
+
+		if (child->value != oper->value) {
+			oper->value = child->value;
+			return;
+		}
  	}
  }

@@ -280,8 +311,6 @@ event_operator_match (EventOperator *ope

  	nih_assert (oper != NULL);
  	nih_assert (oper->type == EVENT_MATCH);
-	nih_assert (oper->node.left == NULL);
-	nih_assert (oper->node.right == NULL);
  	nih_assert (event != NULL);

  	/* Names must match */
@@ -391,29 +420,30 @@ event_operator_handle (EventOperator *ro
  	 * before we update the node itself.  Simply iterate the tree and
  	 * update the nodes.
  	 */
-	NIH_TREE_FOREACH_POST (&root->node, iter) {
+	NIH_LIST_FOREACH (&root->children, iter) {
  		EventOperator *oper = (EventOperator *)iter;

-		switch (oper->type) {
-		case EVENT_OR:
-		case EVENT_AND:
-			event_operator_update (oper);
-			break;
-		case EVENT_MATCH:
-			if ((! oper->value)
-			    && event_operator_match (oper, event, env)) {
-				oper->value = TRUE;
+		ret = ret || event_operator_handle (oper, event, env);
+	}

-				oper->event = event;
-				event_block (oper->event);
+	switch (root->type) {
+	case EVENT_OR:
+	case EVENT_AND:
+		event_operator_update (root);
+		break;
+	case EVENT_MATCH:
+		if ((! root->value)
+		    && event_operator_match (root, event, env)) {
+			root->value = TRUE;

-				ret = TRUE;
-			}
-			break;
-		default:
-			nih_assert_not_reached ();
-		}
+			root->event = event;
+			event_block (root->event);

+			ret = TRUE;
+		}
+		break;
+	default:
+		nih_assert_not_reached ();
  	}

  	return ret;
@@ -501,44 +531,77 @@ event_operator_environment (EventOperato
  			return NULL;
  	}

-	/* Iterate the operator tree, filtering out nodes with a non-TRUE
-	 * value and their children.  The rationale for this is that this
-	 * then matches only the events that had an active role in starting
-	 * the job, not the ones that were also blocked, but the other half
-	 * of their logic wasn't present.
+	if (! event_operator_subtree_environment (root, env, parent,
+					          len, key, &evlist))
+		return NULL;
+
+	/* Append the event list to the environment */
+	if (evlist)
+		if (! environ_add (env, parent, len, TRUE, evlist))
+			return NULL;
+
+	return *env;
+}
+
+/**
+ * event_operator_subtree_environment:
+ * @root: operator tree to collect from,
+ * @env: NULL-terminated array of environment variables to add to,
+ * @parent: parent object for new array,
+ * @len: length of @env,
+ * @key: key of variable to contain event names,
+ * @evlist: string in which to accumulate the event list.
+ *
+ * Does the work of event_operator_environment for one subtree.
+ **/
+
+static char**
+event_operator_subtree_environment (EventOperator   *oper,
+				    char          ***env,
+				    const void      *parent,
+				    size_t          *len,
+				    const char      *key,
+				    char           **evlist)
+{
+	/* Filtering out nodes with a non-TRUE value and their children. The
+	 * rationale for this is that this then matches only the events that had
+	 * an active role in starting the job, not the ones that were also
+	 * blocked, but the other half of their logic wasn't present.
  	 */
-	NIH_TREE_FOREACH_FULL (&root->node, iter,
-			       (NihTreeFilter)event_operator_filter, NULL) {
-		EventOperator *oper = (EventOperator *)iter;
+	if (! oper->value)
+		return *env;

-		if (oper->type != EVENT_MATCH)
-			continue;
+	if (oper->type != EVENT_MATCH) {
+		NIH_LIST_FOREACH(&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+			if (! event_operator_subtree_environment (child, env, parent,
+							          len, key, evlist))
+				return NULL;
+		}

-		nih_assert (oper->event != NULL);
+		return *env;
+	}

-		/* Add environment from the event */
-		if (! environ_append (env, parent, len, TRUE, oper->event->env))
-			return NULL;
+	nih_assert (oper->event != NULL);
+
+	/* Add environment from the event */
+	if (! environ_append (env, parent, len, TRUE, oper->event->env))
+		return NULL;

-		/* Append the name of the event to the string we're building */
-		if (evlist) {
-			if (evlist[strlen (evlist) - 1] != '=') {
-				if (! nih_strcat_sprintf (&evlist, NULL, " %s",
-							  oper->event->name))
-					return NULL;
-			} else {
-				if (! nih_strcat (&evlist, NULL,
+	/* Append the name of the event to the string we're building */
+	if (*evlist) {
+		if ((*evlist)[strlen (*evlist) - 1] != '=') {
+			if (! nih_strcat_sprintf (evlist, NULL, " %s",
  						  oper->event->name))
-					return NULL;
+				return NULL;
+		} else {
+			if (! nih_strcat (evlist, NULL,
+					  oper->event->name)) {
+				return NULL;
  			}
  		}
  	}

-	/* Append the event list to the environment */
-	if (evlist)
-		if (! environ_add (env, parent, len, TRUE, evlist))
-			return NULL;
-
  	return *env;
  }

@@ -564,31 +627,31 @@ event_operator_events (EventOperator *ro
  		       const void    *parent,
  		       NihList       *list)
  {
+	Blocked       *blocked;
+
  	nih_assert (root != NULL);
  	nih_assert (list != NULL);

-	/* Iterate the operator tree, filtering out nodes with a non-TRUE
-	 * value and their children.  The rationale for this is that this
-	 * then matches only the events that had an active role in starting
-	 * the job, not the ones that were also blocked, but the other half
-	 * of their logic wasn't present.
-	 */
-	NIH_TREE_FOREACH_FULL (&root->node, iter,
-			       (NihTreeFilter)event_operator_filter, NULL) {
+	if (! root->value)
+		return;
+
+	NIH_LIST_FOREACH (&root->children, iter) {
  		EventOperator *oper = (EventOperator *)iter;
-		Blocked       *blocked;

-		if (oper->type != EVENT_MATCH)
-			continue;
+		event_operator_events (oper, parent, list);
+	}

-		nih_assert (oper->event != NULL);

-		blocked = NIH_MUST (blocked_new (parent, BLOCKED_EVENT,
-						 oper->event));
-		nih_list_add (list, &blocked->entry);
+	if (root->type != EVENT_MATCH)
+		return;

-		event_block (blocked->event);
-	}
+	nih_assert (root->event != NULL);
+
+	blocked = NIH_MUST (blocked_new (parent, BLOCKED_EVENT,
+					 root->event));
+	nih_list_add (list, &blocked->entry);
+
+	event_block (blocked->event);
  }


@@ -606,24 +669,26 @@ event_operator_reset (EventOperator *roo
  	nih_assert (root != NULL);

  	/* A post-order iteration means we visit children first, perfect! */
-	NIH_TREE_FOREACH_POST (&root->node, iter) {
+	NIH_LIST_FOREACH (&root->children, iter) {
  		EventOperator *oper = (EventOperator *)iter;

-		switch (oper->type) {
-		case EVENT_OR:
-		case EVENT_AND:
-			event_operator_update (oper);
-			break;
-		case EVENT_MATCH:
-			oper->value = FALSE;
-
-			if (oper->event) {
-				event_unblock (oper->event);
-				oper->event = NULL;
-			}
-			break;
-		default:
-			nih_assert_not_reached ();
+		event_operator_reset (oper);
+	}
+
+	switch (root->type) {
+	case EVENT_OR:
+	case EVENT_AND:
+		event_operator_update (root);
+		break;
+	case EVENT_MATCH:
+		root->value = FALSE;
+
+		if (root->event) {
+			event_unblock (root->event);
+			root->event = NULL;
  		}
+		break;
+	default:
+		nih_assert_not_reached ();
  	}
  }

=== modified file 'init/event_operator.h'
--- init/event_operator.h	2009-06-23 09:29:35 +0000
+++ init/event_operator.h	2009-08-13 00:39:09 +0000
@@ -40,7 +40,8 @@ typedef enum event_operator_type {

  /**
   * EventOperator:
- * @node: tree node,
+ * @entry: sibling list entry,
+ * @children: list of children,
   * @type: operator type,
   * @value: operator value,
   * @name: name of event to match (EVENT_MATCH only),
@@ -50,18 +51,19 @@ typedef enum event_operator_type {
   * This structure is used to build up an event expression tree; the leaf
   * nodes are all of EVENT_MATCH type which match a specific event, the 
other
   * nodes are built up of EVENT_OR and EVENT_AND operators that combine the
- * EventOperators to their left and right in interesting ways.
+ * EventOperators which are their children in interesting ways.
   *
   * @value indicates whether this operator is currently TRUE or FALSE.
   * For EVENT_MATCH operators, a TRUE @value means that @event is set to
   * the matched event; for EVENT_OR and EVENT_AND operators, @value is set
- * depending on the value of both immediate children.
+ * depending on the value of the immediate children.
   *
   * Once an event has been matched, the @event member is set and a 
reference
   * held until the structure is cleared.
   **/
  typedef struct event_operator {
-	NihTree             node;
+	NihList             entry;
+	NihList             children;
  	EventOperatorType   type;

  	int                 value;
@@ -84,6 +86,8 @@ EventOperator *event_operator_copy
  	__attribute__ ((warn_unused_result, malloc));

  int            event_operator_destroy     (EventOperator *oper);
+void           event_operator_add_child   (EventOperator *oper,
+		                           EventOperator *child);

  void           event_operator_update      (EventOperator *oper);
  int            event_operator_match       (EventOperator *oper, Event 
*event,

=== modified file 'init/parse_job.c'
--- init/parse_job.c	2009-07-09 11:01:53 +0000
+++ init/parse_job.c	2009-08-13 00:39:09 +0000
@@ -665,10 +665,8 @@ parse_on_operator (JobClass         *cla
  	if (! oper)
  		nih_return_system_error (-1);

-	nih_ref (*root, oper);
+	event_operator_add_child (oper, *root);
  	nih_unref (*root, class);
-
-	nih_tree_add (&oper->node, &(*root)->node, NIH_TREE_LEFT);
  	*root = NULL;

  	/* Push the new operator onto the stack */
@@ -938,11 +936,8 @@ parse_on_collect (JobClass       *class,
  		 * event matches.
  		 */
  		if ((oper->type != EVENT_MATCH) && (*root)) {
-			nih_ref (*root, oper);
+			event_operator_add_child (oper, *root);
  			nih_unref (*root, class);
-
-			nih_tree_add (&oper->node, &(*root)->node,
-				      NIH_TREE_RIGHT);
  		} else if (oper->type != EVENT_MATCH) {
  			nih_return_error (-1, PARSE_EXPECTED_EVENT,
  					  _(PARSE_EXPECTED_EVENT_STR));

=== modified file 'init/tests/test_event.c'
--- init/tests/test_event.c	2009-08-04 00:19:41 +0000
+++ init/tests/test_event.c	2009-08-13 00:49:35 +0000
@@ -76,7 +76,7 @@ test_new (void)
  		TEST_LIST_NOT_EMPTY (&event->entry);

  		TEST_EQ (event->progress, EVENT_PENDING);
-		TEST_EQ (event->failed, FALSE);
+		TEST_FALSE (event->failed);

  		TEST_EQ (event->blockers, 0);
  		TEST_LIST_EMPTY (&event->blocking);
@@ -275,6 +275,7 @@ test_pending_handle_jobs (void)
  	EventOperator  *oper;
  	Blocked        *blocked = NULL, *blocked1 = NULL, *blocked2 = NULL;
  	char          **env1 = NULL, **env2 = NULL;
+	int             any_true = FALSE, all_true = TRUE;

  	TEST_FUNCTION ("event_pending_handle_jobs");
  	program_name = "test";
@@ -308,7 +309,7 @@ test_pending_handle_jobs (void)
  		TEST_HASH_EMPTY (class->instances);

  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

  		nih_free (class);
@@ -335,13 +336,11 @@ test_pending_handle_jobs (void)

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wibble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_LEFT);
+			event_operator_add_child (class->start_on, oper);

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wobble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_RIGHT);
+			event_operator_add_child (class->start_on, oper);

  			nih_hash_add (job_classes, &class->entry);
  		}
@@ -355,16 +354,21 @@ test_pending_handle_jobs (void)
  		TEST_HASH_EMPTY (class->instances);

  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

-		oper = (EventOperator *)class->start_on->node.left;
-		TEST_EQ (oper->value, TRUE);
-		TEST_EQ_P (oper->event, event1);
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;

-		oper = (EventOperator *)class->start_on->node.right;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+			any_true = any_true || child->value;
+			all_true = all_true && child->value;
+		}
+
+		TEST_TRUE (any_true);
+		TEST_FALSE (all_true);
+		
+		any_true = FALSE;
+		all_true = TRUE;

  		nih_free (class);
  		nih_free (event1);
@@ -399,13 +403,11 @@ test_pending_handle_jobs (void)

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wibble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_LEFT);
+			event_operator_add_child (class->start_on, oper);

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wobble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_RIGHT);
+			event_operator_add_child (class->start_on, oper);

  			nih_hash_add (job_classes, &class->entry);
  		}
@@ -444,17 +446,21 @@ test_pending_handle_jobs (void)


  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

-		oper = (EventOperator *)class->start_on->node.left;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;

-		oper = (EventOperator *)class->start_on->node.right;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+			any_true = any_true || child->value;
+			all_true = all_true && child->value;
+		}

+		TEST_FALSE (any_true);
+		TEST_FALSE (all_true);
+		
+		any_true = FALSE;
+		all_true = TRUE;

  		TEST_LIST_NOT_EMPTY (&job->blocking);

@@ -515,13 +521,11 @@ test_pending_handle_jobs (void)

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wibble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_LEFT);
+			event_operator_add_child (class->start_on, oper);

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wobble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_RIGHT);
+			event_operator_add_child (class->start_on, oper);

  			nih_hash_add (job_classes, &class->entry);
  		}
@@ -570,15 +574,20 @@ test_pending_handle_jobs (void)


  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);

-		oper = (EventOperator *)class->start_on->node.left;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;

-		oper = (EventOperator *)class->start_on->node.right;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+			any_true = any_true || child->value;
+			all_true = all_true && child->value;
+		}
+
+		TEST_FALSE (any_true);
+		TEST_FALSE (all_true);
+		
+		any_true = FALSE;
+		all_true = TRUE;


  		TEST_LIST_NOT_EMPTY (&job->blocking);
@@ -641,13 +650,11 @@ test_pending_handle_jobs (void)

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wibble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_LEFT);
+			event_operator_add_child (class->start_on, oper);

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wobble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_RIGHT);
+			event_operator_add_child (class->start_on, oper);

  			nih_hash_add (job_classes, &class->entry);

@@ -734,15 +741,20 @@ test_pending_handle_jobs (void)
  		TEST_EQ_P (job->start_env[8], NULL);

  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);

-		oper = (EventOperator *)class->start_on->node.left;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;

-		oper = (EventOperator *)class->start_on->node.right;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+			any_true = any_true || child->value;
+			all_true = all_true && child->value;
+		}
+
+		TEST_FALSE (any_true);
+		TEST_FALSE (all_true);
+		
+		any_true = FALSE;
+		all_true = TRUE;

  		TEST_FREE (blocked1);
  		TEST_FREE (blocked2);
@@ -809,13 +821,11 @@ test_pending_handle_jobs (void)

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wibble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_LEFT);
+			event_operator_add_child (class->start_on, oper);

  			oper = event_operator_new (
  				class->start_on, EVENT_MATCH, "wobble", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_RIGHT);
+			event_operator_add_child (class->start_on, oper);

  			nih_hash_add (job_classes, &class->entry);

@@ -884,15 +894,20 @@ test_pending_handle_jobs (void)
  		TEST_EQ_P (job->start_env, env2);

  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);

-		oper = (EventOperator *)class->start_on->node.left;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;

-		oper = (EventOperator *)class->start_on->node.right;
-		TEST_EQ (oper->value, FALSE);
-		TEST_EQ_P (oper->event, NULL);
+			any_true = any_true || child->value;
+			all_true = all_true && child->value;
+		}
+
+		TEST_FALSE (any_true);
+		TEST_FALSE (all_true);
+		
+		any_true = FALSE;
+		all_true = TRUE;

  		TEST_LIST_NOT_EMPTY (&job->blocking);
  		TEST_NOT_FREE (blocked1);
@@ -966,7 +981,7 @@ test_pending_handle_jobs (void)


  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);


@@ -1046,7 +1061,7 @@ test_pending_handle_jobs (void)
  		TEST_EQ (job->state, JOB_STOPPING);

  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

  		TEST_FREE (event3);
@@ -1104,7 +1119,7 @@ test_pending_handle_jobs (void)
  		TEST_HASH_EMPTY (class->instances);

  		oper = class->start_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

  		TEST_FILE_EQ (output, ("test: Failed to obtain test instance: "
@@ -1152,11 +1167,11 @@ test_pending_handle_jobs (void)
  		job = (Job *)nih_hash_lookup (class->instances, "");

  		oper = job->stop_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

  		oper = class->stop_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

  		nih_free (class);
@@ -1216,7 +1231,7 @@ test_pending_handle_jobs (void)


  		oper = job->stop_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);


@@ -1295,7 +1310,7 @@ test_pending_handle_jobs (void)


  		oper = job->stop_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);


@@ -1400,7 +1415,7 @@ test_pending_handle_jobs (void)


  		oper = job->stop_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);


@@ -1494,7 +1509,7 @@ test_pending_handle_jobs (void)
  		TEST_EQ_P (job->stop_env, env1);

  		oper = job->stop_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);

  		TEST_NOT_FREE (event3);
@@ -1578,7 +1593,7 @@ test_pending_handle_jobs (void)


  		oper = job->stop_on;
-		TEST_EQ (oper->value, FALSE);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->event, NULL);


@@ -1708,13 +1723,11 @@ test_finished (void)

  			oper = event_operator_new (class, EVENT_MATCH,
  						   "test/failed", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_LEFT);
+			event_operator_add_child (class->start_on, oper);

  			oper = event_operator_new (class, EVENT_MATCH,
  						   "test/failed/failed", NULL);
-			nih_tree_add (&class->start_on->node, &oper->node,
-				      NIH_TREE_RIGHT);
+			event_operator_add_child (class->start_on, oper);

  			nih_hash_add (job_classes, &class->entry);
  		}

=== modified file 'init/tests/test_event_operator.c'
--- init/tests/test_event_operator.c	2009-08-04 00:20:04 +0000
+++ init/tests/test_event_operator.c	2009-08-13 00:49:35 +0000
@@ -53,10 +53,8 @@ test_operator_new (void)
  		}

  		TEST_ALLOC_SIZE (oper, sizeof (EventOperator));
-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-		TEST_EQ (oper->value, FALSE);
+		TEST_LIST_EMPTY (&oper->children);
+		TEST_FALSE (oper->value);
  		TEST_EQ_STR (oper->name, "test");
  		TEST_ALLOC_PARENT (oper->name, oper);

@@ -92,10 +90,8 @@ test_operator_new (void)
  		nih_discard (env);

  		TEST_ALLOC_SIZE (oper, sizeof (EventOperator));
-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-		TEST_EQ (oper->value, FALSE);
+		TEST_LIST_EMPTY (&oper->children);
+		TEST_FALSE (oper->value);
  		TEST_EQ_STR (oper->name, "test");
  		TEST_ALLOC_PARENT (oper->name, oper);

@@ -119,10 +115,8 @@ test_operator_new (void)
  		}

  		TEST_ALLOC_SIZE (oper, sizeof (EventOperator));
-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-		TEST_EQ (oper->value, FALSE);
+		TEST_LIST_EMPTY (&oper->children);
+		TEST_FALSE (oper->value);
  		TEST_EQ_P (oper->name, NULL);
  		TEST_EQ_P (oper->env, NULL);
  		TEST_EQ_P (oper->event, NULL);
@@ -159,11 +153,9 @@ test_operator_copy (void)
  		}

  		TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
-		TEST_EQ_P (copy->node.parent, NULL);
-		TEST_EQ_P (copy->node.left, NULL);
-		TEST_EQ_P (copy->node.right, NULL);
+		TEST_LIST_EMPTY (&copy->children);
  		TEST_EQ (copy->type, EVENT_OR);
-		TEST_EQ (copy->value, TRUE);
+		TEST_TRUE (copy->value);
  		TEST_EQ_P (copy->name, NULL);
  		TEST_EQ_P (copy->env, NULL);
  		TEST_EQ_P (copy->event, NULL);
@@ -193,11 +185,9 @@ test_operator_copy (void)
  		}

  		TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
-		TEST_EQ_P (copy->node.parent, NULL);
-		TEST_EQ_P (copy->node.left, NULL);
-		TEST_EQ_P (copy->node.right, NULL);
+		TEST_LIST_EMPTY (&copy->children);
  		TEST_EQ (copy->type, EVENT_MATCH);
-		TEST_EQ (copy->value, TRUE);
+		TEST_TRUE (copy->value);
  		TEST_EQ_STR (copy->name, "test");
  		TEST_ALLOC_PARENT (copy->name, copy);
  		TEST_EQ_P (copy->env, NULL);
@@ -233,11 +223,9 @@ test_operator_copy (void)
  		}

  		TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
-		TEST_EQ_P (copy->node.parent, NULL);
-		TEST_EQ_P (copy->node.left, NULL);
-		TEST_EQ_P (copy->node.right, NULL);
+		TEST_LIST_EMPTY (&copy->children);
  		TEST_EQ (copy->type, EVENT_MATCH);
-		TEST_EQ (copy->value, TRUE);
+		TEST_TRUE (copy->value);
  		TEST_EQ_STR (copy->name, "test");
  		TEST_ALLOC_PARENT (copy->name, copy);

@@ -279,11 +267,9 @@ test_operator_copy (void)
  		}

  		TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
-		TEST_EQ_P (copy->node.parent, NULL);
-		TEST_EQ_P (copy->node.left, NULL);
-		TEST_EQ_P (copy->node.right, NULL);
+		TEST_LIST_EMPTY (&copy->children);
  		TEST_EQ (copy->type, EVENT_MATCH);
-		TEST_EQ (copy->value, TRUE);
+		TEST_TRUE (copy->value);
  		TEST_EQ_STR (copy->name, "test");
  		TEST_ALLOC_PARENT (copy->name, copy);
  		TEST_EQ_P (copy->env, NULL);
@@ -310,47 +296,39 @@ test_operator_copy (void)
  			oper1->value = TRUE;
  			oper1->event = event_new (oper1, "foo", NULL);
  			event_block (oper1->event);
-			nih_tree_add (&oper->node, &oper1->node,
-				      NIH_TREE_LEFT);
+			event_operator_add_child (oper, oper1);

  			oper2 = event_operator_new (NULL, EVENT_MATCH,
  						    "bar", NULL);
  			oper2->value = TRUE;
  			oper2->event = event_new (oper2, "foo", NULL);
  			event_block (oper2->event);
-			nih_tree_add (&oper->node, &oper2->node,
-				      NIH_TREE_RIGHT);
+			event_operator_add_child (oper, oper2);
  		}

  		copy = event_operator_copy (NULL, oper);

  		if (test_alloc_failed) {
  			TEST_EQ_P (copy, NULL);
-			nih_free (oper);
  			TEST_EQ (oper1->event->blockers, 1);
-			nih_free (oper1);
  			TEST_EQ (oper2->event->blockers, 1);
-			nih_free (oper2);
+			nih_free (oper);
  			continue;
  		}

  		TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
-		TEST_EQ_P (copy->node.parent, NULL);
-		TEST_NE_P (copy->node.left, NULL);
-		TEST_NE_P (copy->node.right, NULL);
+		TEST_LIST_NOT_EMPTY (&copy->children);
  		TEST_EQ (copy->type, EVENT_OR);
-		TEST_EQ (copy->value, TRUE);
+		TEST_TRUE (copy->value);
  		TEST_EQ_P (copy->name, NULL);
  		TEST_EQ_P (copy->env, NULL);

-		copy1 = (EventOperator *)copy->node.left;
+		copy1 = (EventOperator *)copy->children.next;
  		TEST_ALLOC_SIZE (copy1, sizeof (EventOperator));
  		TEST_ALLOC_PARENT (copy1, copy);
-		TEST_EQ_P (copy1->node.parent, &copy->node);
-		TEST_EQ_P (copy1->node.left, NULL);
-		TEST_EQ_P (copy1->node.right, NULL);
+		TEST_LIST_EMPTY (&copy1->children);
  		TEST_EQ (copy1->type, EVENT_MATCH);
-		TEST_EQ (copy1->value, TRUE);
+		TEST_TRUE (copy1->value);
  		TEST_EQ_STR (copy1->name, "foo");
  		TEST_ALLOC_PARENT (copy1->name, copy1);
  		TEST_EQ_P (copy1->env, NULL);
@@ -360,14 +338,12 @@ test_operator_copy (void)

  		nih_free (copy1);

-		copy2 = (EventOperator *)copy->node.right;
+		copy2 = (EventOperator *)copy1->entry.next;
  		TEST_ALLOC_SIZE (copy2, sizeof (EventOperator));
  		TEST_ALLOC_PARENT (copy2, copy);
-		TEST_EQ_P (copy2->node.parent, &copy->node);
-		TEST_EQ_P (copy2->node.left, NULL);
-		TEST_EQ_P (copy2->node.right, NULL);
+		TEST_LIST_EMPTY (&copy1->children);
  		TEST_EQ (copy2->type, EVENT_MATCH);
-		TEST_EQ (copy2->value, TRUE);
+		TEST_TRUE (copy2->value);
  		TEST_EQ_STR (copy2->name, "bar");
  		TEST_ALLOC_PARENT (copy2->name, copy2);
  		TEST_EQ_P (copy2->env, NULL);
@@ -434,8 +410,8 @@ test_operator_update (void)
  	oper2 = event_operator_new (NULL, EVENT_MATCH, "foo", NULL);
  	oper3 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL);

-	nih_tree_add (&oper1->node, &oper2->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper1->node, &oper3->node, NIH_TREE_RIGHT);
+	event_operator_add_child (oper1, oper2);
+	event_operator_add_child (oper1, oper3);


  	/* Check that EVENT_OR is FALSE if both children are FALSE. */
@@ -444,7 +420,7 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, FALSE);
+	TEST_FALSE (oper1->value);


  	/* Check that EVENT_OR is TRUE if only the left child is TRUE. */
@@ -454,7 +430,7 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, TRUE);
+	TEST_TRUE (oper1->value);


  	/* Check that EVENT_OR is TRUE if only the right child is TRUE. */
@@ -464,7 +440,7 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, TRUE);
+	TEST_TRUE (oper1->value);


  	/* Check that EVENT_OR is TRUE if both children are TRUE. */
@@ -474,7 +450,7 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, TRUE);
+	TEST_TRUE (oper1->value);


  	/* Check that EVENT_AND is FALSE if both children are FALSE. */
@@ -484,7 +460,7 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, FALSE);
+	TEST_FALSE (oper1->value);


  	/* Check that EVENT_AND is FALSE if only the left child is TRUE. */
@@ -494,7 +470,7 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, FALSE);
+	TEST_FALSE (oper1->value);


  	/* Check that EVENT_AND is FALSE if only the right child is TRUE. */
@@ -504,7 +480,7 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, FALSE);
+	TEST_FALSE (oper1->value);


  	/* Check that EVENT_AND is TRUE if both children are TRUE. */
@@ -514,12 +490,10 @@ test_operator_update (void)

  	event_operator_update (oper1);

-	TEST_EQ (oper1->value, TRUE);
+	TEST_TRUE (oper1->value);


  	nih_free (oper1);
-	nih_free (oper2);
-	nih_free (oper3);
  }

  void
@@ -813,10 +787,10 @@ test_operator_handle (void)
  	oper5->env[0] = "BAR=$WIBBLE";
  	oper5->env[1] = NULL;

-	nih_tree_add (&oper1->node, &oper2->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper2->node, &oper3->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper2->node, &oper4->node, NIH_TREE_RIGHT);
-	nih_tree_add (&oper1->node, &oper5->node, NIH_TREE_RIGHT);
+	event_operator_add_child (oper1, oper2);
+	event_operator_add_child (oper2, oper3);
+	event_operator_add_child (oper2, oper4);
+	event_operator_add_child (oper1, oper5);


  	/* Check that a non-matching event doesn't touch the tree. */
@@ -824,14 +798,14 @@ test_operator_handle (void)
  	event = event_new (NULL, "frodo", NULL);
  	ret = event_operator_handle (oper1, event, NULL);

-	TEST_EQ (ret, FALSE);
-	TEST_EQ (oper1->value, FALSE);
-	TEST_EQ (oper2->value, FALSE);
-	TEST_EQ (oper3->value, FALSE);
+	TEST_FALSE (ret);
+	TEST_FALSE (oper1->value);
+	TEST_FALSE (oper2->value);
+	TEST_FALSE (oper3->value);
  	TEST_EQ_P (oper3->event, NULL);
-	TEST_EQ (oper4->value, FALSE);
+	TEST_FALSE (oper4->value);
  	TEST_EQ_P (oper4->event, NULL);
-	TEST_EQ (oper5->value, FALSE);
+	TEST_FALSE (oper5->value);
  	TEST_EQ_P (oper5->event, NULL);

  	TEST_EQ (event->blockers, 0);
@@ -846,14 +820,14 @@ test_operator_handle (void)
  	event = event_new (NULL, "foo", NULL);
  	ret = event_operator_handle (oper1, event, NULL);

-	TEST_EQ (ret, TRUE);
-	TEST_EQ (oper1->value, FALSE);
-	TEST_EQ (oper2->value, FALSE);
-	TEST_EQ (oper3->value, TRUE);
+	TEST_TRUE (ret);
+	TEST_FALSE (oper1->value);
+	TEST_FALSE (oper2->value);
+	TEST_TRUE (oper3->value);
  	TEST_EQ_P (oper3->event, event);
-	TEST_EQ (oper4->value, FALSE);
+	TEST_FALSE (oper4->value);
  	TEST_EQ_P (oper4->event, NULL);
-	TEST_EQ (oper5->value, FALSE);
+	TEST_FALSE (oper5->value);
  	TEST_EQ_P (oper5->event, NULL);

  	TEST_EQ (event->blockers, 1);
@@ -869,15 +843,15 @@ test_operator_handle (void)

  	ret = event_operator_handle (oper1, event, NULL);

-	TEST_EQ (ret, FALSE);
-	TEST_EQ (oper1->value, FALSE);
-	TEST_EQ (oper2->value, FALSE);
-	TEST_EQ (oper3->value, TRUE);
+	TEST_FALSE (ret);
+	TEST_FALSE (oper1->value);
+	TEST_FALSE (oper2->value);
+	TEST_TRUE (oper3->value);
  	TEST_NE_P (oper3->event, event);
  	TEST_NOT_FREE (oper3->event);
-	TEST_EQ (oper4->value, FALSE);
+	TEST_FALSE (oper4->value);
  	TEST_EQ_P (oper4->event, NULL);
-	TEST_EQ (oper5->value, FALSE);
+	TEST_FALSE (oper5->value);
  	TEST_EQ_P (oper5->event, NULL);

  	TEST_EQ (event->blockers, 0);
@@ -893,14 +867,14 @@ test_operator_handle (void)
  	event = event_new (NULL, "bar", NULL);
  	ret = event_operator_handle (oper1, event, NULL);

-	TEST_EQ (ret, TRUE);
-	TEST_EQ (oper1->value, TRUE);
-	TEST_EQ (oper2->value, TRUE);
-	TEST_EQ (oper3->value, TRUE);
+	TEST_TRUE (ret);
+	TEST_TRUE (oper1->value);
+	TEST_TRUE (oper2->value);
+	TEST_TRUE (oper3->value);
  	TEST_NE_P (oper3->event, NULL);
-	TEST_EQ (oper4->value, TRUE);
+	TEST_TRUE (oper4->value);
  	TEST_EQ_P (oper4->event, event);
-	TEST_EQ (oper5->value, FALSE);
+	TEST_FALSE (oper5->value);
  	TEST_EQ_P (oper5->event, NULL);

  	TEST_EQ (event->blockers, 1);
@@ -922,14 +896,14 @@ test_operator_handle (void)
  	env[1] = NULL;
  	ret = event_operator_handle (oper1, event, env);

-	TEST_EQ (ret, TRUE);
-	TEST_EQ (oper1->value, TRUE);
-	TEST_EQ (oper2->value, FALSE);
-	TEST_EQ (oper3->value, FALSE);
+	TEST_TRUE (ret);
+	TEST_TRUE (oper1->value);
+	TEST_FALSE (oper2->value);
+	TEST_FALSE (oper3->value);
  	TEST_EQ_P (oper4->event, NULL);
-	TEST_EQ (oper4->value, FALSE);
+	TEST_FALSE (oper4->value);
  	TEST_EQ_P (oper4->event, NULL);
-	TEST_EQ (oper5->value, TRUE);
+	TEST_TRUE (oper5->value);
  	TEST_EQ_P (oper5->event, event);

  	TEST_EQ (event->blockers, 1);
@@ -938,10 +912,6 @@ test_operator_handle (void)
  	event_operator_reset (oper1);

  	nih_free (oper1);
-	nih_free (oper2);
-	nih_free (oper3);
-	nih_free (oper4);
-	nih_free (oper5);

  	event_poll ();
  }
@@ -964,12 +934,12 @@ test_operator_environment (void)
  	oper5 = event_operator_new (root, EVENT_MATCH, "frodo", NULL);
  	oper6 = event_operator_new (root, EVENT_MATCH, "bilbo", NULL);

-	nih_tree_add (&root->node, &oper1->node, NIH_TREE_LEFT);
-	nih_tree_add (&root->node, &oper2->node, NIH_TREE_RIGHT);
-	nih_tree_add (&oper1->node, &oper3->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper1->node, &oper4->node, NIH_TREE_RIGHT);
-	nih_tree_add (&oper2->node, &oper5->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper2->node, &oper6->node, NIH_TREE_RIGHT);
+	event_operator_add_child (root, oper1);
+	event_operator_add_child (root, oper2);
+	event_operator_add_child (oper1, oper3);
+	event_operator_add_child (oper1, oper4);
+	event_operator_add_child (oper2, oper5);
+	event_operator_add_child (oper2, oper6);

  	root->value = TRUE;

@@ -1132,12 +1102,12 @@ test_operator_events (void)
  	oper5 = event_operator_new (root, EVENT_MATCH, "frodo", NULL);
  	oper6 = event_operator_new (root, EVENT_MATCH, "bilbo", NULL);

-	nih_tree_add (&root->node, &oper1->node, NIH_TREE_LEFT);
-	nih_tree_add (&root->node, &oper2->node, NIH_TREE_RIGHT);
-	nih_tree_add (&oper1->node, &oper3->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper1->node, &oper4->node, NIH_TREE_RIGHT);
-	nih_tree_add (&oper2->node, &oper5->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper2->node, &oper6->node, NIH_TREE_RIGHT);
+	event_operator_add_child (root, oper1);
+	event_operator_add_child (root, oper2);
+	event_operator_add_child (oper1, oper3);
+	event_operator_add_child (oper1, oper4);
+	event_operator_add_child (oper2, oper5);
+	event_operator_add_child (oper2, oper6);

  	root->value = TRUE;

@@ -1238,10 +1208,10 @@ test_operator_reset (void)
  	oper4 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL);
  	oper5 = event_operator_new (NULL, EVENT_MATCH, "baz", NULL);

-	nih_tree_add (&oper1->node, &oper2->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper2->node, &oper3->node, NIH_TREE_LEFT);
-	nih_tree_add (&oper2->node, &oper4->node, NIH_TREE_RIGHT);
-	nih_tree_add (&oper1->node, &oper5->node, NIH_TREE_RIGHT);
+	event_operator_add_child (oper1, oper2);
+	event_operator_add_child (oper2, oper3);
+	event_operator_add_child (oper2, oper4);
+	event_operator_add_child (oper1, oper5);

  	event1 = event_new (NULL, "foo", NULL);
  	event2 = event_new (NULL, "bar", NULL);
@@ -1249,40 +1219,98 @@ test_operator_reset (void)
  	event_operator_handle (oper1, event1, NULL);
  	event_operator_handle (oper1, event2, NULL);

-	TEST_EQ (oper1->value, TRUE);
-	TEST_EQ (oper2->value, TRUE);
-	TEST_EQ (oper3->value, TRUE);
+	TEST_TRUE (oper1->value);
+	TEST_TRUE (oper2->value);
+	TEST_TRUE (oper3->value);
  	TEST_EQ_P (oper3->event, event1);
-	TEST_EQ (oper4->value, TRUE);
+	TEST_TRUE (oper4->value);
  	TEST_EQ (oper4->event, event2);
-	TEST_EQ (oper5->value, FALSE);
+	TEST_FALSE (oper5->value);

  	TEST_EQ (event1->blockers, 1);
  	TEST_EQ (event2->blockers, 1);

  	event_operator_reset (oper1);

-	TEST_EQ (oper1->value, FALSE);
-	TEST_EQ (oper2->value, FALSE);
-	TEST_EQ (oper3->value, FALSE);
+	TEST_FALSE (oper1->value);
+	TEST_FALSE (oper2->value);
+	TEST_FALSE (oper3->value);
  	TEST_EQ_P (oper3->event, NULL);
-	TEST_EQ (oper4->value, FALSE);
+	TEST_FALSE (oper4->value);
  	TEST_EQ (oper4->event, NULL);
-	TEST_EQ (oper5->value, FALSE);
+	TEST_FALSE (oper5->value);

  	TEST_EQ (event1->blockers, 0);
  	TEST_EQ (event2->blockers, 0);

  	nih_free (oper1);
-	nih_free (oper2);
-	nih_free (oper3);
-	nih_free (oper4);
-	nih_free (oper5);

  	event_poll ();
  }


+void
+test_operator_add_child (void)
+{
+	EventOperator *oper1, *oper2, *oper3, *oper4, *oper5, *oper6, *oper7;
+	int found_foo = 0;
+	int found_bar = 0;
+	int found_baz = 0;
+	int found_bam = 0;
+	int found_all = 0;
+
+	TEST_FUNCTION ("event_operator_add_child");
+	oper1 = event_operator_new (NULL, EVENT_OR, NULL, NULL);
+	oper2 = event_operator_new (NULL, EVENT_AND, NULL, NULL);
+	oper3 = event_operator_new (NULL, EVENT_MATCH, "foo", NULL);
+	oper4 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL);
+	oper5 = event_operator_new (NULL, EVENT_MATCH, "baz", NULL);
+	oper6 = event_operator_new (NULL, EVENT_MATCH, "bam", NULL);
+	oper7 = event_operator_new (NULL, EVENT_OR, NULL, NULL);
+
+	event_operator_add_child (oper2, oper3);
+	event_operator_add_child (oper2, oper4);
+	event_operator_add_child (oper7, oper5);
+	event_operator_add_child (oper7, oper6);
+	event_operator_add_child (oper1, oper2);
+	event_operator_add_child (oper1, oper7);
+
+	TEST_EQ (oper1->type, EVENT_OR);
+
+	NIH_LIST_FOREACH (&oper1->children, iter) {
+		EventOperator *child = (EventOperator *)iter;
+
+		if (child->type == EVENT_AND) {
+			found_all++;
+			continue;
+		}
+
+		TEST_EQ (child->type, EVENT_MATCH);
+
+		if (! strncmp (child->name, "foo", 4))
+			found_foo++;
+
+		if (! strncmp (child->name, "bar", 4))
+			found_bar++;
+
+		if (! strncmp (child->name, "baz", 4))
+			found_baz++;
+
+		if (! strncmp (child->name, "bam", 4))
+			found_bam++;
+	}
+
+	/* Not a truth test. 2 is also a failure. */
+	TEST_EQ (found_all, 1);
+	TEST_EQ (found_foo, 0);
+	TEST_EQ (found_bar, 0);
+	TEST_EQ (found_baz, 1);
+	TEST_EQ (found_bam, 1);
+
+	nih_free (oper1);
+}
+
+
  int
  main (int   argc,
        char *argv[])
@@ -1296,6 +1324,7 @@ main (int   argc,
  	test_operator_environment ();
  	test_operator_events ();
  	test_operator_reset ();
+	test_operator_add_child ();

  	return 0;
  }

=== modified file 'init/tests/test_parse_job.c'
--- init/tests/test_parse_job.c	2009-07-09 11:01:53 +0000
+++ init/tests/test_parse_job.c	2009-08-13 00:49:35 +0000
@@ -87,14 +87,14 @@ test_parse_job (void)
  		process = job->process[PROCESS_MAIN];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/sbin/daemon -d");

  		process = job->process[PROCESS_PRE_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "rm /var/lock/daemon\n");

@@ -174,7 +174,7 @@ test_stanza_exec (void)
  		process = job->process[PROCESS_MAIN];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/sbin/daemon -d \"foo\"");

@@ -211,7 +211,7 @@ test_stanza_exec (void)
  		process = job->process[PROCESS_MAIN];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/sbin/daemon -d \"foo\"");

@@ -250,7 +250,7 @@ test_stanza_exec (void)
  		process = job->process[PROCESS_MAIN];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/sbin/daemon -d \"foo\"");

@@ -320,7 +320,7 @@ test_stanza_script (void)
  		process = job->process[PROCESS_MAIN];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -361,7 +361,7 @@ test_stanza_script (void)
  		process = job->process[PROCESS_MAIN];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -400,7 +400,7 @@ test_stanza_script (void)
  		process = job->process[PROCESS_MAIN];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -468,7 +468,7 @@ test_stanza_pre_start (void)
  		process = job->process[PROCESS_PRE_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -505,7 +505,7 @@ test_stanza_pre_start (void)
  		process = job->process[PROCESS_PRE_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -545,7 +545,7 @@ test_stanza_pre_start (void)
  		process = job->process[PROCESS_PRE_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -586,7 +586,7 @@ test_stanza_pre_start (void)
  		process = job->process[PROCESS_PRE_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -625,7 +625,7 @@ test_stanza_pre_start (void)
  		process = job->process[PROCESS_PRE_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -664,7 +664,7 @@ test_stanza_pre_start (void)
  		process = job->process[PROCESS_PRE_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -789,7 +789,7 @@ test_stanza_post_start (void)
  		process = job->process[PROCESS_POST_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -826,7 +826,7 @@ test_stanza_post_start (void)
  		process = job->process[PROCESS_POST_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -866,7 +866,7 @@ test_stanza_post_start (void)
  		process = job->process[PROCESS_POST_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -907,7 +907,7 @@ test_stanza_post_start (void)
  		process = job->process[PROCESS_POST_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -946,7 +946,7 @@ test_stanza_post_start (void)
  		process = job->process[PROCESS_POST_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -985,7 +985,7 @@ test_stanza_post_start (void)
  		process = job->process[PROCESS_POST_START];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -1110,7 +1110,7 @@ test_stanza_pre_stop (void)
  		process = job->process[PROCESS_PRE_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -1147,7 +1147,7 @@ test_stanza_pre_stop (void)
  		process = job->process[PROCESS_PRE_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -1187,7 +1187,7 @@ test_stanza_pre_stop (void)
  		process = job->process[PROCESS_PRE_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -1228,7 +1228,7 @@ test_stanza_pre_stop (void)
  		process = job->process[PROCESS_PRE_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -1267,7 +1267,7 @@ test_stanza_pre_stop (void)
  		process = job->process[PROCESS_PRE_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -1306,7 +1306,7 @@ test_stanza_pre_stop (void)
  		process = job->process[PROCESS_PRE_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -1431,7 +1431,7 @@ test_stanza_post_stop (void)
  		process = job->process[PROCESS_POST_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -1468,7 +1468,7 @@ test_stanza_post_stop (void)
  		process = job->process[PROCESS_POST_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -1508,7 +1508,7 @@ test_stanza_post_stop (void)
  		process = job->process[PROCESS_POST_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -1549,7 +1549,7 @@ test_stanza_post_stop (void)
  		process = job->process[PROCESS_POST_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -1588,7 +1588,7 @@ test_stanza_post_stop (void)
  		process = job->process[PROCESS_POST_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, TRUE);
+		TEST_TRUE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "echo\n");

@@ -1627,7 +1627,7 @@ test_stanza_post_stop (void)
  		process = job->process[PROCESS_POST_STOP];
  		TEST_ALLOC_PARENT (process, job->process);
  		TEST_ALLOC_SIZE (process, sizeof (Process));
-		TEST_EQ (process->script, FALSE);
+		TEST_FALSE (process->script);
  		TEST_ALLOC_PARENT (process->command, process);
  		TEST_EQ_STR (process->command, "/bin/tool -d \"foo\"");

@@ -1714,11 +1714,12 @@ test_stanza_post_stop (void)
  void
  test_stanza_start (void)
  {
-	JobClass     *job;
+	JobClass      *job;
  	EventOperator *oper;
  	NihError      *err;
  	size_t         pos, lineno;
  	char           buf[1024];
+	int            got_wibble, got_wobble, got_wiggle;

  	TEST_FUNCTION ("stanza_start");

@@ -1757,9 +1758,7 @@ test_stanza_start (void)
  		TEST_EQ_STR (oper->name, "wibble");
  		TEST_EQ_P (oper->env, NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}
@@ -1807,9 +1806,7 @@ test_stanza_start (void)
  		TEST_EQ_STR (oper->env[2], "b?z*");
  		TEST_EQ_P (oper->env[3], NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}
@@ -1861,9 +1858,7 @@ test_stanza_start (void)
  		TEST_EQ_STR (oper->env[4], "BILBO=foo bar");
  		TEST_EQ_P (oper->env[5], NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}
@@ -1903,29 +1898,25 @@ test_stanza_start (void)
  		oper = job->start_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		EventOperator *parent = oper;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ_P (child->env, NULL);
+			TEST_EQ (child->type, EVENT_MATCH);
+			if ((! strncmp ("wibble", child->name, 7)) && (! got_wibble)) {
+				got_wibble = TRUE;
+			} else if ((! strncmp ("wobble", child->name, 7)) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -1966,37 +1957,30 @@ test_stanza_start (void)
  		oper = job->start_on;
  		TEST_EQ (oper->type, EVENT_AND);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-
-		TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
-		TEST_EQ_STR (oper->env[0], "foo");
-		TEST_EQ_STR (oper->env[1], "bar");
-		TEST_EQ_P (oper->env[2], NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-
-		TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
-		TEST_EQ_STR (oper->env[0], "frodo");
-		TEST_EQ_STR (oper->env[1], "bilbo");
-		TEST_EQ_P (oper->env[2], NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_ALLOC_SIZE (child->env, sizeof (char *) * 3);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+				TEST_EQ_STR (child->env[0], "foo");
+				TEST_EQ_STR (child->env[1], "bar");
+				TEST_EQ_P (child->env[2], NULL);
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+				TEST_EQ_STR (child->env[0], "frodo");
+				TEST_EQ_STR (child->env[1], "bilbo");
+				TEST_EQ_P (child->env[2], NULL);
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -2036,46 +2020,27 @@ test_stanza_start (void)
  		oper = job->start_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.left;
-		TEST_EQ (oper->type, EVENT_OR);
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.left->left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->start_on->node.left);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.left->right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->start_on->node.left);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wiggle");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		got_wiggle = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_EQ_P (child->env, NULL);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
+				got_wiggle = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -2114,47 +2079,27 @@ test_stanza_start (void)
  		oper = job->start_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.right;
-		TEST_EQ (oper->type, EVENT_OR);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.right->left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->start_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.right->right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wiggle");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->start_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		got_wiggle = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_EQ_P (child->env, NULL);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
+				got_wiggle = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -2194,47 +2139,27 @@ test_stanza_start (void)
  		oper = job->start_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.right;
-		TEST_EQ (oper->type, EVENT_OR);
-
-		TEST_EQ_P (oper->node.parent, &job->start_on->node);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->start_on->node.right->left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->start_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->start_on->node.right->right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wiggle");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->start_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		got_wiggle = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_EQ_P (child->env, NULL);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
+				got_wiggle = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -2275,9 +2200,7 @@ test_stanza_start (void)
  		TEST_EQ_STR (oper->name, "waggle");
  		TEST_EQ_P (oper->env, NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}
@@ -2536,6 +2459,7 @@ test_stanza_stop (void)
  	NihError      *err;
  	size_t         pos, lineno;
  	char           buf[1024];
+	int            got_wibble, got_wobble, got_wiggle;

  	TEST_FUNCTION ("stanza_stop");

@@ -2574,9 +2498,7 @@ test_stanza_stop (void)
  		TEST_EQ_STR (oper->name, "wibble");
  		TEST_EQ_P (oper->env, NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}
@@ -2624,9 +2546,7 @@ test_stanza_stop (void)
  		TEST_EQ_STR (oper->env[2], "b?z*");
  		TEST_EQ_P (oper->env[3], NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}
@@ -2678,9 +2598,7 @@ test_stanza_stop (void)
  		TEST_EQ_STR (oper->env[4], "BILBO=foo bar");
  		TEST_EQ_P (oper->env[5], NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}
@@ -2720,29 +2638,24 @@ test_stanza_stop (void)
  		oper = job->stop_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_EQ_P (child->env, NULL);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -2783,37 +2696,30 @@ test_stanza_stop (void)
  		oper = job->stop_on;
  		TEST_EQ (oper->type, EVENT_AND);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-
-		TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
-		TEST_EQ_STR (oper->env[0], "foo");
-		TEST_EQ_STR (oper->env[1], "bar");
-		TEST_EQ_P (oper->env[2], NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-
-		TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
-		TEST_EQ_STR (oper->env[0], "frodo");
-		TEST_EQ_STR (oper->env[1], "bilbo");
-		TEST_EQ_P (oper->env[2], NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_ALLOC_SIZE (child->env, sizeof (char *) * 3);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+				TEST_EQ_STR (child->env[0], "foo");
+				TEST_EQ_STR (child->env[1], "bar");
+				TEST_EQ_P (child->env[2], NULL);
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+				TEST_EQ_STR (child->env[0], "frodo");
+				TEST_EQ_STR (child->env[1], "bilbo");
+				TEST_EQ_P (child->env[2], NULL);
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -2853,46 +2759,27 @@ test_stanza_stop (void)
  		oper = job->stop_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.left;
-		TEST_EQ (oper->type, EVENT_OR);
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.left->left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->stop_on->node.left);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.left->right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->stop_on->node.left);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wiggle");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		got_wiggle = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_EQ_P (child->env, NULL);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
+				got_wiggle = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -2931,47 +2818,27 @@ test_stanza_stop (void)
  		oper = job->stop_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.right;
-		TEST_EQ (oper->type, EVENT_OR);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.right->left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.right->right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wiggle");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		got_wiggle = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_EQ_P (child->env, NULL);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
+				got_wiggle = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -3011,47 +2878,27 @@ test_stanza_stop (void)
  		oper = job->stop_on;
  		TEST_EQ (oper->type, EVENT_OR);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wibble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.right;
-		TEST_EQ (oper->type, EVENT_OR);
-
-		TEST_EQ_P (oper->node.parent, &job->stop_on->node);
-		TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.left, oper);
-		TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
-		TEST_ALLOC_PARENT (oper->node.right, oper);
-
-		oper = (EventOperator *)job->stop_on->node.right->left;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wobble");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
-
-		oper = (EventOperator *)job->stop_on->node.right->right;
-		TEST_EQ (oper->type, EVENT_MATCH);
-		TEST_EQ_STR (oper->name, "wiggle");
-		TEST_EQ_P (oper->env, NULL);
-
-		TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		got_wibble = FALSE;
+		got_wobble = FALSE;
+		got_wiggle = FALSE;
+		NIH_LIST_FOREACH (&oper->children, iter) {
+			EventOperator *child = (EventOperator *)iter;
+
+			TEST_ALLOC_SIZE (child, sizeof (EventOperator));
+
+			TEST_LIST_EMPTY (&child->children);
+			TEST_EQ (child->type, EVENT_MATCH);
+			TEST_EQ_P (child->env, NULL);
+			if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
+				got_wibble = TRUE;
+			} else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
+				got_wobble = TRUE;
+			} else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
+				got_wiggle = TRUE;
+			} else {
+				TEST_FAILED ("Unexpected child");
+			}
+		}

  		nih_free (job);
  	}
@@ -3092,9 +2939,7 @@ test_stanza_stop (void)
  		TEST_EQ_STR (oper->name, "waggle");
  		TEST_EQ_P (oper->env, NULL);

-		TEST_EQ_P (oper->node.parent, NULL);
-		TEST_EQ_P (oper->node.left, NULL);
-		TEST_EQ_P (oper->node.right, NULL);
+		TEST_LIST_EMPTY (&oper->children);

  		nih_free (job);
  	}




More information about the upstart-devel mailing list