We test notifications by defining a "tree" of expected responses (this is needed because the system is multithreaded and only some ordering is guaranteed serial; other actions happen in parallel) Each node can test for a notification and then has a set of parallel nodes, which describe which notifications happen next in any order. Finally, after all parallel nodes are matched, a node has a set of serial nodes, which are matched in order.
Note that nested nodes may themselves have structure and that empty nodes are available, which can help group dependencies.
More exactly, we specify a tree and a traversal - the traversal is hardcoded below, and implicit in the instructions above.