This patch adds more testcases around variables used in dbus rules.
In particular, it

  - attempts to verify that variable expansion and alternation
    expansion results in identical DFA blobs,
  - tests that variables can be expanded within alternations,
  - tests that alternations can occur in variable definitions, and
  - that having alternations inside variable declarations that are
    used inside alternations results in parsing success

Note that vars/vars_dbus_9.sd veers into stress test land, as the
combinatoric expansion results in over 1000 dbus rule entries being
generated, which means that DFA reduction on all the fields takes
noticeable amounts of time (around 1s on my i5 ivy-core laptop).

Patch history:
  v1: initial version
  v2: based on feedback:
      - add more alternation tests for cases where only part of the
        alternation is defined within a variable
      - mark test with nested alternations as being successful now that
	the patch that implements it was accepted

Signed-off-by: Steve Beattie <steve@nxnw.org>

---
 parser/tst/equality.sh                             |    9 ++++++++-
 parser/tst/simple_tests/vars/vars_alternation_3.sd |    8 ++++++++
 parser/tst/simple_tests/vars/vars_alternation_4.sd |    8 ++++++++
 parser/tst/simple_tests/vars/vars_alternation_5.sd |    8 ++++++++
 parser/tst/simple_tests/vars/vars_dbus_10.sd       |   14 ++++++++++++++
 parser/tst/simple_tests/vars/vars_dbus_11.sd       |   14 ++++++++++++++
 parser/tst/simple_tests/vars/vars_dbus_8.sd        |   13 +++++++++++++
 parser/tst/simple_tests/vars/vars_dbus_9.sd        |   18 ++++++++++++++++++
 tests/regression/apparmor/dbus_message.sh          |   19 +++++++++++++++++++
 9 files changed, 110 insertions(+), 1 deletion(-)

Index: b/parser/tst/equality.sh
===================================================================
--- a/parser/tst/equality.sh
+++ b/parser/tst/equality.sh
@@ -162,12 +162,19 @@ verify_binary_equality "dbus variable ex
 
 verify_binary_equality "dbus variable expansion, multiple values/rules" \
 	"/t { dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
+	"/t { dbus (send, receive) path=/com/{foo,bar}, }" \
+	"/t { dbus (send, receive) path={/com/foo,/com/bar}, }" \
 	"@{FOO}=foo
 	    /t { dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/bar, }" \
 	"@{FOO}=foo bar
 	    /t { dbus (send, receive) path=/com/@{FOO}, }" \
 	"@{FOO}=bar foo
-	    /t { dbus (send, receive) path=/com/@{FOO}, }"
+	    /t { dbus (send, receive) path=/com/@{FOO}, }" \
+	"@{FOO}={bar,foo}
+	    /t { dbus (send, receive) path=/com/@{FOO}, }" \
+	"@{FOO}=foo
+	 @{BAR}=bar
+	    /t { dbus (send, receive) path=/com/{@{FOO},@{BAR}}, }" \
 
 verify_binary_equality "dbus variable expansion, ensure rule de-duping occurs" \
 	"/t { dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
Index: b/parser/tst/simple_tests/vars/vars_dbus_8.sd
===================================================================
--- /dev/null
+++ b/parser/tst/simple_tests/vars/vars_dbus_8.sd
@@ -0,0 +1,13 @@
+#=DESCRIPTION reference variables in dbus rules, embedded within alternation
+#=EXRESULT PASS
+
+@{TLDS}=com org
+@{DOMAINS}=gnome freedesktop
+
+/does/not/exist {
+   dbus (send, receive)
+       bus=session
+       path={/@{TLDS}/foo,/com/@{DOMAINS}}
+       interface=@{TLDS}.freedesktop
+       peer=(name=@{TLDS}.freedesktop label=/@{TLDS}/freedesktop),
+}
Index: b/tests/regression/apparmor/dbus_message.sh
===================================================================
--- a/tests/regression/apparmor/dbus_message.sh
+++ b/tests/regression/apparmor/dbus_message.sh
@@ -130,6 +130,25 @@ message_gendbusprofile "dbus send bus=se
 runtestfg "message (send allowed w/ bus, dest, path, interface, method)" pass $confined_args
 checktestfg "compare_logs $unconfined_log eq $confined_log"
 
