Merge lp:~cjdahlin/upstart/n-ary-event-oper into lp:~canonical-scott/upstart/trunk

Proposed by Casey Dahlin on 2009-08-11
Status: Needs review
Proposed branch: lp:~cjdahlin/upstart/n-ary-event-oper
Merge into: lp:~canonical-scott/upstart/trunk
Diff against target: None lines
To merge this branch: bzr merge lp:~cjdahlin/upstart/n-ary-event-oper
Reviewer Review Type Date Requested Status
Scott James Remnant (Canonical) 2009-08-11 Needs Fixing on 2009-08-12
Review via email: mp+9968@code.launchpad.net
To post a comment you must log in.
Casey Dahlin (cjdahlin) wrote :

This makes EventOperators N-ary rather than binary trees. It auto-optimizes them with a new event_operator_add_child helper that simply gifts all of the new child's children to the new parent rather than attaching it when the new parent and child are of the same type.

This makes it a bit easier to make qualitative statements about trees, particularly "this tree only contains OR operators," which should become useful as AND operators become deprecated in future state models.

Hi Casey,

Could you send this in the form of a patch to the upstart-devel ML?

review: Abstain
review: Needs Fixing
Download full text (21.7 KiB)

On Tue, 2009-08-11 at 17:33 -0400, Casey Dahlin wrote:

> This makes EventOperators N-ary rather than binary trees. It
> auto-optimizes them with a new event_operator_add_child helper that
> simply gifts all of the new child's children to the new parent rather
> than attaching it when the new parent and child are of the same type.
>
> This makes it a bit easier to make qualitative statements about trees,
> particularly "this tree only contains OR operators," which should become
> useful as AND operators become deprecated in future state models.
>
Thanks Casey.

Could you explain a little bit more about the rationale behind these
changes? Right now this just looks like a different way of constructing
the operator trees, and unless I'm mistaken, it's more expensive to
build them this way, they use more memory per node and they're more
difficult to iterate than the btrees we currently use.

Are you working on something else that requires this? Perhaps it'd help
to outline that work as well to the ML.

One thing I'd like to ask about - I don't have any plans to deprecate
AND operators; could you tell us a little bit about your plans in this
regard?

>
> === modified file 'ChangeLog'
> --- ChangeLog 2009-08-04 08:51:25 +0000
> +++ ChangeLog 2009-08-11 05:51:31 +0000
> @@ -1,3 +1,60 @@
> +2009-08-11 Casey Dahlin <email address hidden>
> +
> + * 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 (...

Casey Dahlin (cjdahlin) wrote :
Download full text (25.2 KiB)

-------- Original Message --------
Subject: Re: [PATCH] N-ary event operators
Date: Wed, 12 Aug 2009 10:06:39 -0400
From: Casey Dahlin <email address hidden>
To: Scott James Remnant <email address hidden>
CC: Upstart Dev List <email address hidden>

On 08/12/2009 06:12 AM, Scott James Remnant wrote:
> On Tue, 2009-08-11 at 17:33 -0400, Casey Dahlin wrote:
>
>> This makes EventOperators N-ary rather than binary trees. It
>> auto-optimizes them with a new event_operator_add_child helper that
>> simply gifts all of the new child's children to the new parent rather
>> than attaching it when the new parent and child are of the same type.
>>
>> This makes it a bit easier to make qualitative statements about trees,
>> particularly "this tree only contains OR operators," which should become
>> useful as AND operators become deprecated in future state models.
>>
> Thanks Casey.
>
> Could you explain a little bit more about the rationale behind these
> changes? Right now this just looks like a different way of constructing
> the operator trees, and unless I'm mistaken, it's more expensive to
> build them this way, they use more memory per node and they're more
> difficult to iterate than the btrees we currently use.
>

Building them might be a bit more expensive, but they do take up less memory by virtue of simply having fewer nodes.

> Are you working on something else that requires this? Perhaps it'd help
> to outline that work as well to the ML.
>

I am. I'll do that.

> One thing I'd like to ask about - I don't have any plans to deprecate
> AND operators; could you tell us a little bit about your plans in this
> regard?
>

When we switch from start on to on, I see no reason to keep them. We'll have much better ways to retain state (frankly I'd rather just allow multiple "on" stanzas and do away with operators altogether, in which case our commitment to compatibility with 0.6 is the only reason any of this code needs to be around).

>
>
>> === modified file 'ChangeLog'
>> --- ChangeLog 2009-08-04 08:51:25 +0000
>> +++ ChangeLog 2009-08-11 05:51:31 +0000
>> @@ -1,3 +1,60 @@
>> +2009-08-11 Casey Dahlin <email address hidden>
>> +
>> + * 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 colla...

1187. By Casey Dahlin on 2009-08-12

* ChangeLog: Format fix

1188. By Casey Dahlin on 2009-08-13

* ChangeLog: More format fixes

1189. By Casey Dahlin on 2009-08-13

* init/event_operator.c: Fix static prototypes, rename ALL/ANY to AND/OR again
(event_operator_copy): Style fix
(event_operator_add_child, event_operator_update): Improve docstring
* init/event_operator.h, init/parse_job.c: Rename ALL/ANY back to AND/OR
* init/tests/test_event.c: Style fixes
* init/tests/test_event_operator.c: Style fixes
* init/tests/test_parse_job.c: Style fixes

Casey Dahlin (cjdahlin) wrote :
Download full text (78.0 KiB)

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 <email address hidden>
+
+ * 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 <email address hidden>

   * 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_op...

Unmerged revisions

1189. By Casey Dahlin on 2009-08-13

* init/event_operator.c: Fix static prototypes, rename ALL/ANY to AND/OR again
(event_operator_copy): Style fix
(event_operator_add_child, event_operator_update): Improve docstring
* init/event_operator.h, init/parse_job.c: Rename ALL/ANY back to AND/OR
* init/tests/test_event.c: Style fixes
* init/tests/test_event_operator.c: Style fixes
* init/tests/test_parse_job.c: Style fixes

1188. By Casey Dahlin on 2009-08-13

* ChangeLog: More format fixes

1187. By Casey Dahlin on 2009-08-12

* ChangeLog: Format fix

1186. By Casey Dahlin on 2009-08-11

Johan Kiviniemi 2009-08-04 * conf/rc-sysinit.conf: Don't replace DEFAULT_RUNLEVEL with an
Scott James Remnant 2009-08-04 * init/tests/test_event_operator.c (test_operator_new): Replace
Scott James Remnant 2009-08-04 * init/tests/test_event.c (test_new): Replace TEST_ALLOC_ORPHAN(env)
Scott James Remnant 2009-08-04 * init/tests/test_control.c (test_emit_event): Discard event
Scott James Remnant 2009-08-04 * init/init.supp: Add nih_alloc_ref_new() to init functions
Scott James Remnant 2009-08-02 * configure.ac: Bump version to 0.7.0
Scott James Remnant 2009-08-02 * NEWS: Release 0.6.3
Scott James Remnant 2009-08-01 Update NEWS from libnih
Scott James Remnant 2009-08-01 * init/tests/test_job_process.c (test_handler): Add a missing test
Scott James Remnant 2009-07-31 * dbus/upstart.h: Allow the service name and address to be overriden
Michael Biebl 2009-07-29 * init/tests/test_job_process.c: Add missing sys/ptrace.h include
Scott James Remnant 2009-07-21 * configure.ac: Bump version to 0.6.3
Scott James Remnant 2009-07-21 * NEWS: Release 0.6.2
Scott James Remnant 2009-07-21 * init/main.c (crash_handler): Restore missing chdir ("/") call.
Scott James Remnant 2009-07-21 * init/tests/test_job_process.c (test_handler): We should allow
Scott James Remnant 2009-07-21 * init/job.c (job_change_state): Obvious bug fix; the set of states
Scott James Remnant 2009-07-16 * configure.ac: Bump version to 0.6.2
Scott James Remnant 2009-07-16 * NEWS: Release 0.6.1
Scott James Remnant 2009-07-16 * util/runlevel.c: Output the path before the error message,
Scott James Remnant 2009-07-16 * util/runlevel.c: If there is no current runlevel because the
Scott James Remnant 2009-07-15 * README: Now that D-Bus 1.2.16 proper has been released, update
Scott James Remnant 2009-07-14 * TODO: Update
Scott James Remnant 2009-07-14 * init/tests/test_job_process.c (test_handler): Rework the existing
Scott James Remnant 2009-07-14 * util/Makefile.am (EXTRA_DIST): Distribute the valgrind suppressions
Scott James Remnant 2009-07-14 * util/tests/test_utmp.c (test_write_shutdown): Additional instance
Scott James Remnant 2009-07-14 * util/tests/test_utmp.c (test_write_runlevel): Looks like glibc

ChangeLog: Update

1185. By Casey Dahlin on 2009-08-11

* 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

Preview Diff