+# extra test to look for multi-field replacements
+set_dbus_var "@{TLDS}=Hello ListNames org"
+message_gendbusprofile "dbus send bus=session path=/@{TLDS}/freedesktop/DBus interface=@{TLDS}.freedesktop.DBus member=@{TLDS} peer=(name=@{TLDS}.freedesktop.DBus),"
+runtestfg "message (send allowed w/ bus, dest, path, interface, method)" pass $confined_args
+checktestfg "compare_logs $unconfined_log eq $confined_log"
+
+# extra test to look for multi-field replacements, w/embedded alternations
+set_dbus_var "@{TLDS}={Hello,ListNames} org"
+message_gendbusprofile "dbus send bus=session path=/@{TLDS}/freedesktop/DBus interface=@{TLDS}.freedesktop.DBus member=@{TLDS} peer=(name=@{TLDS}.freedesktop.DBus),"
+runtestfg "message (send allowed w/ bus, dest, path, interface, method)" pass $confined_args
+checktestfg "compare_logs $unconfined_log eq $confined_log"
+
+# extra test to look for multi-field replacements w/alternations
+# surrounding vars
+set_dbus_var "@{TLDS}=Hello org"
+message_gendbusprofile "dbus send bus=session path=/@{TLDS}/freedesktop/DBus interface=@{TLDS}.freedesktop.DBus member={ListNames,@{TLDS}} peer=(name=@{TLDS}.freedesktop.DBus),"
+runtestfg "message (send allowed w/ bus, dest, path, interface, method)" pass $confined_args
+checktestfg "compare_logs $unconfined_log eq $confined_log"
+
 # Make sure send is denied when confined with appropriate permissions along
 # with incorrect conditionals
 
Index: b/parser/tst/simple_tests/vars/vars_dbus_9.sd
===================================================================
--- /dev/null
+++ b/parser/tst/simple_tests/vars/vars_dbus_9.sd
@@ -0,0 +1,18 @@
+#=DESCRIPTION reference variables in dbus rules, multiple expansions
+#=EXRESULT PASS
+
+@{BUSES}=session system
+@{TLDS}=com org
+@{DOMAINS}=gnome freedesktop
+@{FOO}=bar baz
+@{BAR}=@{FOO}/blort
+@{MEMBERS}=Get Set
+
+/does/not/exist {
+   dbus (send, receive)
+       bus=@{BUSES}
+       path=/@{TLDS}/foo
+       member=@{MEMBERS}.bar
+       interface=@{TLDS}.@{DOMAINS}
+       peer=(name=@{TLDS}.@{DOMAINS} label=/@{TLDS}/@{DOMAINS}),
+}
Index: b/parser/tst/simple_tests/vars/vars_dbus_10.sd
===================================================================
--- /dev/null
+++ b/parser/tst/simple_tests/vars/vars_dbus_10.sd
@@ -0,0 +1,14 @@
+#=DESCRIPTION reference variables in dbus rules, var containing alternation
+#=EXRESULT PASS
+
+@{BUSES}=session system
+@{TLDS}=com org
+@{MEMBERS}={Get,Set}
+
+/does/not/exist {
+   dbus (send, receive)
+       bus=@{BUSES}
+       path=/@{TLDS}/foo
+       member=@{MEMBERS}.bar,
+
+}
Index: b/parser/tst/simple_tests/vars/vars_dbus_11.sd
===================================================================
--- /dev/null
+++ b/parser/tst/simple_tests/vars/vars_dbus_11.sd
@@ -0,0 +1,14 @@
+#=DESCRIPTION reference variables in dbus rules, nested embedded alternations
+#=EXRESULT PASS
+
+@{BUSES}=session system
+@{TLDS}=com org
+@{MEMBERS}={Get,Set}
+
+/does/not/exist {
+   dbus (send, receive)
+       bus=@{BUSES}
+       path=/@{TLDS}/foo
+       member={@{MEMBERS}.bar,List.baz},
+
+}
Index: b/parser/tst/simple_tests/vars/vars_alternation_3.sd
===================================================================
--- /dev/null
+++ b/parser/tst/simple_tests/vars/vars_alternation_3.sd
@@ -0,0 +1,8 @@
+#=DESCRIPTION variable w/part of an alternation included
+#=EXRESULT PASS
+
+@{BAR}={bar,baz,blort
+
+/does/not/exist {
+  /does/not/@{BAR},exist,notexist} r,
+}
Index: b/parser/tst/simple_tests/vars/vars_alternation_4.sd
===================================================================
--- /dev/null
+++ b/parser/tst/simple_tests/vars/vars_alternation_4.sd
@@ -0,0 +1,8 @@
+#=DESCRIPTION variable w/part of an alternation included
+#=EXRESULT PASS
+
+@{BAR}=bar,baz,blort}
+
+/does/not/exist {
+  /does/not/{exist,notexist@{BAR}/meep r,
+}
Index: b/parser/tst/simple_tests/vars/vars_alternation_5.sd
===================================================================
--- /dev/null
+++ b/parser/tst/simple_tests/vars/vars_alternation_5.sd
@@ -0,0 +1,8 @@
+#=DESCRIPTION variable w/part of an alternation included
+#=EXRESULT PASS
+
+@{BAR}=bar,baz,blort
+
+/does/not/exist {
+  /does/not/{exist@{BAR}notexist}/meep r,
+}