1=== modified file 'ChangeLog'
2--- ChangeLog 2009-08-04 08:51:25 +0000
3+++ ChangeLog 2009-08-11 05:51:31 +0000
4@@ -1,3 +1,60 @@
5+2009-08-11 Casey Dahlin <cdahlin@redhat.com>
6+
7+ * init/event_operator.h (EventOperatorType): Change types from AND/OR to
8+ ANY/ALL
9+
10+ (EventOperator): Get rid of node entry and add children list.
11+
12+ * init/event_operator.c (event_operator_subtree_environment): New
13+ version of event_operator_environment that assumes we are not at the
14+ root of the tree.
15+
16+ (event_operator_new): Initialize new children member instead of tree
17+ node.
18+
19+ (event_operator_copy): Use recursive call to correctly copy N-ary tree
20+
21+ (event_operator_reset): Use recursive call to correctly reset N-ary tree
22+
23+ (event_operator_events): Use recursive call to correctly get events from
24+ N-ary tree.
25+
26+ (event_operator_handle): Use recursive call to correctly handle N-ary
27+ tree.
28+
29+ (event_operator_update): Update based on all N children
30+
31+ (event_operator_match): Don't assert based on now-defunct node
32+
33+ (event_operator_add_child): New helper to add a child to a tree,
34+ automatically collapsing it into its new parent if it is the same type.
35+
36+ (event_operator_destroy): Destroy children list head correctly.
37+
38+ (event_operator_environment): Use new event_operator_subtree_environment
39+ to recursively collect environment variables.
40+
41+ * init/parse_job.c (parse_on_operator): Change AND/OR to ANY/ALL. Change
42+ tree adds to event_operator_add_child calls.
43+
44+ (parse_on_collect): Change tree adds to event_operator_add_child calls
45+
46+ * init/tests/test_event.c (test_pending_handle_jobs): Fix structural
47+ assumptions about EventOperator.
48+
49+ (test_finish): Change AND/OR to ANY/ALL
50+
51+ * init/tests/test_event_operator.c (everywhere): Fix structural
52+ assumptions about EventOperator.
53+
54+ (test_operator_add_child): New test for this new helper.
55+
56+ * init/tests/test_job_process.c (everywhere): Fix structural assumptions
57+ about EventOperator
58+
59+ * init/tests/test_parse_job.c (everywhere): Fix structural assumptions
60+ about EventOperator
61+
62 2009-08-04 Johan Kiviniemi <johan@kiviniemi.name>
63
64 * conf/rc-sysinit.conf: Don't replace DEFAULT_RUNLEVEL with an
65
66=== modified file 'init/event_operator.c'
67--- init/event_operator.c 2009-06-23 09:29:35 +0000
68+++ init/event_operator.c 2009-08-11 05:12:01 +0000
69@@ -43,6 +43,9 @@
70 #include "blocked.h"
71 #include "errors.h"
72
73+static char** event_operator_subtree_environment
74+ (EventOperator *oper, char ***env, const void *parent,
75+ size_t *len, const char *key, char **evlist);
76
77 /**
78 * event_operator_new:
79@@ -85,7 +88,8 @@
80 if (! oper)
81 return NULL;
82
83- nih_tree_init (&oper->node);
84+ nih_list_init (&oper->entry);
85+ nih_list_init (&oper->children);
86
87 oper->type = type;
88 oper->value = FALSE;
89@@ -163,33 +167,51 @@
90 event_block (oper->event);
91 }
92
93- if (old_oper->node.left) {
94- child = event_operator_copy (
95- oper, (EventOperator *)old_oper->node.left);
96- if (! child) {
97- nih_free (oper);
98- return NULL;
99- }
100-
101- nih_tree_add (&oper->node, &child->node, NIH_TREE_LEFT);
102- }
103-
104-
105- if (old_oper->node.right) {
106- child = event_operator_copy (
107- oper, (EventOperator *)old_oper->node.right);
108- if (! child) {
109- nih_free (oper);
110- return NULL;
111- }
112-
113- nih_tree_add (&oper->node, &child->node, NIH_TREE_RIGHT);
114+ NIH_LIST_FOREACH (&old_oper->children, iter) {
115+ EventOperator *child = event_operator_copy (
116+ oper, (EventOperator *)iter);
117+ if (! child) {
118+ nih_free (oper);
119+ return NULL;
120+ }
121+
122+ event_operator_add_child (oper, child);
123 }
124
125 return oper;
126 }
127
128 /**
129+ * event_operator_add_child:
130+ * @oper: oper to add child to,
131+ * @child: child to add.
132+ *
133+ * Makes @child a child of @oper. If @child and @oper are the same type, then
134+ * @oper simply steals all of @child's children.
135+ **/
136+void
137+event_operator_add_child (EventOperator *oper, EventOperator *child)
138+{
139+ nih_assert (oper != NULL);
140+ nih_assert (child != NULL);
141+ nih_assert (oper->type != EVENT_MATCH);
142+
143+ if (child->type != oper->type) {
144+ nih_ref (child, oper);
145+ nih_list_add (&oper->children, &child->entry);
146+ return;
147+ }
148+
149+ NIH_LIST_FOREACH_SAFE (&child->children, iter) {
150+ EventOperator *grandchild = (EventOperator *)iter;
151+
152+ nih_ref (grandchild, oper);
153+ nih_unref (grandchild, child);
154+ nih_list_add (&oper->children, &grandchild->entry);
155+ }
156+}
157+
158+/**
159 * event_operator_destroy:
160 * @oper: operator to be destroyed.
161 *
162@@ -209,7 +231,7 @@
163 if (oper->event)
164 event_unblock (oper->event);
165
166- nih_tree_destroy (&oper->node);
167+ nih_list_destroy (&oper->entry);
168
169 return 0;
170 }
171@@ -227,24 +249,17 @@
172 void
173 event_operator_update (EventOperator *oper)
174 {
175- EventOperator *left, *right;
176-
177 nih_assert (oper != NULL);
178- nih_assert (oper->node.left != NULL);
179- nih_assert (oper->node.right != NULL);
180-
181- left = (EventOperator *)oper->node.left;
182- right = (EventOperator *)oper->node.right;
183-
184- switch (oper->type) {
185- case EVENT_OR:
186- oper->value = (left->value || right->value);
187- break;
188- case EVENT_AND:
189- oper->value = (left->value && right->value);
190- break;
191- default:
192- nih_assert_not_reached ();
193+ nih_assert (oper->type != EVENT_MATCH);
194+
195+ oper->value = (oper->type == EVENT_ALL) ? TRUE : FALSE;
196+
197+ NIH_LIST_FOREACH (&oper->children, iter) {
198+ EventOperator *child = (EventOperator *)iter;
199+ if (child->value != oper->value) {
200+ oper->value = child->value;
201+ return;
202+ }
203 }
204 }
205
206@@ -280,8 +295,6 @@
207
208 nih_assert (oper != NULL);
209 nih_assert (oper->type == EVENT_MATCH);
210- nih_assert (oper->node.left == NULL);
211- nih_assert (oper->node.right == NULL);
212 nih_assert (event != NULL);
213
214 /* Names must match */
215@@ -391,29 +404,30 @@
216 * before we update the node itself. Simply iterate the tree and
217 * update the nodes.
218 */
219- NIH_TREE_FOREACH_POST (&root->node, iter) {
220+ NIH_LIST_FOREACH (&root->children, iter) {
221 EventOperator *oper = (EventOperator *)iter;
222
223- switch (oper->type) {
224- case EVENT_OR:
225- case EVENT_AND:
226- event_operator_update (oper);
227- break;
228- case EVENT_MATCH:
229- if ((! oper->value)
230- && event_operator_match (oper, event, env)) {
231- oper->value = TRUE;
232-
233- oper->event = event;
234- event_block (oper->event);
235-
236- ret = TRUE;
237- }
238- break;
239- default:
240- nih_assert_not_reached ();
241+ ret = ret || event_operator_handle (oper, event, env);
242+ }
243+
244+ switch (root->type) {
245+ case EVENT_ANY:
246+ case EVENT_ALL:
247+ event_operator_update (root);
248+ break;
249+ case EVENT_MATCH:
250+ if ((! root->value)
251+ && event_operator_match (root, event, env)) {
252+ root->value = TRUE;
253+
254+ root->event = event;
255+ event_block (root->event);
256+
257+ ret = TRUE;
258 }
259-
260+ break;
261+ default:
262+ nih_assert_not_reached ();
263 }
264
265 return ret;
266@@ -501,38 +515,9 @@
267 return NULL;
268 }
269
270- /* Iterate the operator tree, filtering out nodes with a non-TRUE
271- * value and their children. The rationale for this is that this
272- * then matches only the events that had an active role in starting
273- * the job, not the ones that were also blocked, but the other half
274- * of their logic wasn't present.
275- */
276- NIH_TREE_FOREACH_FULL (&root->node, iter,
277- (NihTreeFilter)event_operator_filter, NULL) {
278- EventOperator *oper = (EventOperator *)iter;
279-
280- if (oper->type != EVENT_MATCH)
281- continue;
282-
283- nih_assert (oper->event != NULL);
284-
285- /* Add environment from the event */
286- if (! environ_append (env, parent, len, TRUE, oper->event->env))
287- return NULL;
288-
289- /* Append the name of the event to the string we're building */
290- if (evlist) {
291- if (evlist[strlen (evlist) - 1] != '=') {
292- if (! nih_strcat_sprintf (&evlist, NULL, " %s",
293- oper->event->name))
294- return NULL;
295- } else {
296- if (! nih_strcat (&evlist, NULL,
297- oper->event->name))
298- return NULL;
299- }
300- }
301- }
302+ if (! event_operator_subtree_environment (root, env, parent,
303+ len, key, &evlist))
304+ return NULL;
305
306 /* Append the event list to the environment */
307 if (evlist)
308@@ -543,6 +528,68 @@
309 }
310
311 /**
312+ * event_operator_subtree_environment:
313+ * @root: operator tree to collect from,
314+ * @env: NULL-terminated array of environment variables to add to,
315+ * @parent: parent object for new array,
316+ * @len: length of @env,
317+ * @key: key of variable to contain event names,
318+ * @evlist: string in which to accumulate the event list.
319+ *
320+ * Does the work of event_operator_environment for one subtree.
321+ **/
322+
323+static char**
324+event_operator_subtree_environment (EventOperator *oper,
325+ char ***env,
326+ const void *parent,
327+ size_t *len,
328+ const char *key,
329+ char **evlist)
330+{
331+ /* Filtering out nodes with a non-TRUE value and their children. The
332+ * rationale for this is that this then matches only the events that had
333+ * an active role in starting the job, not the ones that were also
334+ * blocked, but the other half of their logic wasn't present.
335+ */
336+ if (! oper->value)
337+ return *env;
338+
339+ if (oper->type != EVENT_MATCH) {
340+ NIH_LIST_FOREACH(&oper->children, iter) {
341+ EventOperator *child = (EventOperator *)iter;
342+ if (! event_operator_subtree_environment (child, env, parent,
343+ len, key, evlist))
344+ return NULL;
345+ }
346+
347+ return *env;
348+ }
349+
350+ nih_assert (oper->event != NULL);
351+
352+ /* Add environment from the event */
353+ if (! environ_append (env, parent, len, TRUE, oper->event->env))
354+ return NULL;
355+
356+ /* Append the name of the event to the string we're building */
357+ if (*evlist) {
358+ if ((*evlist)[strlen (*evlist) - 1] != '=') {
359+ if (! nih_strcat_sprintf (evlist, NULL, " %s",
360+ oper->event->name))
361+ return NULL;
362+ } else {
363+ if (! nih_strcat (evlist, NULL,
364+ oper->event->name)) {
365+ return NULL;
366+ }
367+ }
368+ }
369+
370+ return *env;
371+}
372+
373+/**
374 * event_operator_events:
375 * @root: operator tree to collect from,
376 * @parent: parent object for blocked structures,
377@@ -564,31 +611,31 @@
378 const void *parent,
379 NihList *list)
380 {
381+ Blocked *blocked;
382+
383 nih_assert (root != NULL);
384 nih_assert (list != NULL);
385
386- /* Iterate the operator tree, filtering out nodes with a non-TRUE
387- * value and their children. The rationale for this is that this
388- * then matches only the events that had an active role in starting
389- * the job, not the ones that were also blocked, but the other half
390- * of their logic wasn't present.
391- */
392- NIH_TREE_FOREACH_FULL (&root->node, iter,
393- (NihTreeFilter)event_operator_filter, NULL) {
394+ if (! root->value)
395+ return;
396+
397+ NIH_LIST_FOREACH (&root->children, iter) {
398 EventOperator *oper = (EventOperator *)iter;
399- Blocked *blocked;
400-
401- if (oper->type != EVENT_MATCH)
402- continue;
403-
404- nih_assert (oper->event != NULL);
405-
406- blocked = NIH_MUST (blocked_new (parent, BLOCKED_EVENT,
407- oper->event));
408- nih_list_add (list, &blocked->entry);
409-
410- event_block (blocked->event);
411+
412+ event_operator_events (oper, parent, list);
413 }
414+
415+
416+ if (root->type != EVENT_MATCH)
417+ return;
418+
419+ nih_assert (root->event != NULL);
420+
421+ blocked = NIH_MUST (blocked_new (parent, BLOCKED_EVENT,
422+ root->event));
423+ nih_list_add (list, &blocked->entry);
424+
425+ event_block (blocked->event);
426 }
427
428
429@@ -606,24 +653,26 @@
430 nih_assert (root != NULL);
431
432 /* A post-order iteration means we visit children first, perfect! */
433- NIH_TREE_FOREACH_POST (&root->node, iter) {
434+ NIH_LIST_FOREACH (&root->children, iter) {
435 EventOperator *oper = (EventOperator *)iter;
436
437- switch (oper->type) {
438- case EVENT_OR:
439- case EVENT_AND:
440- event_operator_update (oper);
441- break;
442- case EVENT_MATCH:
443- oper->value = FALSE;
444-
445- if (oper->event) {
446- event_unblock (oper->event);
447- oper->event = NULL;
448- }
449- break;
450- default:
451- nih_assert_not_reached ();
452+ event_operator_reset (oper);
453+ }
454+
455+ switch (root->type) {
456+ case EVENT_ANY:
457+ case EVENT_ALL:
458+ event_operator_update (root);
459+ break;
460+ case EVENT_MATCH:
461+ root->value = FALSE;
462+
463+ if (root->event) {
464+ event_unblock (root->event);
465+ root->event = NULL;
466 }
467+ break;
468+ default:
469+ nih_assert_not_reached ();
470 }
471 }
472
473=== modified file 'init/event_operator.h'
474--- init/event_operator.h 2009-06-23 09:29:35 +0000
475+++ init/event_operator.h 2009-08-11 05:12:01 +0000
476@@ -33,14 +33,15 @@
477 * the EventOperator structure.
478 **/
479 typedef enum event_operator_type {
480- EVENT_OR,
481- EVENT_AND,
482+ EVENT_ANY,
483+ EVENT_ALL,
484 EVENT_MATCH
485 } EventOperatorType;
486
487 /**
488 * EventOperator:
489- * @node: tree node,
490+ * @entry: sibling list entry,
491+ * @children: list of children,
492 * @type: operator type,
493 * @value: operator value,
494 * @name: name of event to match (EVENT_MATCH only),
495@@ -49,19 +50,20 @@
496 *
497 * This structure is used to build up an event expression tree; the leaf
498 * nodes are all of EVENT_MATCH type which match a specific event, the other
499- * nodes are built up of EVENT_OR and EVENT_AND operators that combine the
500- * EventOperators to their left and right in interesting ways.
501+ * nodes are built up of EVENT_ANY and EVENT_ALL operators that combine the
502+ * EventOperators which are their children in interesting ways.
503 *
504 * @value indicates whether this operator is currently TRUE or FALSE.
505 * For EVENT_MATCH operators, a TRUE @value means that @event is set to
506- * the matched event; for EVENT_OR and EVENT_AND operators, @value is set
507- * depending on the value of both immediate children.
508+ * the matched event; for EVENT_ANY and EVENT_ALL operators, @value is set
509+ * depending on the value of the immediate children.
510 *
511 * Once an event has been matched, the @event member is set and a reference
512 * held until the structure is cleared.
513 **/
514 typedef struct event_operator {
515- NihTree node;
516+ NihList entry;
517+ NihList children;
518 EventOperatorType type;
519
520 int value;
521@@ -84,6 +86,8 @@
522 __attribute__ ((warn_unused_result, malloc));
523
524 int event_operator_destroy (EventOperator *oper);
525+void event_operator_add_child (EventOperator *oper,
526+ EventOperator *child);
527
528 void event_operator_update (EventOperator *oper);
529 int event_operator_match (EventOperator *oper, Event *event,
530
531=== modified file 'init/parse_job.c'
532--- init/parse_job.c 2009-07-09 11:01:53 +0000
533+++ init/parse_job.c 2009-08-11 05:12:01 +0000
534@@ -644,9 +644,9 @@
535 * back to the starting position and deal with it as an operand.
536 */
537 if (! strcmp (arg, "and")) {
538- type = EVENT_AND;
539+ type = EVENT_ALL;
540 } else if (! strcmp (arg, "or")) {
541- type = EVENT_OR;
542+ type = EVENT_ANY;
543 } else {
544 return parse_on_operand (class, stanza, file, len, pos, lineno,
545 stack, root);
546@@ -665,10 +665,8 @@
547 if (! oper)
548 nih_return_system_error (-1);
549
550- nih_ref (*root, oper);
551+ event_operator_add_child (oper, *root);
552 nih_unref (*root, class);
553-
554- nih_tree_add (&oper->node, &(*root)->node, NIH_TREE_LEFT);
555 *root = NULL;
556
557 /* Push the new operator onto the stack */
558@@ -938,11 +936,8 @@
559 * event matches.
560 */
561 if ((oper->type != EVENT_MATCH) && (*root)) {
562- nih_ref (*root, oper);
563+ event_operator_add_child (oper, *root);
564 nih_unref (*root, class);
565-
566- nih_tree_add (&oper->node, &(*root)->node,
567- NIH_TREE_RIGHT);
568 } else if (oper->type != EVENT_MATCH) {
569 nih_return_error (-1, PARSE_EXPECTED_EVENT,
570 _(PARSE_EXPECTED_EVENT_STR));
571
572=== modified file 'init/tests/test_event.c'
573--- init/tests/test_event.c 2009-08-04 00:19:41 +0000
574+++ init/tests/test_event.c 2009-08-11 05:51:31 +0000
575@@ -275,6 +275,7 @@
576 EventOperator *oper;
577 Blocked *blocked = NULL, *blocked1 = NULL, *blocked2 = NULL;
578 char **env1 = NULL, **env2 = NULL;
579+ int any_true = FALSE, all_true = TRUE;
580
581 TEST_FUNCTION ("event_pending_handle_jobs");
582 program_name = "test";
583@@ -331,17 +332,15 @@
584 class->task = TRUE;
585
586 class->start_on = event_operator_new (
587- class, EVENT_AND, NULL, NULL);
588+ class, EVENT_ALL, NULL, NULL);
589
590 oper = event_operator_new (
591 class->start_on, EVENT_MATCH, "wibble", NULL);
592- nih_tree_add (&class->start_on->node, &oper->node,
593- NIH_TREE_LEFT);
594+ event_operator_add_child (class->start_on, oper);
595
596 oper = event_operator_new (
597 class->start_on, EVENT_MATCH, "wobble", NULL);
598- nih_tree_add (&class->start_on->node, &oper->node,
599- NIH_TREE_RIGHT);
600+ event_operator_add_child (class->start_on, oper);
601
602 nih_hash_add (job_classes, &class->entry);
603 }
604@@ -358,13 +357,18 @@
605 TEST_EQ (oper->value, FALSE);
606 TEST_EQ_P (oper->event, NULL);
607
608- oper = (EventOperator *)class->start_on->node.left;
609- TEST_EQ (oper->value, TRUE);
610- TEST_EQ_P (oper->event, event1);
611-
612- oper = (EventOperator *)class->start_on->node.right;
613- TEST_EQ (oper->value, FALSE);
614- TEST_EQ_P (oper->event, NULL);
615+ NIH_LIST_FOREACH (&oper->children, iter) {
616+ EventOperator *child = (EventOperator *)iter;
617+
618+ any_true = any_true || child->value;
619+ all_true = all_true && child->value;
620+ }
621+
622+ TEST_EQ (any_true, TRUE);
623+ TEST_EQ (all_true, FALSE);
624+
625+ any_true = FALSE;
626+ all_true = TRUE;
627
628 nih_free (class);
629 nih_free (event1);
630@@ -395,17 +399,15 @@
631 NULL, "BAR=BAZ"));
632
633 class->start_on = event_operator_new (
634- class, EVENT_AND, NULL, NULL);
635+ class, EVENT_ALL, NULL, NULL);
636
637 oper = event_operator_new (
638 class->start_on, EVENT_MATCH, "wibble", NULL);
639- nih_tree_add (&class->start_on->node, &oper->node,
640- NIH_TREE_LEFT);
641+ event_operator_add_child (class->start_on, oper);
642
643 oper = event_operator_new (
644 class->start_on, EVENT_MATCH, "wobble", NULL);
645- nih_tree_add (&class->start_on->node, &oper->node,
646- NIH_TREE_RIGHT);
647+ event_operator_add_child (class->start_on, oper);
648
649 nih_hash_add (job_classes, &class->entry);
650 }
651@@ -447,14 +449,18 @@
652 TEST_EQ (oper->value, FALSE);
653 TEST_EQ_P (oper->event, NULL);
654
655- oper = (EventOperator *)class->start_on->node.left;
656- TEST_EQ (oper->value, FALSE);
657- TEST_EQ_P (oper->event, NULL);
658-
659- oper = (EventOperator *)class->start_on->node.right;
660- TEST_EQ (oper->value, FALSE);
661- TEST_EQ_P (oper->event, NULL);
662-
663+ NIH_LIST_FOREACH (&oper->children, iter) {
664+ EventOperator *child = (EventOperator *)iter;
665+
666+ any_true = any_true || child->value;
667+ all_true = all_true && child->value;
668+ }
669+
670+ TEST_EQ (any_true, FALSE);
671+ TEST_EQ (all_true, FALSE);
672+
673+ any_true = FALSE;
674+ all_true = TRUE;
675
676 TEST_LIST_NOT_EMPTY (&job->blocking);
677
678@@ -511,17 +517,15 @@
679 NULL, "BAR=BAZ"));
680
681 class->start_on = event_operator_new (
682- class, EVENT_AND, NULL, NULL);
683+ class, EVENT_ALL, NULL, NULL);
684
685 oper = event_operator_new (
686 class->start_on, EVENT_MATCH, "wibble", NULL);
687- nih_tree_add (&class->start_on->node, &oper->node,
688- NIH_TREE_LEFT);
689+ event_operator_add_child (class->start_on, oper);
690
691 oper = event_operator_new (
692 class->start_on, EVENT_MATCH, "wobble", NULL);
693- nih_tree_add (&class->start_on->node, &oper->node,
694- NIH_TREE_RIGHT);
695+ event_operator_add_child (class->start_on, oper);
696
697 nih_hash_add (job_classes, &class->entry);
698 }
699@@ -572,13 +576,18 @@
700 oper = class->start_on;
701 TEST_EQ (oper->value, FALSE);
702
703- oper = (EventOperator *)class->start_on->node.left;
704- TEST_EQ (oper->value, FALSE);
705- TEST_EQ_P (oper->event, NULL);
706-
707- oper = (EventOperator *)class->start_on->node.right;
708- TEST_EQ (oper->value, FALSE);
709- TEST_EQ_P (oper->event, NULL);
710+ NIH_LIST_FOREACH (&oper->children, iter) {
711+ EventOperator *child = (EventOperator *)iter;
712+
713+ any_true = any_true || child->value;
714+ all_true = all_true && child->value;
715+ }
716+
717+ TEST_EQ (any_true, FALSE);
718+ TEST_EQ (all_true, FALSE);
719+
720+ any_true = FALSE;
721+ all_true = TRUE;
722
723
724 TEST_LIST_NOT_EMPTY (&job->blocking);
725@@ -637,17 +646,15 @@
726 NULL, "BAR=BAZ"));
727
728 class->start_on = event_operator_new (
729- class, EVENT_AND, NULL, NULL);
730+ class, EVENT_ALL, NULL, NULL);
731
732 oper = event_operator_new (
733 class->start_on, EVENT_MATCH, "wibble", NULL);
734- nih_tree_add (&class->start_on->node, &oper->node,
735- NIH_TREE_LEFT);
736+ event_operator_add_child (class->start_on, oper);
737
738 oper = event_operator_new (
739 class->start_on, EVENT_MATCH, "wobble", NULL);
740- nih_tree_add (&class->start_on->node, &oper->node,
741- NIH_TREE_RIGHT);
742+ event_operator_add_child (class->start_on, oper);
743
744 nih_hash_add (job_classes, &class->entry);
745
746@@ -736,13 +743,18 @@
747 oper = class->start_on;
748 TEST_EQ (oper->value, FALSE);
749
750- oper = (EventOperator *)class->start_on->node.left;
751- TEST_EQ (oper->value, FALSE);
752- TEST_EQ_P (oper->event, NULL);
753-
754- oper = (EventOperator *)class->start_on->node.right;
755- TEST_EQ (oper->value, FALSE);
756- TEST_EQ_P (oper->event, NULL);
757+ NIH_LIST_FOREACH (&oper->children, iter) {
758+ EventOperator *child = (EventOperator *)iter;
759+
760+ any_true = any_true || child->value;
761+ all_true = all_true && child->value;
762+ }
763+
764+ TEST_EQ (any_true, FALSE);
765+ TEST_EQ (all_true, FALSE);
766+
767+ any_true = FALSE;
768+ all_true = TRUE;
769
770 TEST_FREE (blocked1);
771 TEST_FREE (blocked2);
772@@ -805,17 +817,15 @@
773 NULL, "BAR=BAZ"));
774
775 class->start_on = event_operator_new (
776- class, EVENT_AND, NULL, NULL);
777+ class, EVENT_ALL, NULL, NULL);
778
779 oper = event_operator_new (
780 class->start_on, EVENT_MATCH, "wibble", NULL);
781- nih_tree_add (&class->start_on->node, &oper->node,
782- NIH_TREE_LEFT);
783+ event_operator_add_child (class->start_on, oper);
784
785 oper = event_operator_new (
786 class->start_on, EVENT_MATCH, "wobble", NULL);
787- nih_tree_add (&class->start_on->node, &oper->node,
788- NIH_TREE_RIGHT);
789+ event_operator_add_child (class->start_on, oper);
790
791 nih_hash_add (job_classes, &class->entry);
792
793@@ -886,13 +896,18 @@
794 oper = class->start_on;
795 TEST_EQ (oper->value, FALSE);
796
797- oper = (EventOperator *)class->start_on->node.left;
798- TEST_EQ (oper->value, FALSE);
799- TEST_EQ_P (oper->event, NULL);
800-
801- oper = (EventOperator *)class->start_on->node.right;
802- TEST_EQ (oper->value, FALSE);
803- TEST_EQ_P (oper->event, NULL);
804+ NIH_LIST_FOREACH (&oper->children, iter) {
805+ EventOperator *child = (EventOperator *)iter;
806+
807+ any_true = any_true || child->value;
808+ all_true = all_true && child->value;
809+ }
810+
811+ TEST_EQ (any_true, FALSE);
812+ TEST_EQ (all_true, FALSE);
813+
814+ any_true = FALSE;
815+ all_true = TRUE;
816
817 TEST_LIST_NOT_EMPTY (&job->blocking);
818 TEST_NOT_FREE (blocked1);
819@@ -1704,17 +1719,15 @@
820 class->process[PROCESS_MAIN]->command = "echo";
821
822 class->start_on = event_operator_new (
823- class, EVENT_OR, NULL, NULL);
824+ class, EVENT_ANY, NULL, NULL);
825
826 oper = event_operator_new (class, EVENT_MATCH,
827 "test/failed", NULL);
828- nih_tree_add (&class->start_on->node, &oper->node,
829- NIH_TREE_LEFT);
830+ event_operator_add_child (class->start_on, oper);
831
832 oper = event_operator_new (class, EVENT_MATCH,
833 "test/failed/failed", NULL);
834- nih_tree_add (&class->start_on->node, &oper->node,
835- NIH_TREE_RIGHT);
836+ event_operator_add_child (class->start_on, oper);
837
838 nih_hash_add (job_classes, &class->entry);
839 }
840
841=== modified file 'init/tests/test_event_operator.c'
842--- init/tests/test_event_operator.c 2009-08-04 00:20:04 +0000
843+++ init/tests/test_event_operator.c 2009-08-11 05:51:31 +0000
844@@ -53,9 +53,7 @@
845 }
846
847 TEST_ALLOC_SIZE (oper, sizeof (EventOperator));
848- TEST_EQ_P (oper->node.parent, NULL);
849- TEST_EQ_P (oper->node.left, NULL);
850- TEST_EQ_P (oper->node.right, NULL);
851+ TEST_LIST_EMPTY (&oper->children);
852 TEST_EQ (oper->value, FALSE);
853 TEST_EQ_STR (oper->name, "test");
854 TEST_ALLOC_PARENT (oper->name, oper);
855@@ -92,9 +90,7 @@
856 nih_discard (env);
857
858 TEST_ALLOC_SIZE (oper, sizeof (EventOperator));
859- TEST_EQ_P (oper->node.parent, NULL);
860- TEST_EQ_P (oper->node.left, NULL);
861- TEST_EQ_P (oper->node.right, NULL);
862+ TEST_LIST_EMPTY (&oper->children);
863 TEST_EQ (oper->value, FALSE);
864 TEST_EQ_STR (oper->name, "test");
865 TEST_ALLOC_PARENT (oper->name, oper);
866@@ -109,9 +105,9 @@
867
868
869 /* Check that an ordinary operator needs no name attached. */
870- TEST_FEATURE ("with EVENT_OR");
871+ TEST_FEATURE ("with EVENT_ANY");
872 TEST_ALLOC_FAIL {
873- oper = event_operator_new (NULL, EVENT_OR, NULL, NULL);
874+ oper = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
875
876 if (test_alloc_failed) {
877 TEST_EQ_P (oper, NULL);
878@@ -119,9 +115,7 @@
879 }
880
881 TEST_ALLOC_SIZE (oper, sizeof (EventOperator));
882- TEST_EQ_P (oper->node.parent, NULL);
883- TEST_EQ_P (oper->node.left, NULL);
884- TEST_EQ_P (oper->node.right, NULL);
885+ TEST_LIST_EMPTY (&oper->children);
886 TEST_EQ (oper->value, FALSE);
887 TEST_EQ_P (oper->name, NULL);
888 TEST_EQ_P (oper->env, NULL);
889@@ -143,10 +137,10 @@
890 /* Check that we can copy a plain event operator, the value should
891 * be copied as well, and the other fields left as NULL.
892 */
893- TEST_FEATURE ("with EVENT_OR");
894+ TEST_FEATURE ("with EVENT_ANY");
895 TEST_ALLOC_FAIL {
896 TEST_ALLOC_SAFE {
897- oper = event_operator_new (NULL, EVENT_OR, NULL, NULL);
898+ oper = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
899 oper->value = TRUE;
900 }
901
902@@ -159,10 +153,8 @@
903 }
904
905 TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
906- TEST_EQ_P (copy->node.parent, NULL);
907- TEST_EQ_P (copy->node.left, NULL);
908- TEST_EQ_P (copy->node.right, NULL);
909- TEST_EQ (copy->type, EVENT_OR);
910+ TEST_LIST_EMPTY (&copy->children);
911+ TEST_EQ (copy->type, EVENT_ANY);
912 TEST_EQ (copy->value, TRUE);
913 TEST_EQ_P (copy->name, NULL);
914 TEST_EQ_P (copy->env, NULL);
915@@ -193,9 +185,7 @@
916 }
917
918 TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
919- TEST_EQ_P (copy->node.parent, NULL);
920- TEST_EQ_P (copy->node.left, NULL);
921- TEST_EQ_P (copy->node.right, NULL);
922+ TEST_LIST_EMPTY (&copy->children);
923 TEST_EQ (copy->type, EVENT_MATCH);
924 TEST_EQ (copy->value, TRUE);
925 TEST_EQ_STR (copy->name, "test");
926@@ -233,9 +223,7 @@
927 }
928
929 TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
930- TEST_EQ_P (copy->node.parent, NULL);
931- TEST_EQ_P (copy->node.left, NULL);
932- TEST_EQ_P (copy->node.right, NULL);
933+ TEST_LIST_EMPTY (&copy->children);
934 TEST_EQ (copy->type, EVENT_MATCH);
935 TEST_EQ (copy->value, TRUE);
936 TEST_EQ_STR (copy->name, "test");
937@@ -279,9 +267,7 @@
938 }
939
940 TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
941- TEST_EQ_P (copy->node.parent, NULL);
942- TEST_EQ_P (copy->node.left, NULL);
943- TEST_EQ_P (copy->node.right, NULL);
944+ TEST_LIST_EMPTY (&copy->children);
945 TEST_EQ (copy->type, EVENT_MATCH);
946 TEST_EQ (copy->value, TRUE);
947 TEST_EQ_STR (copy->name, "test");
948@@ -302,7 +288,7 @@
949 TEST_FEATURE ("with children");
950 TEST_ALLOC_FAIL {
951 TEST_ALLOC_SAFE {
952- oper = event_operator_new (NULL, EVENT_OR, NULL, NULL);
953+ oper = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
954 oper->value = TRUE;
955
956 oper1 = event_operator_new (NULL, EVENT_MATCH,
957@@ -310,45 +296,37 @@
958 oper1->value = TRUE;
959 oper1->event = event_new (oper1, "foo", NULL);
960 event_block (oper1->event);
961- nih_tree_add (&oper->node, &oper1->node,
962- NIH_TREE_LEFT);
963+ event_operator_add_child (oper, oper1);
964
965 oper2 = event_operator_new (NULL, EVENT_MATCH,
966 "bar", NULL);
967 oper2->value = TRUE;
968 oper2->event = event_new (oper2, "foo", NULL);
969 event_block (oper2->event);
970- nih_tree_add (&oper->node, &oper2->node,
971- NIH_TREE_RIGHT);
972+ event_operator_add_child (oper, oper2);
973 }
974
975 copy = event_operator_copy (NULL, oper);
976
977 if (test_alloc_failed) {
978 TEST_EQ_P (copy, NULL);
979- nih_free (oper);
980 TEST_EQ (oper1->event->blockers, 1);
981- nih_free (oper1);
982 TEST_EQ (oper2->event->blockers, 1);
983- nih_free (oper2);
984+ nih_free (oper);
985 continue;
986 }
987
988 TEST_ALLOC_SIZE (copy, sizeof (EventOperator));
989- TEST_EQ_P (copy->node.parent, NULL);
990- TEST_NE_P (copy->node.left, NULL);
991- TEST_NE_P (copy->node.right, NULL);
992- TEST_EQ (copy->type, EVENT_OR);
993+ TEST_LIST_NOT_EMPTY (&copy->children);
994+ TEST_EQ (copy->type, EVENT_ANY);
995 TEST_EQ (copy->value, TRUE);
996 TEST_EQ_P (copy->name, NULL);
997 TEST_EQ_P (copy->env, NULL);
998
999- copy1 = (EventOperator *)copy->node.left;
1000+ copy1 = (EventOperator *)copy->children.next;
1001 TEST_ALLOC_SIZE (copy1, sizeof (EventOperator));
1002 TEST_ALLOC_PARENT (copy1, copy);
1003- TEST_EQ_P (copy1->node.parent, &copy->node);
1004- TEST_EQ_P (copy1->node.left, NULL);
1005- TEST_EQ_P (copy1->node.right, NULL);
1006+ TEST_LIST_EMPTY (&copy1->children);
1007 TEST_EQ (copy1->type, EVENT_MATCH);
1008 TEST_EQ (copy1->value, TRUE);
1009 TEST_EQ_STR (copy1->name, "foo");
1010@@ -360,12 +338,10 @@
1011
1012 nih_free (copy1);
1013
1014- copy2 = (EventOperator *)copy->node.right;
1015+ copy2 = (EventOperator *)copy1->entry.next;
1016 TEST_ALLOC_SIZE (copy2, sizeof (EventOperator));
1017 TEST_ALLOC_PARENT (copy2, copy);
1018- TEST_EQ_P (copy2->node.parent, &copy->node);
1019- TEST_EQ_P (copy2->node.left, NULL);
1020- TEST_EQ_P (copy2->node.right, NULL);
1021+ TEST_LIST_EMPTY (&copy1->children);
1022 TEST_EQ (copy2->type, EVENT_MATCH);
1023 TEST_EQ (copy2->value, TRUE);
1024 TEST_EQ_STR (copy2->name, "bar");
1025@@ -430,16 +406,16 @@
1026 EventOperator *oper1, *oper2, *oper3;
1027
1028 TEST_FUNCTION ("event_operator_update");
1029- oper1 = event_operator_new (NULL, EVENT_OR, NULL, NULL);
1030+ oper1 = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
1031 oper2 = event_operator_new (NULL, EVENT_MATCH, "foo", NULL);
1032 oper3 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL);
1033
1034- nih_tree_add (&oper1->node, &oper2->node, NIH_TREE_LEFT);
1035- nih_tree_add (&oper1->node, &oper3->node, NIH_TREE_RIGHT);
1036-
1037-
1038- /* Check that EVENT_OR is FALSE if both children are FALSE. */
1039- TEST_FEATURE ("with EVENT_OR and both children FALSE");
1040+ event_operator_add_child (oper1, oper2);
1041+ event_operator_add_child (oper1, oper3);
1042+
1043+
1044+ /* Check that EVENT_ANY is FALSE if both children are FALSE. */
1045+ TEST_FEATURE ("with EVENT_ANY and both children FALSE");
1046 oper1->value = oper2->value = oper3->value = FALSE;
1047
1048 event_operator_update (oper1);
1049@@ -447,8 +423,8 @@
1050 TEST_EQ (oper1->value, FALSE);
1051
1052
1053- /* Check that EVENT_OR is TRUE if only the left child is TRUE. */
1054- TEST_FEATURE ("with EVENT_OR and only left child TRUE");
1055+ /* Check that EVENT_ANY is TRUE if only the left child is TRUE. */
1056+ TEST_FEATURE ("with EVENT_ANY and only left child TRUE");
1057 oper1->value = oper3->value = FALSE;
1058 oper2->value = TRUE;
1059
1060@@ -457,8 +433,8 @@
1061 TEST_EQ (oper1->value, TRUE);
1062
1063
1064- /* Check that EVENT_OR is TRUE if only the right child is TRUE. */
1065- TEST_FEATURE ("with EVENT_OR and only right child TRUE");
1066+ /* Check that EVENT_ANY is TRUE if only the right child is TRUE. */
1067+ TEST_FEATURE ("with EVENT_ANY and only right child TRUE");
1068 oper1->value = oper2->value = FALSE;
1069 oper3->value = TRUE;
1070
1071@@ -467,8 +443,8 @@
1072 TEST_EQ (oper1->value, TRUE);
1073
1074
1075- /* Check that EVENT_OR is TRUE if both children are TRUE. */
1076- TEST_FEATURE ("with EVENT_OR and both children TRUE");
1077+ /* Check that EVENT_ANY is TRUE if both children are TRUE. */
1078+ TEST_FEATURE ("with EVENT_ANY and both children TRUE");
1079 oper1->value = FALSE;
1080 oper2->value = oper3->value = TRUE;
1081
1082@@ -477,9 +453,9 @@
1083 TEST_EQ (oper1->value, TRUE);
1084
1085
1086- /* Check that EVENT_AND is FALSE if both children are FALSE. */
1087- TEST_FEATURE ("with EVENT_AND and both children FALSE");
1088- oper1->type = EVENT_AND;
1089+ /* Check that EVENT_ALL is FALSE if both children are FALSE. */
1090+ TEST_FEATURE ("with EVENT_ALL and both children FALSE");
1091+ oper1->type = EVENT_ALL;
1092 oper1->value = oper2->value = oper3->value = FALSE;
1093
1094 event_operator_update (oper1);
1095@@ -487,8 +463,8 @@
1096 TEST_EQ (oper1->value, FALSE);
1097
1098
1099- /* Check that EVENT_AND is FALSE if only the left child is TRUE. */
1100- TEST_FEATURE ("with EVENT_AND and only left child TRUE");
1101+ /* Check that EVENT_ALL is FALSE if only the left child is TRUE. */
1102+ TEST_FEATURE ("with EVENT_ALL and only left child TRUE");
1103 oper1->value = oper3->value = FALSE;
1104 oper2->value = TRUE;
1105
1106@@ -497,8 +473,8 @@
1107 TEST_EQ (oper1->value, FALSE);
1108
1109
1110- /* Check that EVENT_AND is FALSE if only the right child is TRUE. */
1111- TEST_FEATURE ("with EVENT_AND and only right child TRUE");
1112+ /* Check that EVENT_ALL is FALSE if only the right child is TRUE. */
1113+ TEST_FEATURE ("with EVENT_ALL and only right child TRUE");
1114 oper1->value = oper2->value = FALSE;
1115 oper3->value = TRUE;
1116
1117@@ -507,8 +483,8 @@
1118 TEST_EQ (oper1->value, FALSE);
1119
1120
1121- /* Check that EVENT_AND is TRUE if both children are TRUE. */
1122- TEST_FEATURE ("with EVENT_AND and both children TRUE");
1123+ /* Check that EVENT_ALL is TRUE if both children are TRUE. */
1124+ TEST_FEATURE ("with EVENT_ALL and both children TRUE");
1125 oper1->value = FALSE;
1126 oper2->value = oper3->value = TRUE;
1127
1128@@ -518,8 +494,6 @@
1129
1130
1131 nih_free (oper1);
1132- nih_free (oper2);
1133- nih_free (oper3);
1134 }
1135
1136 void
1137@@ -804,8 +778,8 @@
1138 int ret;
1139
1140 TEST_FUNCTION ("event_operator_handle");
1141- oper1 = event_operator_new (NULL, EVENT_OR, NULL, NULL);
1142- oper2 = event_operator_new (NULL, EVENT_AND, NULL, NULL);
1143+ oper1 = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
1144+ oper2 = event_operator_new (NULL, EVENT_ALL, NULL, NULL);
1145 oper3 = event_operator_new (NULL, EVENT_MATCH, "foo", NULL);
1146 oper4 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL);
1147 oper5 = event_operator_new (NULL, EVENT_MATCH, "baz", NULL);
1148@@ -813,10 +787,10 @@
1149 oper5->env[0] = "BAR=$WIBBLE";
1150 oper5->env[1] = NULL;
1151
1152- nih_tree_add (&oper1->node, &oper2->node, NIH_TREE_LEFT);
1153- nih_tree_add (&oper2->node, &oper3->node, NIH_TREE_LEFT);
1154- nih_tree_add (&oper2->node, &oper4->node, NIH_TREE_RIGHT);
1155- nih_tree_add (&oper1->node, &oper5->node, NIH_TREE_RIGHT);
1156+ event_operator_add_child (oper1, oper2);
1157+ event_operator_add_child (oper2, oper3);
1158+ event_operator_add_child (oper2, oper4);
1159+ event_operator_add_child (oper1, oper5);
1160
1161
1162 /* Check that a non-matching event doesn't touch the tree. */
1163@@ -938,10 +912,6 @@
1164 event_operator_reset (oper1);
1165
1166 nih_free (oper1);
1167- nih_free (oper2);
1168- nih_free (oper3);
1169- nih_free (oper4);
1170- nih_free (oper5);
1171
1172 event_poll ();
1173 }
1174@@ -956,20 +926,20 @@
1175 size_t len;
1176
1177 TEST_FUNCTION ("event_operator_environment");
1178- root = event_operator_new (NULL, EVENT_OR, NULL, NULL);
1179- oper1 = event_operator_new (root, EVENT_AND, NULL, NULL);
1180- oper2 = event_operator_new (root, EVENT_AND, NULL, NULL);
1181+ root = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
1182+ oper1 = event_operator_new (root, EVENT_ALL, NULL, NULL);
1183+ oper2 = event_operator_new (root, EVENT_ALL, NULL, NULL);
1184 oper3 = event_operator_new (root, EVENT_MATCH, "foo", NULL);
1185 oper4 = event_operator_new (root, EVENT_MATCH, "bar", NULL);
1186 oper5 = event_operator_new (root, EVENT_MATCH, "frodo", NULL);
1187 oper6 = event_operator_new (root, EVENT_MATCH, "bilbo", NULL);
1188
1189- nih_tree_add (&root->node, &oper1->node, NIH_TREE_LEFT);
1190- nih_tree_add (&root->node, &oper2->node, NIH_TREE_RIGHT);
1191- nih_tree_add (&oper1->node, &oper3->node, NIH_TREE_LEFT);
1192- nih_tree_add (&oper1->node, &oper4->node, NIH_TREE_RIGHT);
1193- nih_tree_add (&oper2->node, &oper5->node, NIH_TREE_LEFT);
1194- nih_tree_add (&oper2->node, &oper6->node, NIH_TREE_RIGHT);
1195+ event_operator_add_child (root, oper1);
1196+ event_operator_add_child (root, oper2);
1197+ event_operator_add_child (oper1, oper3);
1198+ event_operator_add_child (oper1, oper4);
1199+ event_operator_add_child (oper2, oper5);
1200+ event_operator_add_child (oper2, oper6);
1201
1202 root->value = TRUE;
1203
1204@@ -1124,20 +1094,20 @@
1205 Blocked *blocked;
1206
1207 TEST_FUNCTION ("event_operator_events");
1208- root = event_operator_new (NULL, EVENT_OR, NULL, NULL);
1209- oper1 = event_operator_new (root, EVENT_AND, NULL, NULL);
1210- oper2 = event_operator_new (root, EVENT_AND, NULL, NULL);
1211+ root = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
1212+ oper1 = event_operator_new (root, EVENT_ALL, NULL, NULL);
1213+ oper2 = event_operator_new (root, EVENT_ALL, NULL, NULL);
1214 oper3 = event_operator_new (root, EVENT_MATCH, "foo", NULL);
1215 oper4 = event_operator_new (root, EVENT_MATCH, "bar", NULL);
1216 oper5 = event_operator_new (root, EVENT_MATCH, "frodo", NULL);
1217 oper6 = event_operator_new (root, EVENT_MATCH, "bilbo", NULL);
1218
1219- nih_tree_add (&root->node, &oper1->node, NIH_TREE_LEFT);
1220- nih_tree_add (&root->node, &oper2->node, NIH_TREE_RIGHT);
1221- nih_tree_add (&oper1->node, &oper3->node, NIH_TREE_LEFT);
1222- nih_tree_add (&oper1->node, &oper4->node, NIH_TREE_RIGHT);
1223- nih_tree_add (&oper2->node, &oper5->node, NIH_TREE_LEFT);
1224- nih_tree_add (&oper2->node, &oper6->node, NIH_TREE_RIGHT);
1225+ event_operator_add_child (root, oper1);
1226+ event_operator_add_child (root, oper2);
1227+ event_operator_add_child (oper1, oper3);
1228+ event_operator_add_child (oper1, oper4);
1229+ event_operator_add_child (oper2, oper5);
1230+ event_operator_add_child (oper2, oper6);
1231
1232 root->value = TRUE;
1233
1234@@ -1232,16 +1202,16 @@
1235 * all the values back to FALSE.
1236 */
1237 TEST_FUNCTION ("event_operator_reset");
1238- oper1 = event_operator_new (NULL, EVENT_OR, NULL, NULL);
1239- oper2 = event_operator_new (NULL, EVENT_AND, NULL, NULL);
1240+ oper1 = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
1241+ oper2 = event_operator_new (NULL, EVENT_ALL, NULL, NULL);
1242 oper3 = event_operator_new (NULL, EVENT_MATCH, "foo", NULL);
1243 oper4 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL);
1244 oper5 = event_operator_new (NULL, EVENT_MATCH, "baz", NULL);
1245
1246- nih_tree_add (&oper1->node, &oper2->node, NIH_TREE_LEFT);
1247- nih_tree_add (&oper2->node, &oper3->node, NIH_TREE_LEFT);
1248- nih_tree_add (&oper2->node, &oper4->node, NIH_TREE_RIGHT);
1249- nih_tree_add (&oper1->node, &oper5->node, NIH_TREE_RIGHT);
1250+ event_operator_add_child (oper1, oper2);
1251+ event_operator_add_child (oper2, oper3);
1252+ event_operator_add_child (oper2, oper4);
1253+ event_operator_add_child (oper1, oper5);
1254
1255 event1 = event_new (NULL, "foo", NULL);
1256 event2 = event_new (NULL, "bar", NULL);
1257@@ -1274,15 +1244,73 @@
1258 TEST_EQ (event2->blockers, 0);
1259
1260 nih_free (oper1);
1261- nih_free (oper2);
1262- nih_free (oper3);
1263- nih_free (oper4);
1264- nih_free (oper5);
1265
1266 event_poll ();
1267 }
1268
1269
1270+void
1271+test_operator_add_child (void)
1272+{
1273+ EventOperator *oper1, *oper2, *oper3, *oper4, *oper5, *oper6, *oper7;
1274+ int found_foo = 0;
1275+ int found_bar = 0;
1276+ int found_baz = 0;
1277+ int found_bam = 0;
1278+ int found_all = 0;
1279+
1280+ TEST_FUNCTION ("event_operator_add_child");
1281+ oper1 = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
1282+ oper2 = event_operator_new (NULL, EVENT_ALL, NULL, NULL);
1283+ oper3 = event_operator_new (NULL, EVENT_MATCH, "foo", NULL);
1284+ oper4 = event_operator_new (NULL, EVENT_MATCH, "bar", NULL);
1285+ oper5 = event_operator_new (NULL, EVENT_MATCH, "baz", NULL);
1286+ oper6 = event_operator_new (NULL, EVENT_MATCH, "bam", NULL);
1287+ oper7 = event_operator_new (NULL, EVENT_ANY, NULL, NULL);
1288+
1289+ event_operator_add_child (oper2, oper3);
1290+ event_operator_add_child (oper2, oper4);
1291+ event_operator_add_child (oper7, oper5);
1292+ event_operator_add_child (oper7, oper6);
1293+ event_operator_add_child (oper1, oper2);
1294+ event_operator_add_child (oper1, oper7);
1295+
1296+ TEST_EQ (oper1->type, EVENT_ANY);
1297+
1298+ NIH_LIST_FOREACH (&oper1->children, iter) {
1299+ EventOperator *child = (EventOperator *)iter;
1300+
1301+ if (child->type == EVENT_ALL) {
1302+ found_all++;
1303+ continue;
1304+ }
1305+
1306+ TEST_EQ (child->type, EVENT_MATCH);
1307+
1308+ if (! strncmp (child->name, "foo", 4))
1309+ found_foo++;
1310+
1311+ if (! strncmp (child->name, "bar", 4))
1312+ found_bar++;
1313+
1314+ if (! strncmp (child->name, "baz", 4))
1315+ found_baz++;
1316+
1317+ if (! strncmp (child->name, "bam", 4))
1318+ found_bam++;
1319+ }
1320+
1321+ // Not a truth test. 2 is also a failure.
1322+ TEST_EQ (found_all, 1);
1323+ TEST_EQ (found_foo, 0);
1324+ TEST_EQ (found_bar, 0);
1325+ TEST_EQ (found_baz, 1);
1326+ TEST_EQ (found_bam, 1);
1327+
1328+ nih_free (oper1);
1329+}
1330+
1331+
1332 int
1333 main (int argc,
1334 char *argv[])
1335@@ -1296,6 +1324,7 @@
1336 test_operator_environment ();
1337 test_operator_events ();
1338 test_operator_reset ();
1339+ test_operator_add_child ();
1340
1341 return 0;
1342 }
1343
1344=== modified file 'init/tests/test_parse_job.c'
1345--- init/tests/test_parse_job.c 2009-07-09 11:01:53 +0000
1346+++ init/tests/test_parse_job.c 2009-08-11 05:12:01 +0000
1347@@ -1714,11 +1714,12 @@
1348 void
1349 test_stanza_start (void)
1350 {
1351- JobClass *job;
1352+ JobClass *job;
1353 EventOperator *oper;
1354 NihError *err;
1355 size_t pos, lineno;
1356 char buf[1024];
1357+ int got_wibble, got_wobble, got_wiggle;
1358
1359 TEST_FUNCTION ("stanza_start");
1360
1361@@ -1757,9 +1758,7 @@
1362 TEST_EQ_STR (oper->name, "wibble");
1363 TEST_EQ_P (oper->env, NULL);
1364
1365- TEST_EQ_P (oper->node.parent, NULL);
1366- TEST_EQ_P (oper->node.left, NULL);
1367- TEST_EQ_P (oper->node.right, NULL);
1368+ TEST_LIST_EMPTY (&oper->children);
1369
1370 nih_free (job);
1371 }
1372@@ -1807,9 +1806,7 @@
1373 TEST_EQ_STR (oper->env[2], "b?z*");
1374 TEST_EQ_P (oper->env[3], NULL);
1375
1376- TEST_EQ_P (oper->node.parent, NULL);
1377- TEST_EQ_P (oper->node.left, NULL);
1378- TEST_EQ_P (oper->node.right, NULL);
1379+ TEST_LIST_EMPTY (&oper->children);
1380
1381 nih_free (job);
1382 }
1383@@ -1861,9 +1858,7 @@
1384 TEST_EQ_STR (oper->env[4], "BILBO=foo bar");
1385 TEST_EQ_P (oper->env[5], NULL);
1386
1387- TEST_EQ_P (oper->node.parent, NULL);
1388- TEST_EQ_P (oper->node.left, NULL);
1389- TEST_EQ_P (oper->node.right, NULL);
1390+ TEST_LIST_EMPTY (&oper->children);
1391
1392 nih_free (job);
1393 }
1394@@ -1901,31 +1896,26 @@
1395 TEST_ALLOC_PARENT (job->start_on, job);
1396
1397 oper = job->start_on;
1398- TEST_EQ (oper->type, EVENT_OR);
1399-
1400- TEST_EQ_P (oper->node.parent, NULL);
1401- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1402- TEST_ALLOC_PARENT (oper->node.left, oper);
1403- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1404- TEST_ALLOC_PARENT (oper->node.right, oper);
1405-
1406- oper = (EventOperator *)job->start_on->node.left;
1407- TEST_EQ (oper->type, EVENT_MATCH);
1408- TEST_EQ_STR (oper->name, "wibble");
1409- TEST_EQ_P (oper->env, NULL);
1410-
1411- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1412- TEST_EQ_P (oper->node.left, NULL);
1413- TEST_EQ_P (oper->node.right, NULL);
1414-
1415- oper = (EventOperator *)job->start_on->node.right;
1416- TEST_EQ (oper->type, EVENT_MATCH);
1417- TEST_EQ_STR (oper->name, "wobble");
1418- TEST_EQ_P (oper->env, NULL);
1419-
1420- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1421- TEST_EQ_P (oper->node.left, NULL);
1422- TEST_EQ_P (oper->node.right, NULL);
1423+ TEST_EQ (oper->type, EVENT_ANY);
1424+
1425+ got_wibble = FALSE;
1426+ got_wobble = FALSE;
1427+ EventOperator *parent = oper;
1428+ NIH_LIST_FOREACH (&oper->children, iter) {
1429+ EventOperator *child = (EventOperator *)iter;
1430+
1431+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1432+
1433+ TEST_LIST_EMPTY (&child->children);
1434+ TEST_EQ_P (child->env, NULL);
1435+ TEST_EQ (child->type, EVENT_MATCH);
1436+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble)
1437+ got_wibble = TRUE;
1438+ else if (!strncmp ("wobble", child->name, 7) && ! got_wobble)
1439+ got_wobble = TRUE;
1440+ else
1441+ TEST_FAILED ("Unexpected child");
1442+ }
1443
1444 nih_free (job);
1445 }
1446@@ -1964,39 +1954,32 @@
1447 TEST_ALLOC_PARENT (job->start_on, job);
1448
1449 oper = job->start_on;
1450- TEST_EQ (oper->type, EVENT_AND);
1451-
1452- TEST_EQ_P (oper->node.parent, NULL);
1453- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1454- TEST_ALLOC_PARENT (oper->node.left, oper);
1455- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1456- TEST_ALLOC_PARENT (oper->node.right, oper);
1457-
1458- oper = (EventOperator *)job->start_on->node.left;
1459- TEST_EQ (oper->type, EVENT_MATCH);
1460- TEST_EQ_STR (oper->name, "wibble");
1461-
1462- TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
1463- TEST_EQ_STR (oper->env[0], "foo");
1464- TEST_EQ_STR (oper->env[1], "bar");
1465- TEST_EQ_P (oper->env[2], NULL);
1466-
1467- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1468- TEST_EQ_P (oper->node.left, NULL);
1469- TEST_EQ_P (oper->node.right, NULL);
1470-
1471- oper = (EventOperator *)job->start_on->node.right;
1472- TEST_EQ (oper->type, EVENT_MATCH);
1473- TEST_EQ_STR (oper->name, "wobble");
1474-
1475- TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
1476- TEST_EQ_STR (oper->env[0], "frodo");
1477- TEST_EQ_STR (oper->env[1], "bilbo");
1478- TEST_EQ_P (oper->env[2], NULL);
1479-
1480- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1481- TEST_EQ_P (oper->node.left, NULL);
1482- TEST_EQ_P (oper->node.right, NULL);
1483+ TEST_EQ (oper->type, EVENT_ALL);
1484+
1485+ got_wibble = FALSE;
1486+ got_wobble = FALSE;
1487+ NIH_LIST_FOREACH (&oper->children, iter) {
1488+ EventOperator *child = (EventOperator *)iter;
1489+
1490+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1491+
1492+ TEST_LIST_EMPTY (&child->children);
1493+ TEST_EQ (child->type, EVENT_MATCH);
1494+ TEST_ALLOC_SIZE (child->env, sizeof (char *) * 3);
1495+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
1496+ got_wibble = TRUE;
1497+ TEST_EQ_STR (child->env[0], "foo");
1498+ TEST_EQ_STR (child->env[1], "bar");
1499+ TEST_EQ_P (child->env[2], NULL);
1500+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
1501+ got_wobble = TRUE;
1502+ TEST_EQ_STR (child->env[0], "frodo");
1503+ TEST_EQ_STR (child->env[1], "bilbo");
1504+ TEST_EQ_P (child->env[2], NULL);
1505+ } else {
1506+ TEST_FAILED ("Unexpected child");
1507+ }
1508+ }
1509
1510 nih_free (job);
1511 }
1512@@ -2034,48 +2017,29 @@
1513 TEST_ALLOC_PARENT (job->start_on, job);
1514
1515 oper = job->start_on;
1516- TEST_EQ (oper->type, EVENT_OR);
1517-
1518- TEST_EQ_P (oper->node.parent, NULL);
1519- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1520- TEST_ALLOC_PARENT (oper->node.left, oper);
1521- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1522- TEST_ALLOC_PARENT (oper->node.right, oper);
1523-
1524- oper = (EventOperator *)job->start_on->node.left;
1525- TEST_EQ (oper->type, EVENT_OR);
1526- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1527- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1528- TEST_ALLOC_PARENT (oper->node.left, oper);
1529- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1530- TEST_ALLOC_PARENT (oper->node.right, oper);
1531-
1532- oper = (EventOperator *)job->start_on->node.left->left;
1533- TEST_EQ (oper->type, EVENT_MATCH);
1534- TEST_EQ_STR (oper->name, "wibble");
1535- TEST_EQ_P (oper->env, NULL);
1536-
1537- TEST_EQ_P (oper->node.parent, job->start_on->node.left);
1538- TEST_EQ_P (oper->node.left, NULL);
1539- TEST_EQ_P (oper->node.right, NULL);
1540-
1541- oper = (EventOperator *)job->start_on->node.left->right;
1542- TEST_EQ (oper->type, EVENT_MATCH);
1543- TEST_EQ_STR (oper->name, "wobble");
1544- TEST_EQ_P (oper->env, NULL);
1545-
1546- TEST_EQ_P (oper->node.parent, job->start_on->node.left);
1547- TEST_EQ_P (oper->node.left, NULL);
1548- TEST_EQ_P (oper->node.right, NULL);
1549-
1550- oper = (EventOperator *)job->start_on->node.right;
1551- TEST_EQ (oper->type, EVENT_MATCH);
1552- TEST_EQ_STR (oper->name, "wiggle");
1553- TEST_EQ_P (oper->env, NULL);
1554-
1555- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1556- TEST_EQ_P (oper->node.left, NULL);
1557- TEST_EQ_P (oper->node.right, NULL);
1558+ TEST_EQ (oper->type, EVENT_ANY);
1559+
1560+ got_wibble = FALSE;
1561+ got_wobble = FALSE;
1562+ got_wiggle = FALSE;
1563+ NIH_LIST_FOREACH (&oper->children, iter) {
1564+ EventOperator *child = (EventOperator *)iter;
1565+
1566+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1567+
1568+ TEST_LIST_EMPTY (&child->children);
1569+ TEST_EQ (child->type, EVENT_MATCH);
1570+ TEST_EQ_P (child->env, NULL);
1571+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
1572+ got_wibble = TRUE;
1573+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
1574+ got_wobble = TRUE;
1575+ } else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
1576+ got_wiggle = TRUE;
1577+ } else {
1578+ TEST_FAILED ("Unexpected child");
1579+ }
1580+ }
1581
1582 nih_free (job);
1583 }
1584@@ -2112,49 +2076,29 @@
1585 TEST_ALLOC_PARENT (job->start_on, job);
1586
1587 oper = job->start_on;
1588- TEST_EQ (oper->type, EVENT_OR);
1589-
1590- TEST_EQ_P (oper->node.parent, NULL);
1591- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1592- TEST_ALLOC_PARENT (oper->node.left, oper);
1593- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1594- TEST_ALLOC_PARENT (oper->node.right, oper);
1595-
1596- oper = (EventOperator *)job->start_on->node.left;
1597- TEST_EQ (oper->type, EVENT_MATCH);
1598- TEST_EQ_STR (oper->name, "wibble");
1599- TEST_EQ_P (oper->env, NULL);
1600-
1601- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1602- TEST_EQ_P (oper->node.left, NULL);
1603- TEST_EQ_P (oper->node.right, NULL);
1604-
1605- oper = (EventOperator *)job->start_on->node.right;
1606- TEST_EQ (oper->type, EVENT_OR);
1607-
1608- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1609- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1610- TEST_ALLOC_PARENT (oper->node.left, oper);
1611- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1612- TEST_ALLOC_PARENT (oper->node.right, oper);
1613-
1614- oper = (EventOperator *)job->start_on->node.right->left;
1615- TEST_EQ (oper->type, EVENT_MATCH);
1616- TEST_EQ_STR (oper->name, "wobble");
1617- TEST_EQ_P (oper->env, NULL);
1618-
1619- TEST_EQ_P (oper->node.parent, job->start_on->node.right);
1620- TEST_EQ_P (oper->node.left, NULL);
1621- TEST_EQ_P (oper->node.right, NULL);
1622-
1623- oper = (EventOperator *)job->start_on->node.right->right;
1624- TEST_EQ (oper->type, EVENT_MATCH);
1625- TEST_EQ_STR (oper->name, "wiggle");
1626- TEST_EQ_P (oper->env, NULL);
1627-
1628- TEST_EQ_P (oper->node.parent, job->start_on->node.right);
1629- TEST_EQ_P (oper->node.left, NULL);
1630- TEST_EQ_P (oper->node.right, NULL);
1631+ TEST_EQ (oper->type, EVENT_ANY);
1632+
1633+ got_wibble = FALSE;
1634+ got_wobble = FALSE;
1635+ got_wiggle = FALSE;
1636+ NIH_LIST_FOREACH (&oper->children, iter) {
1637+ EventOperator *child = (EventOperator *)iter;
1638+
1639+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1640+
1641+ TEST_LIST_EMPTY (&child->children);
1642+ TEST_EQ (child->type, EVENT_MATCH);
1643+ TEST_EQ_P (child->env, NULL);
1644+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
1645+ got_wibble = TRUE;
1646+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
1647+ got_wobble = TRUE;
1648+ } else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
1649+ got_wiggle = TRUE;
1650+ } else {
1651+ TEST_FAILED ("Unexpected child");
1652+ }
1653+ }
1654
1655 nih_free (job);
1656 }
1657@@ -2192,49 +2136,29 @@
1658 TEST_ALLOC_PARENT (job->start_on, job);
1659
1660 oper = job->start_on;
1661- TEST_EQ (oper->type, EVENT_OR);
1662-
1663- TEST_EQ_P (oper->node.parent, NULL);
1664- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1665- TEST_ALLOC_PARENT (oper->node.left, oper);
1666- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1667- TEST_ALLOC_PARENT (oper->node.right, oper);
1668-
1669- oper = (EventOperator *)job->start_on->node.left;
1670- TEST_EQ (oper->type, EVENT_MATCH);
1671- TEST_EQ_STR (oper->name, "wibble");
1672- TEST_EQ_P (oper->env, NULL);
1673-
1674- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1675- TEST_EQ_P (oper->node.left, NULL);
1676- TEST_EQ_P (oper->node.right, NULL);
1677-
1678- oper = (EventOperator *)job->start_on->node.right;
1679- TEST_EQ (oper->type, EVENT_OR);
1680-
1681- TEST_EQ_P (oper->node.parent, &job->start_on->node);
1682- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1683- TEST_ALLOC_PARENT (oper->node.left, oper);
1684- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1685- TEST_ALLOC_PARENT (oper->node.right, oper);
1686-
1687- oper = (EventOperator *)job->start_on->node.right->left;
1688- TEST_EQ (oper->type, EVENT_MATCH);
1689- TEST_EQ_STR (oper->name, "wobble");
1690- TEST_EQ_P (oper->env, NULL);
1691-
1692- TEST_EQ_P (oper->node.parent, job->start_on->node.right);
1693- TEST_EQ_P (oper->node.left, NULL);
1694- TEST_EQ_P (oper->node.right, NULL);
1695-
1696- oper = (EventOperator *)job->start_on->node.right->right;
1697- TEST_EQ (oper->type, EVENT_MATCH);
1698- TEST_EQ_STR (oper->name, "wiggle");
1699- TEST_EQ_P (oper->env, NULL);
1700-
1701- TEST_EQ_P (oper->node.parent, job->start_on->node.right);
1702- TEST_EQ_P (oper->node.left, NULL);
1703- TEST_EQ_P (oper->node.right, NULL);
1704+ TEST_EQ (oper->type, EVENT_ANY);
1705+
1706+ got_wibble = FALSE;
1707+ got_wobble = FALSE;
1708+ got_wiggle = FALSE;
1709+ NIH_LIST_FOREACH (&oper->children, iter) {
1710+ EventOperator *child = (EventOperator *)iter;
1711+
1712+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1713+
1714+ TEST_LIST_EMPTY (&child->children);
1715+ TEST_EQ (child->type, EVENT_MATCH);
1716+ TEST_EQ_P (child->env, NULL);
1717+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
1718+ got_wibble = TRUE;
1719+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
1720+ got_wobble = TRUE;
1721+ } else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
1722+ got_wiggle = TRUE;
1723+ } else {
1724+ TEST_FAILED ("Unexpected child");
1725+ }
1726+ }
1727
1728 nih_free (job);
1729 }
1730@@ -2275,9 +2199,7 @@
1731 TEST_EQ_STR (oper->name, "waggle");
1732 TEST_EQ_P (oper->env, NULL);
1733
1734- TEST_EQ_P (oper->node.parent, NULL);
1735- TEST_EQ_P (oper->node.left, NULL);
1736- TEST_EQ_P (oper->node.right, NULL);
1737+ TEST_LIST_EMPTY (&oper->children);
1738
1739 nih_free (job);
1740 }
1741@@ -2536,6 +2458,7 @@
1742 NihError *err;
1743 size_t pos, lineno;
1744 char buf[1024];
1745+ int got_wibble, got_wobble, got_wiggle;
1746
1747 TEST_FUNCTION ("stanza_stop");
1748
1749@@ -2574,9 +2497,7 @@
1750 TEST_EQ_STR (oper->name, "wibble");
1751 TEST_EQ_P (oper->env, NULL);
1752
1753- TEST_EQ_P (oper->node.parent, NULL);
1754- TEST_EQ_P (oper->node.left, NULL);
1755- TEST_EQ_P (oper->node.right, NULL);
1756+ TEST_LIST_EMPTY (&oper->children);
1757
1758 nih_free (job);
1759 }
1760@@ -2624,9 +2545,7 @@
1761 TEST_EQ_STR (oper->env[2], "b?z*");
1762 TEST_EQ_P (oper->env[3], NULL);
1763
1764- TEST_EQ_P (oper->node.parent, NULL);
1765- TEST_EQ_P (oper->node.left, NULL);
1766- TEST_EQ_P (oper->node.right, NULL);
1767+ TEST_LIST_EMPTY (&oper->children);
1768
1769 nih_free (job);
1770 }
1771@@ -2678,9 +2597,7 @@
1772 TEST_EQ_STR (oper->env[4], "BILBO=foo bar");
1773 TEST_EQ_P (oper->env[5], NULL);
1774
1775- TEST_EQ_P (oper->node.parent, NULL);
1776- TEST_EQ_P (oper->node.left, NULL);
1777- TEST_EQ_P (oper->node.right, NULL);
1778+ TEST_LIST_EMPTY (&oper->children);
1779
1780 nih_free (job);
1781 }
1782@@ -2718,31 +2635,26 @@
1783 TEST_ALLOC_PARENT (job->stop_on, job);
1784
1785 oper = job->stop_on;
1786- TEST_EQ (oper->type, EVENT_OR);
1787-
1788- TEST_EQ_P (oper->node.parent, NULL);
1789- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1790- TEST_ALLOC_PARENT (oper->node.left, oper);
1791- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1792- TEST_ALLOC_PARENT (oper->node.right, oper);
1793-
1794- oper = (EventOperator *)job->stop_on->node.left;
1795- TEST_EQ (oper->type, EVENT_MATCH);
1796- TEST_EQ_STR (oper->name, "wibble");
1797- TEST_EQ_P (oper->env, NULL);
1798-
1799- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1800- TEST_EQ_P (oper->node.left, NULL);
1801- TEST_EQ_P (oper->node.right, NULL);
1802-
1803- oper = (EventOperator *)job->stop_on->node.right;
1804- TEST_EQ (oper->type, EVENT_MATCH);
1805- TEST_EQ_STR (oper->name, "wobble");
1806- TEST_EQ_P (oper->env, NULL);
1807-
1808- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1809- TEST_EQ_P (oper->node.left, NULL);
1810- TEST_EQ_P (oper->node.right, NULL);
1811+ TEST_EQ (oper->type, EVENT_ANY);
1812+
1813+ got_wibble = FALSE;
1814+ got_wobble = FALSE;
1815+ NIH_LIST_FOREACH (&oper->children, iter) {
1816+ EventOperator *child = (EventOperator *)iter;
1817+
1818+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1819+
1820+ TEST_LIST_EMPTY (&child->children);
1821+ TEST_EQ (child->type, EVENT_MATCH);
1822+ TEST_EQ_P (child->env, NULL);
1823+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
1824+ got_wibble = TRUE;
1825+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
1826+ got_wobble = TRUE;
1827+ } else {
1828+ TEST_FAILED ("Unexpected child");
1829+ }
1830+ }
1831
1832 nih_free (job);
1833 }
1834@@ -2781,39 +2693,32 @@
1835 TEST_ALLOC_PARENT (job->stop_on, job);
1836
1837 oper = job->stop_on;
1838- TEST_EQ (oper->type, EVENT_AND);
1839-
1840- TEST_EQ_P (oper->node.parent, NULL);
1841- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1842- TEST_ALLOC_PARENT (oper->node.left, oper);
1843- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1844- TEST_ALLOC_PARENT (oper->node.right, oper);
1845-
1846- oper = (EventOperator *)job->stop_on->node.left;
1847- TEST_EQ (oper->type, EVENT_MATCH);
1848- TEST_EQ_STR (oper->name, "wibble");
1849-
1850- TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
1851- TEST_EQ_STR (oper->env[0], "foo");
1852- TEST_EQ_STR (oper->env[1], "bar");
1853- TEST_EQ_P (oper->env[2], NULL);
1854-
1855- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1856- TEST_EQ_P (oper->node.left, NULL);
1857- TEST_EQ_P (oper->node.right, NULL);
1858-
1859- oper = (EventOperator *)job->stop_on->node.right;
1860- TEST_EQ (oper->type, EVENT_MATCH);
1861- TEST_EQ_STR (oper->name, "wobble");
1862-
1863- TEST_ALLOC_SIZE (oper->env, sizeof (char *) * 3);
1864- TEST_EQ_STR (oper->env[0], "frodo");
1865- TEST_EQ_STR (oper->env[1], "bilbo");
1866- TEST_EQ_P (oper->env[2], NULL);
1867-
1868- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1869- TEST_EQ_P (oper->node.left, NULL);
1870- TEST_EQ_P (oper->node.right, NULL);
1871+ TEST_EQ (oper->type, EVENT_ALL);
1872+
1873+ got_wibble = FALSE;
1874+ got_wobble = FALSE;
1875+ NIH_LIST_FOREACH (&oper->children, iter) {
1876+ EventOperator *child = (EventOperator *)iter;
1877+
1878+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1879+
1880+ TEST_LIST_EMPTY (&child->children);
1881+ TEST_EQ (child->type, EVENT_MATCH);
1882+ TEST_ALLOC_SIZE (child->env, sizeof (char *) * 3);
1883+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
1884+ got_wibble = TRUE;
1885+ TEST_EQ_STR (child->env[0], "foo");
1886+ TEST_EQ_STR (child->env[1], "bar");
1887+ TEST_EQ_P (child->env[2], NULL);
1888+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
1889+ got_wobble = TRUE;
1890+ TEST_EQ_STR (child->env[0], "frodo");
1891+ TEST_EQ_STR (child->env[1], "bilbo");
1892+ TEST_EQ_P (child->env[2], NULL);
1893+ } else {
1894+ TEST_FAILED ("Unexpected child");
1895+ }
1896+ }
1897
1898 nih_free (job);
1899 }
1900@@ -2851,48 +2756,29 @@
1901 TEST_ALLOC_PARENT (job->stop_on, job);
1902
1903 oper = job->stop_on;
1904- TEST_EQ (oper->type, EVENT_OR);
1905-
1906- TEST_EQ_P (oper->node.parent, NULL);
1907- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1908- TEST_ALLOC_PARENT (oper->node.left, oper);
1909- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1910- TEST_ALLOC_PARENT (oper->node.right, oper);
1911-
1912- oper = (EventOperator *)job->stop_on->node.left;
1913- TEST_EQ (oper->type, EVENT_OR);
1914- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1915- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1916- TEST_ALLOC_PARENT (oper->node.left, oper);
1917- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1918- TEST_ALLOC_PARENT (oper->node.right, oper);
1919-
1920- oper = (EventOperator *)job->stop_on->node.left->left;
1921- TEST_EQ (oper->type, EVENT_MATCH);
1922- TEST_EQ_STR (oper->name, "wibble");
1923- TEST_EQ_P (oper->env, NULL);
1924-
1925- TEST_EQ_P (oper->node.parent, job->stop_on->node.left);
1926- TEST_EQ_P (oper->node.left, NULL);
1927- TEST_EQ_P (oper->node.right, NULL);
1928-
1929- oper = (EventOperator *)job->stop_on->node.left->right;
1930- TEST_EQ (oper->type, EVENT_MATCH);
1931- TEST_EQ_STR (oper->name, "wobble");
1932- TEST_EQ_P (oper->env, NULL);
1933-
1934- TEST_EQ_P (oper->node.parent, job->stop_on->node.left);
1935- TEST_EQ_P (oper->node.left, NULL);
1936- TEST_EQ_P (oper->node.right, NULL);
1937-
1938- oper = (EventOperator *)job->stop_on->node.right;
1939- TEST_EQ (oper->type, EVENT_MATCH);
1940- TEST_EQ_STR (oper->name, "wiggle");
1941- TEST_EQ_P (oper->env, NULL);
1942-
1943- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1944- TEST_EQ_P (oper->node.left, NULL);
1945- TEST_EQ_P (oper->node.right, NULL);
1946+ TEST_EQ (oper->type, EVENT_ANY);
1947+
1948+ got_wibble = FALSE;
1949+ got_wobble = FALSE;
1950+ got_wiggle = FALSE;
1951+ NIH_LIST_FOREACH (&oper->children, iter) {
1952+ EventOperator *child = (EventOperator *)iter;
1953+
1954+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
1955+
1956+ TEST_LIST_EMPTY (&child->children);
1957+ TEST_EQ (child->type, EVENT_MATCH);
1958+ TEST_EQ_P (child->env, NULL);
1959+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
1960+ got_wibble = TRUE;
1961+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
1962+ got_wobble = TRUE;
1963+ } else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
1964+ got_wiggle = TRUE;
1965+ } else {
1966+ TEST_FAILED ("Unexpected child");
1967+ }
1968+ }
1969
1970 nih_free (job);
1971 }
1972@@ -2929,49 +2815,29 @@
1973 TEST_ALLOC_PARENT (job->stop_on, job);
1974
1975 oper = job->stop_on;
1976- TEST_EQ (oper->type, EVENT_OR);
1977-
1978- TEST_EQ_P (oper->node.parent, NULL);
1979- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1980- TEST_ALLOC_PARENT (oper->node.left, oper);
1981- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
1982- TEST_ALLOC_PARENT (oper->node.right, oper);
1983-
1984- oper = (EventOperator *)job->stop_on->node.left;
1985- TEST_EQ (oper->type, EVENT_MATCH);
1986- TEST_EQ_STR (oper->name, "wibble");
1987- TEST_EQ_P (oper->env, NULL);
1988-
1989- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1990- TEST_EQ_P (oper->node.left, NULL);
1991- TEST_EQ_P (oper->node.right, NULL);
1992-
1993- oper = (EventOperator *)job->stop_on->node.right;
1994- TEST_EQ (oper->type, EVENT_OR);
1995-
1996- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
1997- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
1998- TEST_ALLOC_PARENT (oper->node.left, oper);
1999- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
2000- TEST_ALLOC_PARENT (oper->node.right, oper);
2001-
2002- oper = (EventOperator *)job->stop_on->node.right->left;
2003- TEST_EQ (oper->type, EVENT_MATCH);
2004- TEST_EQ_STR (oper->name, "wobble");
2005- TEST_EQ_P (oper->env, NULL);
2006-
2007- TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
2008- TEST_EQ_P (oper->node.left, NULL);
2009- TEST_EQ_P (oper->node.right, NULL);
2010-
2011- oper = (EventOperator *)job->stop_on->node.right->right;
2012- TEST_EQ (oper->type, EVENT_MATCH);
2013- TEST_EQ_STR (oper->name, "wiggle");
2014- TEST_EQ_P (oper->env, NULL);
2015-
2016- TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
2017- TEST_EQ_P (oper->node.left, NULL);
2018- TEST_EQ_P (oper->node.right, NULL);
2019+ TEST_EQ (oper->type, EVENT_ANY);
2020+
2021+ got_wibble = FALSE;
2022+ got_wobble = FALSE;
2023+ got_wiggle = FALSE;
2024+ NIH_LIST_FOREACH (&oper->children, iter) {
2025+ EventOperator *child = (EventOperator *)iter;
2026+
2027+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
2028+
2029+ TEST_LIST_EMPTY (&child->children);
2030+ TEST_EQ (child->type, EVENT_MATCH);
2031+ TEST_EQ_P (child->env, NULL);
2032+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
2033+ got_wibble = TRUE;
2034+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
2035+ got_wobble = TRUE;
2036+ } else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
2037+ got_wiggle = TRUE;
2038+ } else {
2039+ TEST_FAILED ("Unexpected child");
2040+ }
2041+ }
2042
2043 nih_free (job);
2044 }
2045@@ -3009,49 +2875,29 @@
2046 TEST_ALLOC_PARENT (job->stop_on, job);
2047
2048 oper = job->stop_on;
2049- TEST_EQ (oper->type, EVENT_OR);
2050-
2051- TEST_EQ_P (oper->node.parent, NULL);
2052- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
2053- TEST_ALLOC_PARENT (oper->node.left, oper);
2054- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
2055- TEST_ALLOC_PARENT (oper->node.right, oper);
2056-
2057- oper = (EventOperator *)job->stop_on->node.left;
2058- TEST_EQ (oper->type, EVENT_MATCH);
2059- TEST_EQ_STR (oper->name, "wibble");
2060- TEST_EQ_P (oper->env, NULL);
2061-
2062- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
2063- TEST_EQ_P (oper->node.left, NULL);
2064- TEST_EQ_P (oper->node.right, NULL);
2065-
2066- oper = (EventOperator *)job->stop_on->node.right;
2067- TEST_EQ (oper->type, EVENT_OR);
2068-
2069- TEST_EQ_P (oper->node.parent, &job->stop_on->node);
2070- TEST_ALLOC_SIZE (oper->node.left, sizeof (EventOperator));
2071- TEST_ALLOC_PARENT (oper->node.left, oper);
2072- TEST_ALLOC_SIZE (oper->node.right, sizeof (EventOperator));
2073- TEST_ALLOC_PARENT (oper->node.right, oper);
2074-
2075- oper = (EventOperator *)job->stop_on->node.right->left;
2076- TEST_EQ (oper->type, EVENT_MATCH);
2077- TEST_EQ_STR (oper->name, "wobble");
2078- TEST_EQ_P (oper->env, NULL);
2079-
2080- TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
2081- TEST_EQ_P (oper->node.left, NULL);
2082- TEST_EQ_P (oper->node.right, NULL);
2083-
2084- oper = (EventOperator *)job->stop_on->node.right->right;
2085- TEST_EQ (oper->type, EVENT_MATCH);
2086- TEST_EQ_STR (oper->name, "wiggle");
2087- TEST_EQ_P (oper->env, NULL);
2088-
2089- TEST_EQ_P (oper->node.parent, job->stop_on->node.right);
2090- TEST_EQ_P (oper->node.left, NULL);
2091- TEST_EQ_P (oper->node.right, NULL);
2092+ TEST_EQ (oper->type, EVENT_ANY);
2093+
2094+ got_wibble = FALSE;
2095+ got_wobble = FALSE;
2096+ got_wiggle = FALSE;
2097+ NIH_LIST_FOREACH (&oper->children, iter) {
2098+ EventOperator *child = (EventOperator *)iter;
2099+
2100+ TEST_ALLOC_SIZE (child, sizeof (EventOperator));
2101+
2102+ TEST_LIST_EMPTY (&child->children);
2103+ TEST_EQ (child->type, EVENT_MATCH);
2104+ TEST_EQ_P (child->env, NULL);
2105+ if (!strncmp ("wibble", child->name, 7) && ! got_wibble) {
2106+ got_wibble = TRUE;
2107+ } else if (!strncmp ("wobble", child->name, 7) && ! got_wobble) {
2108+ got_wobble = TRUE;
2109+ } else if (!strncmp ("wiggle", child->name, 7) && ! got_wiggle) {
2110+ got_wiggle = TRUE;
2111+ } else {
2112+ TEST_FAILED ("Unexpected child");
2113+ }
2114+ }
2115
2116 nih_free (job);
2117 }
2118@@ -3092,9 +2938,7 @@
2119 TEST_EQ_STR (oper->name, "waggle");
2120 TEST_EQ_P (oper->env, NULL);
2121
2122- TEST_EQ_P (oper->node.parent, NULL);
2123- TEST_EQ_P (oper->node.left, NULL);
2124- TEST_EQ_P (oper->node.right, NULL);
2125+ TEST_LIST_EMPTY (&oper->children);
2126
2127 nih_free (job);
2128 }

Subscribers

People subscribed via source and target branches