Merge "Roll-forward the VNDK snapshot list of GSI"
diff --git a/core/Makefile b/core/Makefile
index 37d09f5..a580ac8 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1597,6 +1597,7 @@
     $(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE) \
   ,erofs),)
 INTERNAL_USERIMAGES_DEPS += $(MKEROFSUSERIMG)
+BOARD_EROFS_COMPRESSOR ?= "lz4hc,9"
 endif
 
 ifneq ($(filter \
@@ -2795,7 +2796,7 @@
 $(BUILT_SYSTEMIMAGE): $(BOARD_AVB_SYSTEM_KEY_PATH)
 endif
 ifeq ($(PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA),true)
-$(BUILT_SYSTEMIMAGE): $(HOST_OUT_EXECUTABLES)/fsverity $(HOST_OUT_EXECUTABLES)/aapt2 \
+$(BUILT_SYSTEMIMAGE): $(HOST_OUT_EXECUTABLES)/fsverity $(HOST_OUT_EXECUTABLES)/aapt2 $(HOST_OUT_EXECUTABLES)/apksigner \
     $(FSVERITY_APK_MANIFEST_PATH) $(FSVERITY_APK_KEY_PATH).x509.pem $(FSVERITY_APK_KEY_PATH).pk8
 endif
 $(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
diff --git a/core/combo/HOST_CROSS_linux_bionic-arm64.mk b/core/combo/HOST_CROSS_linux_bionic-arm64.mk
deleted file mode 100644
index df6865f..0000000
--- a/core/combo/HOST_CROSS_linux_bionic-arm64.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Configuration for builds hosted on linux_arm-arm64
-# Included by combo/select.mk
-
-define $(combo_var_prefix)transform-shared-lib-to-toc
-$(call _gen_toc_command_for_elf,$(1),$(2))
-endef
diff --git a/core/combo/HOST_CROSS_windows-x86.mk b/core/combo/HOST_CROSS_windows-x86.mk
deleted file mode 100644
index d924901..0000000
--- a/core/combo/HOST_CROSS_windows-x86.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Copyright (C) 2006 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Settings to use MinGW as a cross-compiler under Linux
-# Included by combo/select.make
-
-define $(combo_var_prefix)transform-shared-lib-to-toc
-$(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OBJDUMP) -x $(1) | grep "^Name" | cut -f3 -d" " > $(2)
-$(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)NM) -g -f p $(1) | cut -f1-2 -d" " >> $(2)
-endef
diff --git a/core/combo/HOST_CROSS_windows-x86_64.mk b/core/combo/HOST_CROSS_windows-x86_64.mk
deleted file mode 100644
index d924901..0000000
--- a/core/combo/HOST_CROSS_windows-x86_64.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Copyright (C) 2006 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Settings to use MinGW as a cross-compiler under Linux
-# Included by combo/select.make
-
-define $(combo_var_prefix)transform-shared-lib-to-toc
-$(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OBJDUMP) -x $(1) | grep "^Name" | cut -f3 -d" " > $(2)
-$(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)NM) -g -f p $(1) | cut -f1-2 -d" " >> $(2)
-endef
diff --git a/core/combo/select.mk b/core/combo/select.mk
index 33c8e6d..7617558 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -27,6 +27,13 @@
 combo_var_prefix := $(combo_2nd_arch_prefix)$(combo_target)
 
 # Set reasonable defaults for the various variables
+ifeq ($(combo_target),HOST_CROSS_)
+$(KATI_obsolete_var \
+  $(combo_var_prefix)GLOBAL_ARFLAGS \
+  $(combo_var_prefix)STATIC_LIB_SUFFIX \
+  $(combo_var_prefix)transform-shared-lib-to-toc \
+  ,HOST_CROSS builds are not supported in Make)
+else
 
 $(combo_var_prefix)GLOBAL_ARFLAGS := crsPD -format=gnu
 
@@ -34,3 +41,5 @@
 
 # Now include the combo for this specific target.
 include $(BUILD_COMBOS)/$(combo_target)$(combo_os_arch).mk
+
+endif
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 46f7f24..a0ff119 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -299,9 +299,6 @@
   my_sanitize := $(filter-out cfi,$(my_sanitize))
   my_cflags += -fno-lto
   my_ldflags += -fno-lto
-
-  # TODO(b/133876586): Disable experimental pass manager for fuzzer builds.
-  my_cflags += -fno-experimental-new-pass-manager
 endif
 
 ifneq ($(filter integer_overflow,$(my_sanitize)),)
diff --git a/core/definitions.mk b/core/definitions.mk
index 38b572b..c981152 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -580,9 +580,17 @@
 ## License metadata build rule for my_register_name $(1)
 ###########################################################
 define license-metadata-rule
-$(strip $(eval _dir := $(call license-metadata-dir)))
+$(foreach meta_lic, $(ALL_MODULES.$(1).DELAYED_META_LIC),$(call _license-metadata-rule,$(1),$(meta_lic)))
+$(call notice-rule,$(1))
+endef
+
+define _license-metadata-rule
 $(strip $(eval _srcs := $(strip $(foreach d,$(ALL_MODULES.$(1).NOTICE_DEPS),$(if $(strip $(ALL_MODULES.$(call word-colon,1,$(d)).INSTALLED)), $(ALL_MODULES.$(call word-colon,1,$(d)).INSTALLED),$(if $(strip $(ALL_MODULES.$(call word-colon,1,$(d)).BUILT)), $(ALL_MODULES.$(call word-colon,1,$(d)).BUILT), $(call word-colon,1,$d)))))))
-$(strip $(eval _deps := $(sort $(filter-out $(_dir)/$(1).meta_lic%,$(foreach d,$(ALL_MODULES.$(1).NOTICE_DEPS), $(_dir)/$(call word-colon,1,$(d)).meta_lic:$(call wordlist-colon,2,9999,$d))))))
+$(strip $(eval _deps := $(sort $(filter-out $(2)%,\
+   $(foreach d,$(ALL_MODULES.$(1).NOTICE_DEPS),\
+     $(addsuffix :$(call wordlist-colon,2,9999,$(d)), \
+       $(foreach dt,$(ALL_MODULES.$(d).BUILT) $(ALL_MODULES.$(d).INSTALLED),\
+         $(ALL_TARGETS.$(dt).META_LIC))))))))
 $(strip $(eval _notices := $(sort $(ALL_MODULES.$(1).NOTICES))))
 $(strip $(eval _tgts := $(sort $(ALL_MODULES.$(1).BUILT))))
 $(strip $(eval _inst := $(sort $(ALL_MODULES.$(1).INSTALLED))))
@@ -594,22 +602,22 @@
   $(foreach ns,$(_ns),$(ns):$(_d) ) \
 ))))
 
-$(_dir)/$(1).meta_lic: PRIVATE_KINDS := $(sort $(ALL_MODULES.$(1).LICENSE_KINDS))
-$(_dir)/$(1).meta_lic: PRIVATE_CONDITIONS := $(sort $(ALL_MODULES.$(1).LICENSE_CONDITIONS))
-$(_dir)/$(1).meta_lic: PRIVATE_NOTICES := $(_notices)
-$(_dir)/$(1).meta_lic: PRIVATE_NOTICE_DEPS := $(_deps)
-$(_dir)/$(1).meta_lic: PRIVATE_SOURCES := $(_srcs)
-$(_dir)/$(1).meta_lic: PRIVATE_TARGETS := $(_tgts)
-$(_dir)/$(1).meta_lic: PRIVATE_INSTALLED := $(_inst)
-$(_dir)/$(1).meta_lic: PRIVATE_PATH := $(_path)
-$(_dir)/$(1).meta_lic: PRIVATE_IS_CONTAINER := $(ALL_MODULES.$(1).IS_CONTAINER)
-$(_dir)/$(1).meta_lic: PRIVATE_PACKAGE_NAME := $(strip $(ALL_MODULES.$(1).LICENSE_PACKAGE_NAME))
-$(_dir)/$(1).meta_lic: PRIVATE_INSTALL_MAP := $(_map)
-$(_dir)/$(1).meta_lic: PRIVATE_MODULE_TYPE := $(ALL_MODULES.$(1).MODULE_TYPE)
-$(_dir)/$(1).meta_lic: PRIVATE_MODULE_CLASS := $(ALL_MODULES.$(1).MODULE_CLASS)
-$(_dir)/$(1).meta_lic: PRIVATE_INSTALL_MAP := $(_map)
-$(_dir)/$(1).meta_lic: $(BUILD_LICENSE_METADATA)
-$(_dir)/$(1).meta_lic : $(foreach d,$(_deps),$(call word-colon,1,$(d))) $(foreach n,$(_notices),$(call word-colon,1,$(n)) )
+$(2): PRIVATE_KINDS := $(sort $(ALL_MODULES.$(1).LICENSE_KINDS))
+$(2): PRIVATE_CONDITIONS := $(sort $(ALL_MODULES.$(1).LICENSE_CONDITIONS))
+$(2): PRIVATE_NOTICES := $(_notices)
+$(2): PRIVATE_NOTICE_DEPS := $(_deps)
+$(2): PRIVATE_SOURCES := $(_srcs)
+$(2): PRIVATE_TARGETS := $(_tgts)
+$(2): PRIVATE_INSTALLED := $(_inst)
+$(2): PRIVATE_PATH := $(_path)
+$(2): PRIVATE_IS_CONTAINER := $(ALL_MODULES.$(1).IS_CONTAINER)
+$(2): PRIVATE_PACKAGE_NAME := $(strip $(ALL_MODULES.$(1).LICENSE_PACKAGE_NAME))
+$(2): PRIVATE_INSTALL_MAP := $(_map)
+$(2): PRIVATE_MODULE_TYPE := $(ALL_MODULES.$(1).MODULE_TYPE)
+$(2): PRIVATE_MODULE_CLASS := $(ALL_MODULES.$(1).MODULE_CLASS)
+$(2): PRIVATE_INSTALL_MAP := $(_map)
+$(2): $(BUILD_LICENSE_METADATA)
+$(2) : $(foreach d,$(_deps),$(call word-colon,1,$(d))) $(foreach n,$(_notices),$(call word-colon,1,$(n)) )
 	rm -f $$@
 	mkdir -p $$(dir $$@)
 	$(BUILD_LICENSE_METADATA) \
@@ -627,7 +635,9 @@
 	  -p '$$(PRIVATE_PACKAGE_NAME)' \
 	  $$(addprefix -r ,$$(PRIVATE_PATH)) \
 	  -o $$@
+endef
 
+define notice-rule
 $(strip $(eval _mifs := $(sort $(ALL_MODULES.$(1).MODULE_INSTALLED_FILENAMES))))
 $(strip $(eval _infs := $(sort $(ALL_MODULES.$(1).INSTALLED_NOTICE_FILE))))
 
@@ -636,7 +646,6 @@
 $(if $(strip $(filter $(1),$(INSTALLED_NOTICE_FILES.$(inf).MODULE))),
 $(strip $(eval _mif := $(firstword $(foreach m,$(_mifs),$(if $(filter %/src/$(m).txt,$(inf)),$(m))))))
 
-$(inf) : $(_dir)/$(1).meta_lic
 $(inf): PRIVATE_INSTALLED_MODULE := $(_mif)
 $(inf) : PRIVATE_NOTICES := $(sort $(foreach n,$(_notices),$(call word-colon,1,$(n) )))
 
@@ -831,14 +840,9 @@
   $(foreach t,$(sort $(ALL_NON_MODULES)), \
     $(eval ALL_TARGETS.$(t).META_LIC := $(_dir)/$(t).meta_lic) \
   ) \
-  $(foreach m,$(sort $(ALL_MODULES)), \
-    $(foreach d,$(sort $(ALL_MODULES.$(m).BUILT) $(ALL_MODULES.$(m).INSTALLED)), \
-      $(eval ALL_TARGETS.$(d).META_LIC := $(_dir)/$(m).meta_lic) \
-    ) \
-  ) \
-)$(foreach t,$(sort $(ALL_NON_MODULES)),$(eval $(call non-module-license-metadata-rule,$(t))))$(strip \
-)$(foreach m,$(sort $(ALL_MODULES)),$(eval $(call license-metadata-rule,$(m))))$(strip \
-)$(eval $(call report-missing-licenses-rule))
+  $(foreach t,$(sort $(ALL_NON_MODULES)),$(eval $(call non-module-license-metadata-rule,$(t)))) \
+  $(foreach m,$(sort $(ALL_MODULES)),$(eval $(call license-metadata-rule,$(m)))) \
+  $(eval $(call report-missing-licenses-rule)))
 endef
 
 ###########################################################
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 21eac7f..b673050 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -167,6 +167,10 @@
   else
     $(error Unsupported HOST_CROSS_OS $(HOST_CROSS_OS))
   endif
+else ifeq ($(HOST_OS),darwin)
+  HOST_CROSS_OS := darwin
+  HOST_CROSS_ARCH := arm64
+  HOST_CROSS_2ND_ARCH :=
 endif
 
 ifeq ($(HOST_OS),)
diff --git a/core/notice_files.mk b/core/notice_files.mk
index 36f2c8f..b3eedc0 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -125,16 +125,27 @@
 
 local_path := $(LOCAL_PATH)
 
+
+module_license_metadata :=
+
 ifdef my_register_name
-ALL_MODULES.$(my_register_name).LICENSE_PACKAGE_NAME := $(strip $(license_package_name))
-ALL_MODULES.$(my_register_name).MODULE_TYPE := $(strip $(ALL_MODULES.$(my_register_name).MODULE_TYPE) $(LOCAL_MODULE_TYPE))
-ALL_MODULES.$(my_register_name).MODULE_CLASS := $(strip $(ALL_MODULES.$(my_register_name).MODULE_CLASS) $(LOCAL_MODULE_CLASS))
-ALL_MODULES.$(my_register_name).LICENSE_KINDS := $(ALL_MODULES.$(my_register_name).LICENSE_KINDS) $(license_kinds)
-ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS := $(ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS) $(license_conditions)
-ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP := $(ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP) $(install_map)
-ALL_MODULES.$(my_register_name).NOTICE_DEPS := $(ALL_MODULES.$(my_register_name).NOTICE_DEPS) $(notice_deps)
-ALL_MODULES.$(my_register_name).IS_CONTAINER := $(strip $(filter-out false,$(ALL_MODULES.$(my_register_name).IS_CONTAINER) $(is_container)))
-ALL_MODULES.$(my_register_name).PATH := $(strip $(ALL_MODULES.$(my_register_name).PATH) $(local_path))
+  module_license_metadata := $(call local-intermediates-dir)/$(my_register_name).meta_lic
+
+  $(foreach target,$(ALL_MODULES.$(my_register_name).BUILT) $(ALL_MODULES.$(my_register_name).INSTALLED),\
+    $(eval ALL_TARGETS.$(target).META_LIC := $(module_license_metadata)))
+
+  ALL_MODULES.$(my_register_name).META_LIC := $(strip $(ALL_MODULES.$(my_register_name).META_LIC) $(module_license_metadata))
+
+  ALL_MODULES.$(my_register_name).DELAYED_META_LIC := $(strip $(ALL_MODULES.$(my_register_name).DELAYED_META_LIC) $(module_license_metadata))
+  ALL_MODULES.$(my_register_name).LICENSE_PACKAGE_NAME := $(strip $(license_package_name))
+  ALL_MODULES.$(my_register_name).MODULE_TYPE := $(strip $(ALL_MODULES.$(my_register_name).MODULE_TYPE) $(LOCAL_MODULE_TYPE))
+  ALL_MODULES.$(my_register_name).MODULE_CLASS := $(strip $(ALL_MODULES.$(my_register_name).MODULE_CLASS) $(LOCAL_MODULE_CLASS))
+  ALL_MODULES.$(my_register_name).LICENSE_KINDS := $(ALL_MODULES.$(my_register_name).LICENSE_KINDS) $(license_kinds)
+  ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS := $(ALL_MODULES.$(my_register_name).LICENSE_CONDITIONS) $(license_conditions)
+  ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP := $(ALL_MODULES.$(my_register_name).LICENSE_INSTALL_MAP) $(install_map)
+  ALL_MODULES.$(my_register_name).NOTICE_DEPS := $(ALL_MODULES.$(my_register_name).NOTICE_DEPS) $(notice_deps)
+  ALL_MODULES.$(my_register_name).IS_CONTAINER := $(strip $(filter-out false,$(ALL_MODULES.$(my_register_name).IS_CONTAINER) $(is_container)))
+  ALL_MODULES.$(my_register_name).PATH := $(strip $(ALL_MODULES.$(my_register_name).PATH) $(local_path))
 endif
 
 ifdef notice_file
@@ -196,6 +207,8 @@
 
 installed_notice_file := $($(my_prefix)OUT_NOTICE_FILES)/src/$(module_installed_filename).txt
 
+$(installed_notice_file): $(module_license_metadata)
+
 ifdef my_register_name
 ALL_MODULES.$(my_register_name).INSTALLED_NOTICE_FILE := $(ALL_MODULES.$(my_register_name).INSTALLED_NOTICE_FILE) $(installed_notice_file)
 ALL_MODULES.$(my_register_name).MODULE_INSTALLED_FILENAMES := $(ALL_MODULES.$(my_register_name).MODULE_INSTALLED_FILENAMES) $(module_installed_filename)
diff --git a/tools/compliance/Android.bp b/tools/compliance/Android.bp
index e56a471..afb3080 100644
--- a/tools/compliance/Android.bp
+++ b/tools/compliance/Android.bp
@@ -17,12 +17,41 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+blueprint_go_binary {
+    name: "checkshare",
+    srcs: ["cmd/checkshare.go"],
+    deps: ["compliance-module"],
+    testSrcs: ["cmd/checkshare_test.go"],
+}
+
+blueprint_go_binary {
+    name: "listshare",
+    srcs: ["cmd/listshare.go"],
+    deps: ["compliance-module"],
+    testSrcs: ["cmd/listshare_test.go"],
+}
+
+blueprint_go_binary {
+    name: "dumpgraph",
+    srcs: ["cmd/dumpgraph.go"],
+    deps: ["compliance-module"],
+    testSrcs: ["cmd/dumpgraph_test.go"],
+}
+
+blueprint_go_binary {
+    name: "dumpresolutions",
+    srcs: ["cmd/dumpresolutions.go"],
+    deps: ["compliance-module"],
+    testSrcs: ["cmd/dumpresolutions_test.go"],
+}
+
 bootstrap_go_package {
     name: "compliance-module",
     srcs: [
         "actionset.go",
         "condition.go",
         "conditionset.go",
+        "doc.go",
         "graph.go",
         "policy/policy.go",
         "policy/resolve.go",
diff --git a/tools/compliance/actionset.go b/tools/compliance/actionset.go
index d575321..656c5de 100644
--- a/tools/compliance/actionset.go
+++ b/tools/compliance/actionset.go
@@ -108,3 +108,12 @@
 	}
 	return true
 }
+
+// conditions returns the set of conditions resolved by the action set.
+func (as actionSet) conditions() *LicenseConditionSet {
+	result := newLicenseConditionSet()
+	for _, cs := range as {
+		result.AddSet(cs)
+	}
+	return result
+}
diff --git a/tools/compliance/cmd/checkshare.go b/tools/compliance/cmd/checkshare.go
new file mode 100644
index 0000000..efac8dc
--- /dev/null
+++ b/tools/compliance/cmd/checkshare.go
@@ -0,0 +1,114 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"compliance"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"sort"
+)
+
+func init() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, `Usage: %s file.meta_lic {file.meta_lic...}
+
+Reports on stderr any targets where policy says that the source both
+must and must not be shared. The error report indicates the target, the
+license condition with origin that has a source privacy policy, and the
+license condition with origin that has a source sharing policy.
+
+Any given target may appear multiple times with different combinations
+of conflicting license conditions.
+
+If all the source code that policy says must be shared may be shared,
+outputs "PASS" to stdout and exits with status 0.
+
+If policy says any source must both be shared and not be shared,
+outputs "FAIL" to stdout and exits with status 1.
+`, filepath.Base(os.Args[0]))
+	}
+}
+
+var (
+	failConflicts = fmt.Errorf("conflicts")
+	failNoneRequested = fmt.Errorf("\nNo metadata files requested")
+	failNoLicenses = fmt.Errorf("No licenses")
+)
+
+
+// byError orders conflicts by error string
+type byError []compliance.SourceSharePrivacyConflict
+
+func (l byError) Len() int           { return len(l) }
+func (l byError) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }
+func (l byError) Less(i, j int) bool { return l[i].Error() < l[j].Error() }
+
+func main() {
+	flag.Parse()
+
+	// Must specify at least one root target.
+	if flag.NArg() == 0 {
+		flag.Usage()
+		os.Exit(2)
+	}
+
+	err := checkShare(os.Stdout, os.Stderr, flag.Args()...)
+	if err != nil {
+		if err != failConflicts {
+			if err == failNoneRequested {
+				flag.Usage()
+			}
+			fmt.Fprintf(os.Stderr, "%s\n", err.Error())
+		}
+		os.Exit(1)
+	}
+	os.Exit(0)
+}
+
+// checkShare implements the checkshare utility.
+func checkShare(stdout, stderr io.Writer, files ...string) error {
+
+	if len(files) < 1 {
+		return failNoneRequested
+	}
+
+	// Read the license graph from the license metadata files (*.meta_lic).
+	licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+	if err != nil {
+		return fmt.Errorf("Unable to read license metadata file(s) %q: %w\n", files, err)
+	}
+	if licenseGraph == nil {
+		return failNoLicenses
+	}
+
+	// Apply policy to find conflicts and report them to stderr lexicographically ordered.
+	conflicts := compliance.ConflictingSharedPrivateSource(licenseGraph)
+	sort.Sort(byError(conflicts))
+	for _, conflict := range conflicts {
+		fmt.Fprintln(stderr, conflict.Error())
+	}
+
+	// Indicate pass or fail on stdout.
+	if len(conflicts) > 0 {
+		fmt.Fprintln(stdout, "FAIL")
+		return failConflicts
+	}
+	fmt.Fprintln(stdout, "PASS")
+	return nil
+}
diff --git a/tools/compliance/cmd/checkshare_test.go b/tools/compliance/cmd/checkshare_test.go
new file mode 100644
index 0000000..8ea7748
--- /dev/null
+++ b/tools/compliance/cmd/checkshare_test.go
@@ -0,0 +1,299 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+type outcome struct {
+	target           string
+	privacyOrigin    string
+	privacyCondition string
+	shareOrigin      string
+	shareCondition   string
+}
+
+func (o *outcome) String() string {
+	return fmt.Sprintf("%s %s from %s and must share from %s %s",
+		o.target, o.privacyCondition, o.privacyOrigin, o.shareCondition, o.shareOrigin)
+}
+
+type outcomeList []*outcome
+
+func (ol outcomeList) String() string {
+	result := ""
+	for _, o := range ol {
+		result = result + o.String() + "\n"
+	}
+	return result
+}
+
+func Test(t *testing.T) {
+	tests := []struct {
+		condition        string
+		name             string
+		roots            []string
+		expectedStdout   string
+		expectedOutcomes outcomeList
+	}{
+		{
+			condition:      "firstparty",
+			name:           "apex",
+			roots:          []string{"highest.apex.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "firstparty",
+			name:           "container",
+			roots:          []string{"container.zip.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "firstparty",
+			name:           "application",
+			roots:          []string{"application.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "firstparty",
+			name:           "binary",
+			roots:          []string{"bin/bin2.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "firstparty",
+			name:           "library",
+			roots:          []string{"lib/libd.so.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "notice",
+			name:           "apex",
+			roots:          []string{"highest.apex.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "notice",
+			name:           "container",
+			roots:          []string{"container.zip.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "notice",
+			name:           "application",
+			roots:          []string{"application.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "notice",
+			name:           "binary",
+			roots:          []string{"bin/bin2.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "notice",
+			name:           "library",
+			roots:          []string{"lib/libd.so.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "reciprocal",
+			name:           "apex",
+			roots:          []string{"highest.apex.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "reciprocal",
+			name:           "container",
+			roots:          []string{"container.zip.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "reciprocal",
+			name:           "application",
+			roots:          []string{"application.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "reciprocal",
+			name:           "binary",
+			roots:          []string{"bin/bin2.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "reciprocal",
+			name:           "library",
+			roots:          []string{"lib/libd.so.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "restricted",
+			name:           "apex",
+			roots:          []string{"highest.apex.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "restricted",
+			name:           "container",
+			roots:          []string{"container.zip.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "restricted",
+			name:           "application",
+			roots:          []string{"application.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "restricted",
+			name:           "binary",
+			roots:          []string{"bin/bin2.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "restricted",
+			name:           "library",
+			roots:          []string{"lib/libd.so.meta_lic"},
+			expectedStdout: "PASS",
+		},
+		{
+			condition:      "proprietary",
+			name:           "apex",
+			roots:          []string{"highest.apex.meta_lic"},
+			expectedStdout: "FAIL",
+			expectedOutcomes: outcomeList{
+				&outcome{
+					target:           "testdata/proprietary/bin/bin2.meta_lic",
+					privacyOrigin:    "testdata/proprietary/bin/bin2.meta_lic",
+					privacyCondition: "proprietary",
+					shareOrigin:      "testdata/proprietary/lib/libb.so.meta_lic",
+					shareCondition:   "restricted",
+				},
+			},
+		},
+		{
+			condition:      "proprietary",
+			name:           "container",
+			roots:          []string{"container.zip.meta_lic"},
+			expectedStdout: "FAIL",
+			expectedOutcomes: outcomeList{
+				&outcome{
+					target:           "testdata/proprietary/bin/bin2.meta_lic",
+					privacyOrigin:    "testdata/proprietary/bin/bin2.meta_lic",
+					privacyCondition: "proprietary",
+					shareOrigin:      "testdata/proprietary/lib/libb.so.meta_lic",
+					shareCondition:   "restricted",
+				},
+			},
+		},
+		{
+			condition:      "proprietary",
+			name:           "application",
+			roots:          []string{"application.meta_lic"},
+			expectedStdout: "FAIL",
+			expectedOutcomes: outcomeList{
+				&outcome{
+					target:           "testdata/proprietary/lib/liba.so.meta_lic",
+					privacyOrigin:    "testdata/proprietary/lib/liba.so.meta_lic",
+					privacyCondition: "proprietary",
+					shareOrigin:      "testdata/proprietary/lib/libb.so.meta_lic",
+					shareCondition:   "restricted",
+				},
+			},
+		},
+		{
+			condition:      "proprietary",
+			name:           "binary",
+			roots:          []string{"bin/bin2.meta_lic", "lib/libb.so.meta_lic"},
+			expectedStdout: "FAIL",
+			expectedOutcomes: outcomeList{
+				&outcome{
+					target:           "testdata/proprietary/bin/bin2.meta_lic",
+					privacyOrigin:    "testdata/proprietary/bin/bin2.meta_lic",
+					privacyCondition: "proprietary",
+					shareOrigin:      "testdata/proprietary/lib/libb.so.meta_lic",
+					shareCondition:   "restricted",
+				},
+			},
+		},
+		{
+			condition:      "proprietary",
+			name:           "library",
+			roots:          []string{"lib/libd.so.meta_lic"},
+			expectedStdout: "PASS",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
+			stdout := &bytes.Buffer{}
+			stderr := &bytes.Buffer{}
+
+			rootFiles := make([]string, 0, len(tt.roots))
+			for _, r := range tt.roots {
+				rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
+			}
+			err := checkShare(stdout, stderr, rootFiles...)
+			if err != nil && err != failConflicts {
+				t.Fatalf("checkshare: error = %v, stderr = %v", err, stderr)
+				return
+			}
+			var actualStdout string
+			for _, s := range strings.Split(stdout.String(), "\n") {
+				ts := strings.TrimLeft(s, " \t")
+				if len(ts) < 1 {
+					continue
+				}
+				if 0 < len(actualStdout) {
+					t.Errorf("checkshare: unexpected multiple output lines %q, want %q", actualStdout+"\n"+ts, tt.expectedStdout)
+				}
+				actualStdout = ts
+			}
+			if actualStdout != tt.expectedStdout {
+				t.Errorf("checkshare: unexpected stdout %q, want %q", actualStdout, tt.expectedStdout)
+			}
+			errList := strings.Split(stderr.String(), "\n")
+			actualOutcomes := make(outcomeList, 0, len(errList))
+			for _, cstring := range errList {
+				ts := strings.TrimLeft(cstring, " \t")
+				if len(ts) < 1 {
+					continue
+				}
+				cFields := strings.Split(ts, " ")
+				actualOutcomes = append(actualOutcomes, &outcome{
+					target:           cFields[0],
+					privacyOrigin:    cFields[3],
+					privacyCondition: cFields[1],
+					shareOrigin:      cFields[9],
+					shareCondition:   cFields[8],
+				})
+			}
+			if len(actualOutcomes) != len(tt.expectedOutcomes) {
+				t.Errorf("checkshare: unexpected got %d outcomes %s, want %d outcomes %s",
+					len(actualOutcomes), actualOutcomes, len(tt.expectedOutcomes), tt.expectedOutcomes)
+				return
+			}
+			for i := range actualOutcomes {
+				if actualOutcomes[i].String() != tt.expectedOutcomes[i].String() {
+					t.Errorf("checkshare: unexpected outcome #%d, got %q, want %q",
+						i+1, actualOutcomes[i], tt.expectedOutcomes[i])
+				}
+			}
+		})
+	}
+}
diff --git a/tools/compliance/cmd/dumpgraph.go b/tools/compliance/cmd/dumpgraph.go
new file mode 100644
index 0000000..1ee63b2
--- /dev/null
+++ b/tools/compliance/cmd/dumpgraph.go
@@ -0,0 +1,178 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"compliance"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+)
+
+var (
+	graphViz        = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.")
+	labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.")
+	stripPrefix     = flag.String("strip_prefix", "", "Prefix to remove from paths. i.e. path to root")
+
+	failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
+	failNoLicenses = fmt.Errorf("No licenses found")
+)
+
+type context struct {
+	graphViz        bool
+	labelConditions bool
+	stripPrefix     string
+}
+
+func init() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
+
+Outputs space-separated Target Dependency Annotations tuples for each
+edge in the license graph. When -dot flag given, outputs the nodes and
+edges in graphViz directed graph format.
+
+In plain text mode, multiple values within a field are colon-separated.
+e.g. multiple annotations appear as annotation1:annotation2:annotation3
+or when -label_conditions is requested, Target and Dependency become
+target:condition1:condition2 etc.
+
+Options:
+`, filepath.Base(os.Args[0]))
+		flag.PrintDefaults()
+	}
+}
+
+func main() {
+	flag.Parse()
+
+	// Must specify at least one root target.
+	if flag.NArg() == 0 {
+		flag.Usage()
+		os.Exit(2)
+	}
+
+	ctx := &context{*graphViz, *labelConditions, *stripPrefix}
+
+	err := dumpGraph(ctx, os.Stdout, os.Stderr, flag.Args()...)
+	if err != nil {
+		if err == failNoneRequested {
+			flag.Usage()
+		}
+		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
+		os.Exit(1)
+	}
+	os.Exit(0)
+}
+
+// dumpGraph implements the dumpgraph utility.
+func dumpGraph(ctx *context, stdout, stderr io.Writer, files ...string) error {
+	if len(files) < 1 {
+		return failNoneRequested
+	}
+
+	// Read the license graph from the license metadata files (*.meta_lic).
+	licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+	if err != nil {
+		return fmt.Errorf("Unable to read license metadata file(s) %q: %w\n", files, err)
+	}
+	if licenseGraph == nil {
+		return failNoLicenses
+	}
+
+	// Sort the edges of the graph.
+	edges := licenseGraph.Edges()
+	sort.Sort(edges)
+
+	// nodes maps license metadata file names to graphViz node names when ctx.graphViz is true.
+	var nodes map[string]string
+	n := 0
+
+	// targetOut calculates the string to output for `target` separating conditions as needed using `sep`.
+	targetOut := func(target *compliance.TargetNode, sep string) string {
+		tOut := strings.TrimPrefix(target.Name(), ctx.stripPrefix)
+		if ctx.labelConditions {
+			conditions := target.LicenseConditions().Names()
+			sort.Strings(conditions)
+			if len(conditions) > 0 {
+				tOut += sep + strings.Join(conditions, sep)
+			}
+		}
+		return tOut
+	}
+
+	// makeNode maps `target` to a graphViz node name.
+	makeNode := func(target *compliance.TargetNode) {
+		tName := target.Name()
+		if _, ok := nodes[tName]; !ok {
+			nodeName := fmt.Sprintf("n%d", n)
+			nodes[tName] = nodeName
+			fmt.Fprintf(stdout, "\t%s [label=\"%s\"];\n", nodeName, targetOut(target, "\\n"))
+			n++
+		}
+	}
+
+	// If graphviz output, map targets to node names, and start the directed graph.
+	if ctx.graphViz {
+		nodes = make(map[string]string)
+		targets := licenseGraph.Targets()
+		sort.Sort(targets)
+
+		fmt.Fprintf(stdout, "strict digraph {\n\trankdir=RL;\n")
+		for _, target := range targets {
+			makeNode(target)
+		}
+	}
+
+	// Print the sorted edges to stdout ...
+	for _, e := range edges {
+		// sort the annotations for repeatability/stability
+		annotations := e.Annotations().AsList()
+		sort.Strings(annotations)
+
+		tName := e.Target().Name()
+		dName := e.Dependency().Name()
+
+		if ctx.graphViz {
+			// ... one edge per line labelled with \\n-separated annotations.
+			tNode := nodes[tName]
+			dNode := nodes[dName]
+			fmt.Fprintf(stdout, "\t%s -> %s [label=\"%s\"];\n", dNode, tNode, strings.Join(annotations, "\\n"))
+		} else {
+			// ... one edge per line with annotations in a colon-separated tuple.
+			fmt.Fprintf(stdout, "%s %s %s\n", targetOut(e.Target(), ":"), targetOut(e.Dependency(), ":"), strings.Join(annotations, ":"))
+		}
+	}
+
+	// If graphViz output, rank the root nodes together, and complete the directed graph.
+	if ctx.graphViz {
+		fmt.Fprintf(stdout, "\t{rank=same;")
+		for _, f := range files {
+			fName := f
+			if !strings.HasSuffix(fName, ".meta_lic") {
+				fName += ".meta_lic"
+			}
+			if fNode, ok := nodes[fName]; ok {
+				fmt.Fprintf(stdout, " %s", fNode)
+			}
+		}
+		fmt.Fprintf(stdout, "}\n}\n")
+	}
+	return nil
+}
diff --git a/tools/compliance/cmd/dumpgraph_test.go b/tools/compliance/cmd/dumpgraph_test.go
new file mode 100644
index 0000000..b7d66f7
--- /dev/null
+++ b/tools/compliance/cmd/dumpgraph_test.go
@@ -0,0 +1,1258 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func Test_plaintext(t *testing.T) {
+	tests := []struct {
+		condition   string
+		name        string
+		roots       []string
+		ctx         context
+		expectedOut []string
+	}{
+		{
+			condition: "firstparty",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/liba.so.meta_lic static",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/libc.a.meta_lic static",
+				"testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/lib/libb.so.meta_lic dynamic",
+				"testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/lib/libd.so.meta_lic dynamic",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/bin/bin1.meta_lic static",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/bin/bin2.meta_lic static",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/lib/liba.so.meta_lic static",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic static",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic static",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic dynamic",
+				"bin/bin2.meta_lic lib/libd.so.meta_lic dynamic",
+				"highest.apex.meta_lic bin/bin1.meta_lic static",
+				"highest.apex.meta_lic bin/bin2.meta_lic static",
+				"highest.apex.meta_lic lib/liba.so.meta_lic static",
+				"highest.apex.meta_lic lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:notice static",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:notice static",
+				"bin/bin2.meta_lic:notice lib/libb.so.meta_lic:notice dynamic",
+				"bin/bin2.meta_lic:notice lib/libd.so.meta_lic:notice dynamic",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice static",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice static",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:notice static",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:notice static",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/liba.so.meta_lic static",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/libc.a.meta_lic static",
+				"testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/lib/libb.so.meta_lic dynamic",
+				"testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/lib/libd.so.meta_lic dynamic",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/bin/bin1.meta_lic static",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/bin/bin2.meta_lic static",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/lib/liba.so.meta_lic static",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/application.meta_lic testdata/firstparty/bin/bin3.meta_lic toolchain",
+				"testdata/firstparty/application.meta_lic testdata/firstparty/lib/liba.so.meta_lic static",
+				"testdata/firstparty/application.meta_lic testdata/firstparty/lib/libb.so.meta_lic dynamic",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/liba.so.meta_lic static",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/libc.a.meta_lic static",
+			},
+		},
+		{
+			condition:   "firstparty",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{},
+		},
+		{
+			condition: "notice",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/liba.so.meta_lic static",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/libc.a.meta_lic static",
+				"testdata/notice/bin/bin2.meta_lic testdata/notice/lib/libb.so.meta_lic dynamic",
+				"testdata/notice/bin/bin2.meta_lic testdata/notice/lib/libd.so.meta_lic dynamic",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/bin/bin1.meta_lic static",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/bin/bin2.meta_lic static",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/lib/liba.so.meta_lic static",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic static",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic static",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic dynamic",
+				"bin/bin2.meta_lic lib/libd.so.meta_lic dynamic",
+				"highest.apex.meta_lic bin/bin1.meta_lic static",
+				"highest.apex.meta_lic bin/bin2.meta_lic static",
+				"highest.apex.meta_lic lib/liba.so.meta_lic static",
+				"highest.apex.meta_lic lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:notice static",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:notice static",
+				"bin/bin2.meta_lic:notice lib/libb.so.meta_lic:notice dynamic",
+				"bin/bin2.meta_lic:notice lib/libd.so.meta_lic:notice dynamic",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice static",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice static",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:notice static",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:notice static",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/liba.so.meta_lic static",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/libc.a.meta_lic static",
+				"testdata/notice/bin/bin2.meta_lic testdata/notice/lib/libb.so.meta_lic dynamic",
+				"testdata/notice/bin/bin2.meta_lic testdata/notice/lib/libd.so.meta_lic dynamic",
+				"testdata/notice/container.zip.meta_lic testdata/notice/bin/bin1.meta_lic static",
+				"testdata/notice/container.zip.meta_lic testdata/notice/bin/bin2.meta_lic static",
+				"testdata/notice/container.zip.meta_lic testdata/notice/lib/liba.so.meta_lic static",
+				"testdata/notice/container.zip.meta_lic testdata/notice/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/application.meta_lic testdata/notice/bin/bin3.meta_lic toolchain",
+				"testdata/notice/application.meta_lic testdata/notice/lib/liba.so.meta_lic static",
+				"testdata/notice/application.meta_lic testdata/notice/lib/libb.so.meta_lic dynamic",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/liba.so.meta_lic static",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/libc.a.meta_lic static",
+			},
+		},
+		{
+			condition:   "notice",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/liba.so.meta_lic static",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/libc.a.meta_lic static",
+				"testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/lib/libb.so.meta_lic dynamic",
+				"testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/lib/libd.so.meta_lic dynamic",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/bin/bin1.meta_lic static",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/bin/bin2.meta_lic static",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/lib/liba.so.meta_lic static",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic static",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic static",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic dynamic",
+				"bin/bin2.meta_lic lib/libd.so.meta_lic dynamic",
+				"highest.apex.meta_lic bin/bin1.meta_lic static",
+				"highest.apex.meta_lic bin/bin2.meta_lic static",
+				"highest.apex.meta_lic lib/liba.so.meta_lic static",
+				"highest.apex.meta_lic lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:reciprocal static",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:reciprocal static",
+				"bin/bin2.meta_lic:notice lib/libb.so.meta_lic:notice dynamic",
+				"bin/bin2.meta_lic:notice lib/libd.so.meta_lic:notice dynamic",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice static",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice static",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:reciprocal static",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:notice static",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/liba.so.meta_lic static",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/libc.a.meta_lic static",
+				"testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/lib/libb.so.meta_lic dynamic",
+				"testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/lib/libd.so.meta_lic dynamic",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/bin/bin1.meta_lic static",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/bin/bin2.meta_lic static",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/lib/liba.so.meta_lic static",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/application.meta_lic testdata/reciprocal/bin/bin3.meta_lic toolchain",
+				"testdata/reciprocal/application.meta_lic testdata/reciprocal/lib/liba.so.meta_lic static",
+				"testdata/reciprocal/application.meta_lic testdata/reciprocal/lib/libb.so.meta_lic dynamic",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/liba.so.meta_lic static",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/libc.a.meta_lic static",
+			},
+		},
+		{
+			condition:   "reciprocal",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{},
+		},
+		{
+			condition: "restricted",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic static",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic static",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic dynamic",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libd.so.meta_lic dynamic",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/bin/bin1.meta_lic static",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/bin/bin2.meta_lic static",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/liba.so.meta_lic static",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic static",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic static",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic dynamic",
+				"bin/bin2.meta_lic lib/libd.so.meta_lic dynamic",
+				"highest.apex.meta_lic bin/bin1.meta_lic static",
+				"highest.apex.meta_lic bin/bin2.meta_lic static",
+				"highest.apex.meta_lic lib/liba.so.meta_lic static",
+				"highest.apex.meta_lic lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:restricted static",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:reciprocal static",
+				"bin/bin2.meta_lic:notice lib/libb.so.meta_lic:restricted dynamic",
+				"bin/bin2.meta_lic:notice lib/libd.so.meta_lic:notice dynamic",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice static",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice static",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:restricted static",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:restricted static",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic static",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic static",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic dynamic",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libd.so.meta_lic dynamic",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/bin/bin1.meta_lic static",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/bin/bin2.meta_lic static",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/lib/liba.so.meta_lic static",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/application.meta_lic testdata/restricted/bin/bin3.meta_lic toolchain",
+				"testdata/restricted/application.meta_lic testdata/restricted/lib/liba.so.meta_lic static",
+				"testdata/restricted/application.meta_lic testdata/restricted/lib/libb.so.meta_lic dynamic",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic static",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic static",
+			},
+		},
+		{
+			condition:   "restricted",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/liba.so.meta_lic static",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/libc.a.meta_lic static",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic dynamic",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libd.so.meta_lic dynamic",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/bin/bin1.meta_lic static",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/bin/bin2.meta_lic static",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/lib/liba.so.meta_lic static",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic static",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic static",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic dynamic",
+				"bin/bin2.meta_lic lib/libd.so.meta_lic dynamic",
+				"highest.apex.meta_lic bin/bin1.meta_lic static",
+				"highest.apex.meta_lic bin/bin2.meta_lic static",
+				"highest.apex.meta_lic lib/liba.so.meta_lic static",
+				"highest.apex.meta_lic lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:by_exception_only:proprietary static",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:by_exception_only:proprietary static",
+				"bin/bin2.meta_lic:by_exception_only:proprietary lib/libb.so.meta_lic:restricted dynamic",
+				"bin/bin2.meta_lic:by_exception_only:proprietary lib/libd.so.meta_lic:notice dynamic",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice static",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:by_exception_only:proprietary static",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:by_exception_only:proprietary static",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:restricted static",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/liba.so.meta_lic static",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/libc.a.meta_lic static",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic dynamic",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libd.so.meta_lic dynamic",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/bin/bin1.meta_lic static",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/bin/bin2.meta_lic static",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/lib/liba.so.meta_lic static",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/lib/libb.so.meta_lic static",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/application.meta_lic testdata/proprietary/bin/bin3.meta_lic toolchain",
+				"testdata/proprietary/application.meta_lic testdata/proprietary/lib/liba.so.meta_lic static",
+				"testdata/proprietary/application.meta_lic testdata/proprietary/lib/libb.so.meta_lic dynamic",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/liba.so.meta_lic static",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/libc.a.meta_lic static",
+			},
+		},
+		{
+			condition:   "proprietary",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
+			expectedOut := &bytes.Buffer{}
+			for _, eo := range tt.expectedOut {
+				expectedOut.WriteString(eo)
+				expectedOut.WriteString("\n")
+			}
+
+			stdout := &bytes.Buffer{}
+			stderr := &bytes.Buffer{}
+
+			rootFiles := make([]string, 0, len(tt.roots))
+			for _, r := range tt.roots {
+				rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
+			}
+			err := dumpGraph(&tt.ctx, stdout, stderr, rootFiles...)
+			if err != nil {
+				t.Fatalf("dumpgraph: error = %v, stderr = %v", err, stderr)
+				return
+			}
+			if stderr.Len() > 0 {
+				t.Errorf("dumpgraph: gotStderr = %v, want none", stderr)
+			}
+			out := stdout.String()
+			expected := expectedOut.String()
+			if out != expected {
+				outList := strings.Split(out, "\n")
+				expectedList := strings.Split(expected, "\n")
+				startLine := 0
+				for len(outList) > startLine && len(expectedList) > startLine && outList[startLine] == expectedList[startLine] {
+					startLine++
+				}
+				t.Errorf("listshare: gotStdout = %v, want %v, somewhere near line %d Stdout = %v, want %v",
+					out, expected, startLine+1, outList[startLine], expectedList[startLine])
+			}
+		})
+	}
+}
+
+type testContext struct {
+	nextNode int
+	nodes    map[string]string
+}
+
+type matcher interface {
+	matchString(*testContext) string
+	typeString() string
+}
+
+type targetMatcher struct {
+	target     string
+	conditions []string
+}
+
+func (tm *targetMatcher) matchString(ctx *testContext) string {
+	m := tm.target
+	if len(tm.conditions) > 0 {
+		m += "\\n" + strings.Join(tm.conditions, "\\n")
+	}
+	m = ctx.nodes[tm.target] + " [label=\"" + m + "\"];"
+	return m
+}
+
+func (tm *targetMatcher) typeString() string {
+	return "target"
+}
+
+type edgeMatcher struct {
+	target      string
+	dep         string
+	annotations []string
+}
+
+func (em *edgeMatcher) matchString(ctx *testContext) string {
+	return ctx.nodes[em.dep] + " -> " + ctx.nodes[em.target] + " [label=\"" + strings.Join(em.annotations, "\\n") + "\"];"
+}
+
+func (tm *edgeMatcher) typeString() string {
+	return "edge"
+}
+
+type getMatcher func(*testContext) matcher
+
+func matchTarget(target string, conditions ...string) getMatcher {
+	return func(ctx *testContext) matcher {
+		ctx.nodes[target] = fmt.Sprintf("n%d", ctx.nextNode)
+		ctx.nextNode++
+		return &targetMatcher{target, append([]string{}, conditions...)}
+	}
+}
+
+func matchEdge(target, dep string, annotations ...string) getMatcher {
+	return func(ctx *testContext) matcher {
+		if _, ok := ctx.nodes[target]; !ok {
+			panic(fmt.Errorf("no node for target %v in %v -> %v [label=\"%s\"];", target, dep, target, strings.Join(annotations, "\\n")))
+		}
+		if _, ok := ctx.nodes[dep]; !ok {
+			panic(fmt.Errorf("no node for dep %v in %v -> %v [label=\"%s\"];", target, dep, target, strings.Join(annotations, "\\n")))
+		}
+		return &edgeMatcher{target, dep, append([]string{}, annotations...)}
+	}
+}
+
+func Test_graphviz(t *testing.T) {
+	tests := []struct {
+		condition   string
+		name        string
+		roots       []string
+		ctx         context
+		expectedOut []getMatcher
+	}{
+		{
+			condition: "firstparty",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/bin/bin1.meta_lic"),
+				matchTarget("testdata/firstparty/bin/bin2.meta_lic"),
+				matchTarget("testdata/firstparty/highest.apex.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libb.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libc.a.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libd.so.meta_lic"),
+				matchEdge("testdata/firstparty/bin/bin1.meta_lic", "testdata/firstparty/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/firstparty/bin/bin1.meta_lic", "testdata/firstparty/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/firstparty/bin/bin2.meta_lic", "testdata/firstparty/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/firstparty/bin/bin2.meta_lic", "testdata/firstparty/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/firstparty/highest.apex.meta_lic", "testdata/firstparty/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/firstparty/highest.apex.meta_lic", "testdata/firstparty/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/firstparty/highest.apex.meta_lic", "testdata/firstparty/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/firstparty/highest.apex.meta_lic", "testdata/firstparty/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "notice"),
+				matchTarget("lib/libb.so.meta_lic", "notice"),
+				matchTarget("lib/libc.a.meta_lic", "notice"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/bin/bin1.meta_lic"),
+				matchTarget("testdata/firstparty/bin/bin2.meta_lic"),
+				matchTarget("testdata/firstparty/container.zip.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libb.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libc.a.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libd.so.meta_lic"),
+				matchEdge("testdata/firstparty/bin/bin1.meta_lic", "testdata/firstparty/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/firstparty/bin/bin1.meta_lic", "testdata/firstparty/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/firstparty/bin/bin2.meta_lic", "testdata/firstparty/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/firstparty/bin/bin2.meta_lic", "testdata/firstparty/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/firstparty/container.zip.meta_lic", "testdata/firstparty/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/firstparty/container.zip.meta_lic", "testdata/firstparty/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/firstparty/container.zip.meta_lic", "testdata/firstparty/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/firstparty/container.zip.meta_lic", "testdata/firstparty/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/application.meta_lic"),
+				matchTarget("testdata/firstparty/bin/bin3.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libb.so.meta_lic"),
+				matchEdge("testdata/firstparty/application.meta_lic", "testdata/firstparty/bin/bin3.meta_lic", "toolchain"),
+				matchEdge("testdata/firstparty/application.meta_lic", "testdata/firstparty/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/firstparty/application.meta_lic", "testdata/firstparty/lib/libb.so.meta_lic", "dynamic"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/bin/bin1.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libc.a.meta_lic"),
+				matchEdge("testdata/firstparty/bin/bin1.meta_lic", "testdata/firstparty/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/firstparty/bin/bin1.meta_lic", "testdata/firstparty/lib/libc.a.meta_lic", "static"),
+			},
+		},
+		{
+			condition:   "firstparty",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{matchTarget("testdata/firstparty/lib/libd.so.meta_lic")},
+		},
+		{
+			condition: "notice",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/bin/bin1.meta_lic"),
+				matchTarget("testdata/notice/bin/bin2.meta_lic"),
+				matchTarget("testdata/notice/highest.apex.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libb.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libc.a.meta_lic"),
+				matchTarget("testdata/notice/lib/libd.so.meta_lic"),
+				matchEdge("testdata/notice/bin/bin1.meta_lic", "testdata/notice/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/notice/bin/bin1.meta_lic", "testdata/notice/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/notice/bin/bin2.meta_lic", "testdata/notice/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/notice/bin/bin2.meta_lic", "testdata/notice/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/notice/highest.apex.meta_lic", "testdata/notice/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/notice/highest.apex.meta_lic", "testdata/notice/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/notice/highest.apex.meta_lic", "testdata/notice/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/notice/highest.apex.meta_lic", "testdata/notice/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "notice"),
+				matchTarget("lib/libb.so.meta_lic", "notice"),
+				matchTarget("lib/libc.a.meta_lic", "notice"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/bin/bin1.meta_lic"),
+				matchTarget("testdata/notice/bin/bin2.meta_lic"),
+				matchTarget("testdata/notice/container.zip.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libb.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libc.a.meta_lic"),
+				matchTarget("testdata/notice/lib/libd.so.meta_lic"),
+				matchEdge("testdata/notice/bin/bin1.meta_lic", "testdata/notice/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/notice/bin/bin1.meta_lic", "testdata/notice/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/notice/bin/bin2.meta_lic", "testdata/notice/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/notice/bin/bin2.meta_lic", "testdata/notice/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/notice/container.zip.meta_lic", "testdata/notice/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/notice/container.zip.meta_lic", "testdata/notice/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/notice/container.zip.meta_lic", "testdata/notice/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/notice/container.zip.meta_lic", "testdata/notice/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/application.meta_lic"),
+				matchTarget("testdata/notice/bin/bin3.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libb.so.meta_lic"),
+				matchEdge("testdata/notice/application.meta_lic", "testdata/notice/bin/bin3.meta_lic", "toolchain"),
+				matchEdge("testdata/notice/application.meta_lic", "testdata/notice/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/notice/application.meta_lic", "testdata/notice/lib/libb.so.meta_lic", "dynamic"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/bin/bin1.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libc.a.meta_lic"),
+				matchEdge("testdata/notice/bin/bin1.meta_lic", "testdata/notice/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/notice/bin/bin1.meta_lic", "testdata/notice/lib/libc.a.meta_lic", "static"),
+			},
+		},
+		{
+			condition:   "notice",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{matchTarget("testdata/notice/lib/libd.so.meta_lic")},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/bin/bin1.meta_lic"),
+				matchTarget("testdata/reciprocal/bin/bin2.meta_lic"),
+				matchTarget("testdata/reciprocal/highest.apex.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libb.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libc.a.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libd.so.meta_lic"),
+				matchEdge("testdata/reciprocal/bin/bin1.meta_lic", "testdata/reciprocal/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/bin/bin1.meta_lic", "testdata/reciprocal/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/bin/bin2.meta_lic", "testdata/reciprocal/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/reciprocal/bin/bin2.meta_lic", "testdata/reciprocal/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/reciprocal/highest.apex.meta_lic", "testdata/reciprocal/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/highest.apex.meta_lic", "testdata/reciprocal/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/highest.apex.meta_lic", "testdata/reciprocal/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/highest.apex.meta_lic", "testdata/reciprocal/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "reciprocal"),
+				matchTarget("lib/libb.so.meta_lic", "notice"),
+				matchTarget("lib/libc.a.meta_lic", "reciprocal"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/bin/bin1.meta_lic"),
+				matchTarget("testdata/reciprocal/bin/bin2.meta_lic"),
+				matchTarget("testdata/reciprocal/container.zip.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libb.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libc.a.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libd.so.meta_lic"),
+				matchEdge("testdata/reciprocal/bin/bin1.meta_lic", "testdata/reciprocal/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/bin/bin1.meta_lic", "testdata/reciprocal/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/bin/bin2.meta_lic", "testdata/reciprocal/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/reciprocal/bin/bin2.meta_lic", "testdata/reciprocal/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/reciprocal/container.zip.meta_lic", "testdata/reciprocal/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/container.zip.meta_lic", "testdata/reciprocal/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/container.zip.meta_lic", "testdata/reciprocal/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/container.zip.meta_lic", "testdata/reciprocal/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/application.meta_lic"),
+				matchTarget("testdata/reciprocal/bin/bin3.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libb.so.meta_lic"),
+				matchEdge("testdata/reciprocal/application.meta_lic", "testdata/reciprocal/bin/bin3.meta_lic", "toolchain"),
+				matchEdge("testdata/reciprocal/application.meta_lic", "testdata/reciprocal/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/application.meta_lic", "testdata/reciprocal/lib/libb.so.meta_lic", "dynamic"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/bin/bin1.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libc.a.meta_lic"),
+				matchEdge("testdata/reciprocal/bin/bin1.meta_lic", "testdata/reciprocal/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/reciprocal/bin/bin1.meta_lic", "testdata/reciprocal/lib/libc.a.meta_lic", "static"),
+			},
+		},
+		{
+			condition:   "reciprocal",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{matchTarget("testdata/reciprocal/lib/libd.so.meta_lic")},
+		},
+		{
+			condition: "restricted",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/bin/bin1.meta_lic"),
+				matchTarget("testdata/restricted/bin/bin2.meta_lic"),
+				matchTarget("testdata/restricted/highest.apex.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libb.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libc.a.meta_lic"),
+				matchTarget("testdata/restricted/lib/libd.so.meta_lic"),
+				matchEdge("testdata/restricted/bin/bin1.meta_lic", "testdata/restricted/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/restricted/bin/bin1.meta_lic", "testdata/restricted/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/restricted/bin/bin2.meta_lic", "testdata/restricted/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/restricted/bin/bin2.meta_lic", "testdata/restricted/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/restricted/highest.apex.meta_lic", "testdata/restricted/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/restricted/highest.apex.meta_lic", "testdata/restricted/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/restricted/highest.apex.meta_lic", "testdata/restricted/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/restricted/highest.apex.meta_lic", "testdata/restricted/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "restricted"),
+				matchTarget("lib/libb.so.meta_lic", "restricted"),
+				matchTarget("lib/libc.a.meta_lic", "reciprocal"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/bin/bin1.meta_lic"),
+				matchTarget("testdata/restricted/bin/bin2.meta_lic"),
+				matchTarget("testdata/restricted/container.zip.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libb.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libc.a.meta_lic"),
+				matchTarget("testdata/restricted/lib/libd.so.meta_lic"),
+				matchEdge("testdata/restricted/bin/bin1.meta_lic", "testdata/restricted/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/restricted/bin/bin1.meta_lic", "testdata/restricted/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/restricted/bin/bin2.meta_lic", "testdata/restricted/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/restricted/bin/bin2.meta_lic", "testdata/restricted/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/restricted/container.zip.meta_lic", "testdata/restricted/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/restricted/container.zip.meta_lic", "testdata/restricted/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/restricted/container.zip.meta_lic", "testdata/restricted/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/restricted/container.zip.meta_lic", "testdata/restricted/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/application.meta_lic"),
+				matchTarget("testdata/restricted/bin/bin3.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libb.so.meta_lic"),
+				matchEdge("testdata/restricted/application.meta_lic", "testdata/restricted/bin/bin3.meta_lic", "toolchain"),
+				matchEdge("testdata/restricted/application.meta_lic", "testdata/restricted/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/restricted/application.meta_lic", "testdata/restricted/lib/libb.so.meta_lic", "dynamic"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/bin/bin1.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libc.a.meta_lic"),
+				matchEdge("testdata/restricted/bin/bin1.meta_lic", "testdata/restricted/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/restricted/bin/bin1.meta_lic", "testdata/restricted/lib/libc.a.meta_lic", "static"),
+			},
+		},
+		{
+			condition:   "restricted",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{matchTarget("testdata/restricted/lib/libd.so.meta_lic")},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/bin/bin1.meta_lic"),
+				matchTarget("testdata/proprietary/bin/bin2.meta_lic"),
+				matchTarget("testdata/proprietary/highest.apex.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libb.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libc.a.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libd.so.meta_lic"),
+				matchEdge("testdata/proprietary/bin/bin1.meta_lic", "testdata/proprietary/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/proprietary/bin/bin1.meta_lic", "testdata/proprietary/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/proprietary/bin/bin2.meta_lic", "testdata/proprietary/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/proprietary/bin/bin2.meta_lic", "testdata/proprietary/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/proprietary/highest.apex.meta_lic", "testdata/proprietary/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/proprietary/highest.apex.meta_lic", "testdata/proprietary/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/proprietary/highest.apex.meta_lic", "testdata/proprietary/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/proprietary/highest.apex.meta_lic", "testdata/proprietary/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("bin/bin2.meta_lic", "by_exception_only", "proprietary"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "by_exception_only", "proprietary"),
+				matchTarget("lib/libb.so.meta_lic", "restricted"),
+				matchTarget("lib/libc.a.meta_lic", "by_exception_only", "proprietary"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchEdge("bin/bin1.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("bin/bin1.meta_lic", "lib/libc.a.meta_lic", "static"),
+				matchEdge("bin/bin2.meta_lic", "lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("bin/bin2.meta_lic", "lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("highest.apex.meta_lic", "bin/bin1.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "bin/bin2.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/liba.so.meta_lic", "static"),
+				matchEdge("highest.apex.meta_lic", "lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/bin/bin1.meta_lic"),
+				matchTarget("testdata/proprietary/bin/bin2.meta_lic"),
+				matchTarget("testdata/proprietary/container.zip.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libb.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libc.a.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libd.so.meta_lic"),
+				matchEdge("testdata/proprietary/bin/bin1.meta_lic", "testdata/proprietary/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/proprietary/bin/bin1.meta_lic", "testdata/proprietary/lib/libc.a.meta_lic", "static"),
+				matchEdge("testdata/proprietary/bin/bin2.meta_lic", "testdata/proprietary/lib/libb.so.meta_lic", "dynamic"),
+				matchEdge("testdata/proprietary/bin/bin2.meta_lic", "testdata/proprietary/lib/libd.so.meta_lic", "dynamic"),
+				matchEdge("testdata/proprietary/container.zip.meta_lic", "testdata/proprietary/bin/bin1.meta_lic", "static"),
+				matchEdge("testdata/proprietary/container.zip.meta_lic", "testdata/proprietary/bin/bin2.meta_lic", "static"),
+				matchEdge("testdata/proprietary/container.zip.meta_lic", "testdata/proprietary/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/proprietary/container.zip.meta_lic", "testdata/proprietary/lib/libb.so.meta_lic", "static"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/application.meta_lic"),
+				matchTarget("testdata/proprietary/bin/bin3.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libb.so.meta_lic"),
+				matchEdge("testdata/proprietary/application.meta_lic", "testdata/proprietary/bin/bin3.meta_lic", "toolchain"),
+				matchEdge("testdata/proprietary/application.meta_lic", "testdata/proprietary/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/proprietary/application.meta_lic", "testdata/proprietary/lib/libb.so.meta_lic", "dynamic"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/bin/bin1.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libc.a.meta_lic"),
+				matchEdge("testdata/proprietary/bin/bin1.meta_lic", "testdata/proprietary/lib/liba.so.meta_lic", "static"),
+				matchEdge("testdata/proprietary/bin/bin1.meta_lic", "testdata/proprietary/lib/libc.a.meta_lic", "static"),
+			},
+		},
+		{
+			condition:   "proprietary",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{matchTarget("testdata/proprietary/lib/libd.so.meta_lic")},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
+			ctx := &testContext{0, make(map[string]string)}
+
+			expectedOut := &bytes.Buffer{}
+			for _, eo := range tt.expectedOut {
+				m := eo(ctx)
+				expectedOut.WriteString(m.matchString(ctx))
+				expectedOut.WriteString("\n")
+			}
+
+			stdout := &bytes.Buffer{}
+			stderr := &bytes.Buffer{}
+
+			rootFiles := make([]string, 0, len(tt.roots))
+			for _, r := range tt.roots {
+				rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
+			}
+			tt.ctx.graphViz = true
+			err := dumpGraph(&tt.ctx, stdout, stderr, rootFiles...)
+			if err != nil {
+				t.Fatalf("dumpgraph: error = %v, stderr = %v", err, stderr)
+				return
+			}
+			if stderr.Len() > 0 {
+				t.Errorf("dumpgraph: gotStderr = %v, want none", stderr)
+			}
+			outList := strings.Split(stdout.String(), "\n")
+			outLine := 0
+			if outList[outLine] != "strict digraph {" {
+				t.Errorf("dumpgraph: got 1st line %v, want strict digraph {")
+			}
+			outLine++
+			if strings.HasPrefix(strings.TrimLeft(outList[outLine], " \t"), "rankdir") {
+				outLine++
+			}
+			endOut := len(outList)
+			for endOut > 0 && strings.TrimLeft(outList[endOut-1], " \t") == "" {
+				endOut--
+			}
+			if outList[endOut-1] != "}" {
+				t.Errorf("dumpgraph: got last line %v, want }", outList[endOut-1])
+			}
+			endOut--
+			if strings.HasPrefix(strings.TrimLeft(outList[endOut-1], " \t"), "{rank=same") {
+				endOut--
+			}
+			expectedList := strings.Split(expectedOut.String(), "\n")
+			for len(expectedList) > 0 && expectedList[len(expectedList)-1] == "" {
+				expectedList = expectedList[0 : len(expectedList)-1]
+			}
+			matchLine := 0
+
+			for outLine < endOut && matchLine < len(expectedList) && strings.TrimLeft(outList[outLine], " \t") == expectedList[matchLine] {
+				outLine++
+				matchLine++
+			}
+			if outLine < endOut || matchLine < len(expectedList) {
+				if outLine >= endOut {
+					t.Errorf("dumpgraph: missing lines at end of graph, want %d lines %v", len(expectedList)-matchLine, strings.Join(expectedList[matchLine:], "\n"))
+				} else if matchLine >= len(expectedList) {
+					t.Errorf("dumpgraph: unexpected lines at end of graph starting line %d, got %v, want nothing", outLine+1, strings.Join(outList[outLine:], "\n"))
+				} else {
+					t.Errorf("dumpgraph: at line %d, got %v, want %v", outLine+1, strings.Join(outList[outLine:], "\n"), strings.Join(expectedList[matchLine:], "\n"))
+				}
+			}
+		})
+	}
+}
diff --git a/tools/compliance/cmd/dumpresolutions.go b/tools/compliance/cmd/dumpresolutions.go
new file mode 100644
index 0000000..36fbb7d
--- /dev/null
+++ b/tools/compliance/cmd/dumpresolutions.go
@@ -0,0 +1,284 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"compliance"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+)
+
+var (
+	conditions      = newMultiString("c", "License condition to resolve. (may be given multiple times)")
+	graphViz        = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.")
+	labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.")
+	stripPrefix     = flag.String("strip_prefix", "", "Prefix to remove from paths. i.e. path to root")
+
+	failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
+	failNoLicenses = fmt.Errorf("No licenses found")
+)
+
+type context struct {
+	conditions      []string
+	graphViz        bool
+	labelConditions bool
+	stripPrefix     string
+}
+
+func init() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
+
+Outputs a space-separated Target ActsOn Origin Condition tuple for each
+resolution in the graph. When -dot flag given, outputs nodes and edges
+in graphviz directed graph format.
+
+If one or more '-c condition' conditions are given, outputs the joined
+set of resolutions for all of the conditions. Otherwise, outputs the
+result of the bottom-up and top-down resolve only.
+
+In plain text mode, when '-label_conditions' is requested, the Target
+and Origin have colon-separated license conditions appended:
+i.e. target:condition1:condition2 etc.
+
+Options:
+`, filepath.Base(os.Args[0]))
+		flag.PrintDefaults()
+	}
+}
+
+// newMultiString creates a flag that allows multiple values in an array.
+func newMultiString(name, usage string) *multiString {
+	var f multiString
+	flag.Var(&f, name, usage)
+	return &f
+}
+
+// multiString implements the flag `Value` interface for multiple strings.
+type multiString []string
+
+func (ms *multiString) String() string     { return strings.Join(*ms, ", ") }
+func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
+
+func main() {
+	flag.Parse()
+
+	// Must specify at least one root target.
+	if flag.NArg() == 0 {
+		flag.Usage()
+		os.Exit(2)
+	}
+
+	ctx := &context{
+		conditions:      append([]string{}, *conditions...),
+		graphViz:        *graphViz,
+		labelConditions: *labelConditions,
+		stripPrefix:     *stripPrefix,
+	}
+	err := dumpResolutions(ctx, os.Stdout, os.Stderr, flag.Args()...)
+	if err != nil {
+		if err == failNoneRequested {
+			flag.Usage()
+		}
+		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
+		os.Exit(1)
+	}
+	os.Exit(0)
+}
+
+// dumpResolutions implements the dumpresolutions utility.
+func dumpResolutions(ctx *context, stdout, stderr io.Writer, files ...string) error {
+	if len(files) < 1 {
+		return failNoneRequested
+	}
+
+	// Read the license graph from the license metadata files (*.meta_lic).
+	licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+	if err != nil {
+		return fmt.Errorf("Unable to read license metadata file(s) %q: %v\n", files, err)
+	}
+	if licenseGraph == nil {
+		return failNoLicenses
+	}
+
+	// resolutions will contain the requested set of resolutions.
+	var resolutions *compliance.ResolutionSet
+
+	resolutions = compliance.ResolveTopDownConditions(licenseGraph)
+	if len(ctx.conditions) > 0 {
+		rlist := make([]*compliance.ResolutionSet, 0, len(ctx.conditions))
+		for _, c := range ctx.conditions {
+			rlist = append(rlist, compliance.WalkResolutionsForCondition(licenseGraph, resolutions, compliance.ConditionNames{c}))
+		}
+		if len(rlist) == 1 {
+			resolutions = rlist[0]
+		} else {
+			resolutions = compliance.JoinResolutionSets(rlist...)
+		}
+	}
+
+	// nodes maps license metadata file names to graphViz node names when graphViz requested.
+	nodes := make(map[string]string)
+	n := 0
+
+	// targetOut calculates the string to output for `target` adding `sep`-separated conditions as needed.
+	targetOut := func(target *compliance.TargetNode, sep string) string {
+		tOut := strings.TrimPrefix(target.Name(), ctx.stripPrefix)
+		if ctx.labelConditions {
+			conditions := make([]string, 0, target.LicenseConditions().Count())
+			for _, lc := range target.LicenseConditions().AsList() {
+				conditions = append(conditions, lc.Name())
+			}
+			sort.Strings(conditions)
+			if len(conditions) > 0 {
+				tOut += sep + strings.Join(conditions, sep)
+			}
+		}
+		return tOut
+	}
+
+	// makeNode maps `target` to a graphViz node name.
+	makeNode := func(target *compliance.TargetNode) {
+		tName := target.Name()
+		if _, ok := nodes[tName]; !ok {
+			nodeName := fmt.Sprintf("n%d", n)
+			nodes[tName] = nodeName
+			fmt.Fprintf(stdout, "\t%s [label=\"%s\"];\n", nodeName, targetOut(target, "\\n"))
+			n++
+		}
+	}
+
+	// outputResolution prints a resolution in the requested format to `stdout`, where one can read
+	// a resolution as `tname` resolves `oname`'s conditions named in `cnames`.
+	// `tname` is the name of the target the resolution applies to.
+	// `oname` is the name of the target where the conditions originate.
+	// `cnames` is the list of conditions to resolve.
+	outputResolution := func(tname, aname, oname string, cnames []string) {
+		if ctx.graphViz {
+			// ... one edge per line labelled with \\n-separated annotations.
+			tNode := nodes[tname]
+			aNode := nodes[aname]
+			oNode := nodes[oname]
+			fmt.Fprintf(stdout, "\t%s -> %s; %s -> %s [label=\"%s\"];\n", tNode, aNode, aNode, oNode, strings.Join(cnames, "\\n"))
+		} else {
+			// ... one edge per line with names in a colon-separated tuple.
+			fmt.Fprintf(stdout, "%s %s %s %s\n", tname, aname, oname, strings.Join(cnames, ":"))
+		}
+	}
+
+	// outputSingleton prints `tname` to plain text in the unexpected event that `tname` is the name of
+	// a target in `resolutions.AppliesTo()` but has no conditions to resolve.
+	outputSingleton := func(tname, aname string) {
+		if !ctx.graphViz {
+			fmt.Fprintf(stdout, "%s %s\n", tname, aname)
+		}
+	}
+
+	// Sort the resolutions by targetname for repeatability/stability.
+	targets := resolutions.AttachesTo()
+	sort.Sort(targets)
+
+	// If graphviz output, start the directed graph.
+	if ctx.graphViz {
+		fmt.Fprintf(stdout, "strict digraph {\n\trankdir=LR;\n")
+		for _, target := range targets {
+			makeNode(target)
+			rl := compliance.ResolutionList(resolutions.Resolutions(target))
+			sort.Sort(rl)
+			for _, r := range rl {
+				makeNode(r.ActsOn())
+			}
+			conditions := rl.AllConditions().AsList()
+			sort.Sort(conditions)
+			for _, lc := range conditions {
+				makeNode(lc.Origin())
+			}
+		}
+	}
+
+	// Output the sorted targets.
+	for _, target := range targets {
+		var tname string
+		if ctx.graphViz {
+			tname = target.Name()
+		} else {
+			tname = targetOut(target, ":")
+		}
+
+		rl := compliance.ResolutionList(resolutions.Resolutions(target))
+		sort.Sort(rl)
+		for _, r := range rl {
+			var aname string
+			if ctx.graphViz {
+				aname = r.ActsOn().Name()
+			} else {
+				aname = targetOut(r.ActsOn(), ":")
+			}
+
+			conditions := r.Resolves().AsList()
+			sort.Sort(conditions)
+
+			// poname is the previous origin name or "" if no previous
+			poname := ""
+
+			// cnames accumulates the list of condition names originating at a single origin that apply to `target`.
+			cnames := make([]string, 0, len(conditions))
+
+			// Output 1 line for each attachesTo+actsOn+origin combination.
+			for _, condition := range conditions {
+				var oname string
+				if ctx.graphViz {
+					oname = condition.Origin().Name()
+				} else {
+					oname = targetOut(condition.Origin(), ":")
+				}
+
+				// Detect when origin changes and output prior origin's conditions.
+				if poname != oname && poname != "" {
+					outputResolution(tname, aname, poname, cnames)
+					cnames = cnames[:0]
+				}
+				poname = oname
+				cnames = append(cnames, condition.Name())
+			}
+			// Output last origin's conditions or a singleton if no origins.
+			if poname == "" {
+				outputSingleton(tname, aname)
+			} else {
+				outputResolution(tname, aname, poname, cnames)
+			}
+		}
+	}
+	// If graphViz output, rank the root nodes together, and complete the directed graph.
+	if ctx.graphViz {
+		fmt.Fprintf(stdout, "\t{rank=same;")
+		for _, f := range files {
+			fName := f
+			if !strings.HasSuffix(fName, ".meta_lic") {
+				fName += ".meta_lic"
+			}
+			if fNode, ok := nodes[fName]; ok {
+				fmt.Fprintf(stdout, " %s", fNode)
+			}
+		}
+		fmt.Fprintf(stdout, "}\n}\n")
+	}
+	return nil
+}
diff --git a/tools/compliance/cmd/dumpresolutions_test.go b/tools/compliance/cmd/dumpresolutions_test.go
new file mode 100644
index 0000000..cab1cc8
--- /dev/null
+++ b/tools/compliance/cmd/dumpresolutions_test.go
@@ -0,0 +1,4634 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func Test_plaintext(t *testing.T) {
+	tests := []struct {
+		condition   string
+		name        string
+		roots       []string
+		ctx         context
+		expectedOut []string
+	}{
+		{
+			condition: "firstparty",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic notice",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+				"testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/bin/bin2.meta_lic notice",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic notice",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/bin/bin2.meta_lic notice",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/highest.apex.meta_lic testdata/firstparty/highest.apex.meta_lic notice",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic notice",
+				"testdata/firstparty/highest.apex.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+				"testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic notice",
+				"testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+				"testdata/firstparty/lib/libd.so.meta_lic testdata/firstparty/lib/libd.so.meta_lic testdata/firstparty/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"lib/libc.a.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"lib/libd.so.meta_lic lib/libd.so.meta_lic lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice notice",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice notice",
+				"bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice highest.apex.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice notice",
+				"lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice notice",
+				"lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice notice",
+				"lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice notice",
+				"lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice notice",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic notice",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+				"testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/bin/bin2.meta_lic notice",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic notice",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/bin/bin2.meta_lic testdata/firstparty/bin/bin2.meta_lic notice",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/container.zip.meta_lic testdata/firstparty/container.zip.meta_lic notice",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic notice",
+				"testdata/firstparty/container.zip.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+				"testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic notice",
+				"testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+				"testdata/firstparty/lib/libd.so.meta_lic testdata/firstparty/lib/libd.so.meta_lic testdata/firstparty/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/application.meta_lic testdata/firstparty/application.meta_lic testdata/firstparty/application.meta_lic notice",
+				"testdata/firstparty/application.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/bin/bin3.meta_lic testdata/firstparty/bin/bin3.meta_lic testdata/firstparty/bin/bin3.meta_lic notice",
+				"testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic testdata/firstparty/lib/libb.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/bin/bin1.meta_lic notice",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/bin/bin1.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+				"testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic testdata/firstparty/lib/liba.so.meta_lic notice",
+				"testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic testdata/firstparty/lib/libc.a.meta_lic notice",
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{
+				"testdata/firstparty/lib/libd.so.meta_lic testdata/firstparty/lib/libd.so.meta_lic testdata/firstparty/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic notice",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+				"testdata/notice/bin/bin2.meta_lic testdata/notice/bin/bin2.meta_lic testdata/notice/bin/bin2.meta_lic notice",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic notice",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/bin/bin2.meta_lic testdata/notice/bin/bin2.meta_lic notice",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/highest.apex.meta_lic testdata/notice/highest.apex.meta_lic notice",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic notice",
+				"testdata/notice/highest.apex.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+				"testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic notice",
+				"testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+				"testdata/notice/lib/libd.so.meta_lic testdata/notice/lib/libd.so.meta_lic testdata/notice/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"lib/libc.a.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"lib/libd.so.meta_lic lib/libd.so.meta_lic lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic notice",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic notice",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice notice",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice notice",
+				"bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice highest.apex.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice notice",
+				"lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice lib/liba.so.meta_lic:notice notice",
+				"lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice notice",
+				"lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice lib/libc.a.meta_lic:notice notice",
+				"lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic notice",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+				"testdata/notice/bin/bin2.meta_lic testdata/notice/bin/bin2.meta_lic testdata/notice/bin/bin2.meta_lic notice",
+				"testdata/notice/container.zip.meta_lic testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic notice",
+				"testdata/notice/container.zip.meta_lic testdata/notice/bin/bin2.meta_lic testdata/notice/bin/bin2.meta_lic notice",
+				"testdata/notice/container.zip.meta_lic testdata/notice/container.zip.meta_lic testdata/notice/container.zip.meta_lic notice",
+				"testdata/notice/container.zip.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/container.zip.meta_lic testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic notice",
+				"testdata/notice/container.zip.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+				"testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic notice",
+				"testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+				"testdata/notice/lib/libd.so.meta_lic testdata/notice/lib/libd.so.meta_lic testdata/notice/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/application.meta_lic testdata/notice/application.meta_lic testdata/notice/application.meta_lic notice",
+				"testdata/notice/application.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/bin/bin3.meta_lic testdata/notice/bin/bin3.meta_lic testdata/notice/bin/bin3.meta_lic notice",
+				"testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic testdata/notice/lib/libb.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic testdata/notice/bin/bin1.meta_lic notice",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/bin/bin1.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+				"testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic testdata/notice/lib/liba.so.meta_lic notice",
+				"testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic testdata/notice/lib/libc.a.meta_lic notice",
+			},
+		},
+		{
+			condition: "notice",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{
+				"testdata/notice/lib/libd.so.meta_lic testdata/notice/lib/libd.so.meta_lic testdata/notice/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic notice",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+				"testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/bin/bin2.meta_lic notice",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic notice",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/bin/bin2.meta_lic notice",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/highest.apex.meta_lic notice",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic notice",
+				"testdata/reciprocal/highest.apex.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+				"testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic notice",
+				"testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+				"testdata/reciprocal/lib/libd.so.meta_lic testdata/reciprocal/lib/libd.so.meta_lic testdata/reciprocal/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"lib/libc.a.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"lib/libd.so.meta_lic lib/libd.so.meta_lic lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic reciprocal",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:reciprocal lib/liba.so.meta_lic:reciprocal reciprocal",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal reciprocal",
+				"bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice highest.apex.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:reciprocal lib/liba.so.meta_lic:reciprocal reciprocal",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal reciprocal",
+				"lib/liba.so.meta_lic:reciprocal lib/liba.so.meta_lic:reciprocal lib/liba.so.meta_lic:reciprocal reciprocal",
+				"lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice lib/libb.so.meta_lic:notice notice",
+				"lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal reciprocal",
+				"lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice notice",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic notice",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+				"testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/bin/bin2.meta_lic notice",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic notice",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/bin/bin2.meta_lic testdata/reciprocal/bin/bin2.meta_lic notice",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/container.zip.meta_lic notice",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic notice",
+				"testdata/reciprocal/container.zip.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+				"testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic notice",
+				"testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+				"testdata/reciprocal/lib/libd.so.meta_lic testdata/reciprocal/lib/libd.so.meta_lic testdata/reciprocal/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/application.meta_lic testdata/reciprocal/application.meta_lic testdata/reciprocal/application.meta_lic notice",
+				"testdata/reciprocal/application.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/bin/bin3.meta_lic testdata/reciprocal/bin/bin3.meta_lic testdata/reciprocal/bin/bin3.meta_lic notice",
+				"testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic testdata/reciprocal/lib/libb.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/bin/bin1.meta_lic notice",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/bin/bin1.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+				"testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic testdata/reciprocal/lib/liba.so.meta_lic reciprocal",
+				"testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic testdata/reciprocal/lib/libc.a.meta_lic reciprocal",
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{
+				"testdata/reciprocal/lib/libd.so.meta_lic testdata/reciprocal/lib/libd.so.meta_lic testdata/reciprocal/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic notice",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic notice",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic notice",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic notice",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/highest.apex.meta_lic testdata/restricted/highest.apex.meta_lic notice",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+				"testdata/restricted/highest.apex.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+				"testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin1.meta_lic bin/bin1.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"bin/bin2.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libd.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"highest.apex.meta_lic lib/libd.so.meta_lic lib/libb.so.meta_lic restricted",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"lib/libc.a.meta_lic lib/libc.a.meta_lic lib/liba.so.meta_lic restricted",
+				"lib/libc.a.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"lib/libd.so.meta_lic lib/libd.so.meta_lic lib/libb.so.meta_lic restricted",
+				"lib/libd.so.meta_lic lib/libd.so.meta_lic lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"bin/bin2.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin1.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []string{},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/liba.so.meta_lic restricted",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"bin/bin2.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin1.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/liba.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic reciprocal",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic restricted",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice lib/liba.so.meta_lic:restricted restricted",
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:restricted lib/liba.so.meta_lic:restricted restricted",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:reciprocal lib/liba.so.meta_lic:restricted restricted",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal reciprocal",
+				"bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"bin/bin2.meta_lic:notice lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted restricted",
+				"bin/bin2.meta_lic:notice lib/libd.so.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice lib/liba.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice bin/bin2.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice highest.apex.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice lib/liba.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:restricted lib/liba.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice lib/libc.a.meta_lic:reciprocal lib/liba.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal reciprocal",
+				"highest.apex.meta_lic:notice lib/libd.so.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"lib/liba.so.meta_lic:restricted lib/liba.so.meta_lic:restricted lib/liba.so.meta_lic:restricted restricted",
+				"lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted restricted",
+				"lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal lib/liba.so.meta_lic:restricted restricted",
+				"lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal lib/libc.a.meta_lic:reciprocal reciprocal",
+				"lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice notice",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic notice",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic notice",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic notice",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/bin/bin2.meta_lic notice",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/bin/bin2.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/container.zip.meta_lic testdata/restricted/container.zip.meta_lic notice",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/container.zip.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/container.zip.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+				"testdata/restricted/container.zip.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+				"testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/application.meta_lic testdata/restricted/application.meta_lic testdata/restricted/application.meta_lic notice",
+				"testdata/restricted/application.meta_lic testdata/restricted/application.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/application.meta_lic testdata/restricted/application.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/application.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/application.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/application.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/bin/bin3.meta_lic testdata/restricted/bin/bin3.meta_lic testdata/restricted/bin/bin3.meta_lic restricted",
+				"testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+				"testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic testdata/restricted/lib/libb.so.meta_lic restricted",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic notice",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/bin/bin1.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+				"testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/liba.so.meta_lic restricted",
+				"testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic testdata/restricted/lib/libc.a.meta_lic reciprocal",
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{
+				"testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic testdata/restricted/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic notice",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic notice",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/highest.apex.meta_lic testdata/proprietary/highest.apex.meta_lic notice",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/highest.apex.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/highest.apex.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/"},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic by_exception_only:proprietary",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic by_exception_only:proprietary",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic by_exception_only:proprietary",
+				"bin/bin2.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libd.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic by_exception_only:proprietary",
+				"highest.apex.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic by_exception_only:proprietary",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic by_exception_only:proprietary",
+				"highest.apex.meta_lic lib/libd.so.meta_lic lib/libb.so.meta_lic restricted",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic by_exception_only:proprietary",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"lib/libc.a.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic by_exception_only:proprietary",
+				"lib/libd.so.meta_lic lib/libd.so.meta_lic lib/libb.so.meta_lic restricted",
+				"lib/libd.so.meta_lic lib/libd.so.meta_lic lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic bin/bin1.meta_lic bin/bin1.meta_lic notice",
+				"highest.apex.meta_lic highest.apex.meta_lic highest.apex.meta_lic notice",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []string{
+				"bin/bin2.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic proprietary",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic proprietary",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic proprietary",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic proprietary",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic proprietary",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic proprietary",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic proprietary",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []string{
+				"bin/bin1.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic proprietary",
+				"bin/bin1.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic proprietary",
+				"bin/bin2.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic proprietary",
+				"bin/bin2.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"bin/bin2.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic bin/bin2.meta_lic bin/bin2.meta_lic proprietary",
+				"highest.apex.meta_lic bin/bin2.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic highest.apex.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic proprietary",
+				"highest.apex.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+				"highest.apex.meta_lic lib/libc.a.meta_lic lib/libc.a.meta_lic proprietary",
+				"lib/liba.so.meta_lic lib/liba.so.meta_lic lib/liba.so.meta_lic proprietary",
+				"lib/libb.so.meta_lic lib/libb.so.meta_lic lib/libb.so.meta_lic restricted",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/", labelConditions: true},
+			expectedOut: []string{
+				"bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"bin/bin1.meta_lic:notice lib/liba.so.meta_lic:by_exception_only:proprietary lib/liba.so.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"bin/bin1.meta_lic:notice lib/libc.a.meta_lic:by_exception_only:proprietary lib/libc.a.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"bin/bin2.meta_lic:by_exception_only:proprietary bin/bin2.meta_lic:by_exception_only:proprietary bin/bin2.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"bin/bin2.meta_lic:by_exception_only:proprietary bin/bin2.meta_lic:by_exception_only:proprietary lib/libb.so.meta_lic:restricted restricted",
+				"bin/bin2.meta_lic:by_exception_only:proprietary lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted restricted",
+				"bin/bin2.meta_lic:by_exception_only:proprietary lib/libd.so.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice bin/bin1.meta_lic:notice bin/bin1.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:by_exception_only:proprietary bin/bin2.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"highest.apex.meta_lic:notice bin/bin2.meta_lic:by_exception_only:proprietary lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice highest.apex.meta_lic:notice notice",
+				"highest.apex.meta_lic:notice highest.apex.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice lib/liba.so.meta_lic:by_exception_only:proprietary lib/liba.so.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"highest.apex.meta_lic:notice lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted restricted",
+				"highest.apex.meta_lic:notice lib/libc.a.meta_lic:by_exception_only:proprietary lib/libc.a.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"highest.apex.meta_lic:notice lib/libd.so.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"lib/liba.so.meta_lic:by_exception_only:proprietary lib/liba.so.meta_lic:by_exception_only:proprietary lib/liba.so.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted lib/libb.so.meta_lic:restricted restricted",
+				"lib/libc.a.meta_lic:by_exception_only:proprietary lib/libc.a.meta_lic:by_exception_only:proprietary lib/libc.a.meta_lic:by_exception_only:proprietary by_exception_only:proprietary",
+				"lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice lib/libb.so.meta_lic:restricted restricted",
+				"lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice lib/libd.so.meta_lic:notice notice",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic notice",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic notice",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/bin/bin2.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/bin/bin2.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/container.zip.meta_lic testdata/proprietary/container.zip.meta_lic notice",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/container.zip.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/container.zip.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic notice",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/application.meta_lic testdata/proprietary/application.meta_lic testdata/proprietary/application.meta_lic notice",
+				"testdata/proprietary/application.meta_lic testdata/proprietary/application.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/application.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/application.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/application.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/bin/bin3.meta_lic testdata/proprietary/bin/bin3.meta_lic testdata/proprietary/bin/bin3.meta_lic restricted",
+				"testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+				"testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic testdata/proprietary/lib/libb.so.meta_lic restricted",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/bin/bin1.meta_lic notice",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/bin/bin1.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic testdata/proprietary/lib/liba.so.meta_lic by_exception_only:proprietary",
+				"testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic testdata/proprietary/lib/libc.a.meta_lic by_exception_only:proprietary",
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []string{
+				"testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic testdata/proprietary/lib/libd.so.meta_lic notice",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
+			expectedOut := &bytes.Buffer{}
+			for _, eo := range tt.expectedOut {
+				expectedOut.WriteString(eo)
+				expectedOut.WriteString("\n")
+			}
+
+			stdout := &bytes.Buffer{}
+			stderr := &bytes.Buffer{}
+
+			rootFiles := make([]string, 0, len(tt.roots))
+			for _, r := range tt.roots {
+				rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
+			}
+			err := dumpResolutions(&tt.ctx, stdout, stderr, rootFiles...)
+			if err != nil {
+				t.Fatalf("dumpresolutions: error = %v, stderr = %v", err, stderr)
+				return
+			}
+			if stderr.Len() > 0 {
+				t.Errorf("dumpresolutions: gotStderr = %v, want none", stderr)
+			}
+			out := stdout.String()
+			expected := expectedOut.String()
+			if out != expected {
+				outList := strings.Split(out, "\n")
+				expectedList := strings.Split(expected, "\n")
+				startLine := 0
+				for len(outList) > startLine && len(expectedList) > startLine && outList[startLine] == expectedList[startLine] {
+					startLine++
+				}
+				t.Errorf("listshare: gotStdout = %v, want %v, somewhere near line %d Stdout = %v, want %v",
+					out, expected, startLine+1, outList[startLine], expectedList[startLine])
+			}
+		})
+	}
+}
+
+type testContext struct {
+	nextNode int
+	nodes    map[string]string
+}
+
+type matcher interface {
+	matchString(*testContext) string
+	typeString() string
+}
+
+type targetMatcher struct {
+	target     string
+	conditions []string
+}
+
+func (tm *targetMatcher) matchString(ctx *testContext) string {
+	m := tm.target
+	if len(tm.conditions) > 0 {
+		m += "\\n" + strings.Join(tm.conditions, "\\n")
+	}
+	m = ctx.nodes[tm.target] + " [label=\"" + m + "\"];"
+	return m
+}
+
+func (tm *targetMatcher) typeString() string {
+	return "target"
+}
+
+type resolutionMatcher struct {
+	appliesTo  string
+	actsOn     string
+	origin     string
+	conditions []string
+}
+
+func (rm *resolutionMatcher) matchString(ctx *testContext) string {
+	return ctx.nodes[rm.appliesTo] + " -> " + ctx.nodes[rm.actsOn] + "; " +
+		ctx.nodes[rm.actsOn] + " -> " + ctx.nodes[rm.origin] +
+		" [label=\"" + strings.Join(rm.conditions, "\\n") + "\"];"
+}
+
+func (rm *resolutionMatcher) typeString() string {
+	return "resolution"
+}
+
+type getMatcher func(*testContext) matcher
+
+func matchTarget(target string, conditions ...string) getMatcher {
+	return func(ctx *testContext) matcher {
+		ctx.nodes[target] = fmt.Sprintf("n%d", ctx.nextNode)
+		ctx.nextNode++
+		return &targetMatcher{target, append([]string{}, conditions...)}
+	}
+}
+
+func matchResolution(appliesTo, actsOn, origin string, conditions ...string) getMatcher {
+	return func(ctx *testContext) matcher {
+		if _, ok := ctx.nodes[appliesTo]; !ok {
+			ctx.nodes[appliesTo] = fmt.Sprintf("unknown%d", ctx.nextNode)
+			ctx.nextNode++
+		}
+		if _, ok := ctx.nodes[actsOn]; !ok {
+			ctx.nodes[actsOn] = fmt.Sprintf("unknown%d", ctx.nextNode)
+			ctx.nextNode++
+		}
+		if _, ok := ctx.nodes[origin]; !ok {
+			ctx.nodes[origin] = fmt.Sprintf("unknown%d", ctx.nextNode)
+			ctx.nextNode++
+		}
+		return &resolutionMatcher{appliesTo, actsOn, origin, append([]string{}, conditions...)}
+	}
+}
+
+func Test_graphviz(t *testing.T) {
+	tests := []struct {
+		condition   string
+		name        string
+		roots       []string
+		ctx         context
+		expectedOut []getMatcher
+	}{
+		{
+			condition: "firstparty",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/bin/bin1.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libc.a.meta_lic"),
+				matchTarget("testdata/firstparty/bin/bin2.meta_lic"),
+				matchTarget("testdata/firstparty/highest.apex.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libb.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/highest.apex.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/highest.apex.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/highest.apex.meta_lic",
+					"testdata/firstparty/highest.apex.meta_lic",
+					"testdata/firstparty/highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/highest.apex.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/highest.apex.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/highest.apex.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/firstparty/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "firstparty",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/firstparty/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "notice"),
+				matchTarget("lib/libc.a.meta_lic", "notice"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/libb.so.meta_lic", "notice"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/bin/bin1.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libc.a.meta_lic"),
+				matchTarget("testdata/firstparty/bin/bin2.meta_lic"),
+				matchTarget("testdata/firstparty/container.zip.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libb.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/container.zip.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/container.zip.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"testdata/firstparty/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/container.zip.meta_lic",
+					"testdata/firstparty/container.zip.meta_lic",
+					"testdata/firstparty/container.zip.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/container.zip.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/container.zip.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/container.zip.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/application.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/bin/bin3.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libb.so.meta_lic"),
+				matchResolution(
+					"testdata/firstparty/application.meta_lic",
+					"testdata/firstparty/application.meta_lic",
+					"testdata/firstparty/application.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/application.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin3.meta_lic",
+					"testdata/firstparty/bin/bin3.meta_lic",
+					"testdata/firstparty/bin/bin3.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"testdata/firstparty/lib/libb.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/bin/bin1.meta_lic"),
+				matchTarget("testdata/firstparty/lib/liba.so.meta_lic"),
+				matchTarget("testdata/firstparty/lib/libc.a.meta_lic"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/bin/bin1.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"testdata/firstparty/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"testdata/firstparty/lib/libc.a.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "firstparty",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/firstparty/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"testdata/firstparty/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/bin/bin1.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libc.a.meta_lic"),
+				matchTarget("testdata/notice/bin/bin2.meta_lic"),
+				matchTarget("testdata/notice/highest.apex.meta_lic"),
+				matchTarget("testdata/notice/lib/libb.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin2.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/highest.apex.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/highest.apex.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/highest.apex.meta_lic",
+					"testdata/notice/highest.apex.meta_lic",
+					"testdata/notice/highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/highest.apex.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/highest.apex.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/highest.apex.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libd.so.meta_lic",
+					"testdata/notice/lib/libd.so.meta_lic",
+					"testdata/notice/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/notice/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "notice",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/notice/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "notice"),
+				matchTarget("lib/libc.a.meta_lic", "notice"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/libb.so.meta_lic", "notice"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/bin/bin1.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libc.a.meta_lic"),
+				matchTarget("testdata/notice/bin/bin2.meta_lic"),
+				matchTarget("testdata/notice/container.zip.meta_lic"),
+				matchTarget("testdata/notice/lib/libb.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin2.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/container.zip.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/container.zip.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"testdata/notice/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/container.zip.meta_lic",
+					"testdata/notice/container.zip.meta_lic",
+					"testdata/notice/container.zip.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/container.zip.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/container.zip.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/container.zip.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libd.so.meta_lic",
+					"testdata/notice/lib/libd.so.meta_lic",
+					"testdata/notice/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/application.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/bin/bin3.meta_lic"),
+				matchTarget("testdata/notice/lib/libb.so.meta_lic"),
+				matchResolution(
+					"testdata/notice/application.meta_lic",
+					"testdata/notice/application.meta_lic",
+					"testdata/notice/application.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/application.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin3.meta_lic",
+					"testdata/notice/bin/bin3.meta_lic",
+					"testdata/notice/bin/bin3.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"testdata/notice/lib/libb.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/bin/bin1.meta_lic"),
+				matchTarget("testdata/notice/lib/liba.so.meta_lic"),
+				matchTarget("testdata/notice/lib/libc.a.meta_lic"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/bin/bin1.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"testdata/notice/lib/liba.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"testdata/notice/lib/libc.a.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "notice",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/notice/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/notice/lib/libd.so.meta_lic",
+					"testdata/notice/lib/libd.so.meta_lic",
+					"testdata/notice/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/bin/bin1.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libc.a.meta_lic"),
+				matchTarget("testdata/reciprocal/bin/bin2.meta_lic"),
+				matchTarget("testdata/reciprocal/highest.apex.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libb.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/highest.apex.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/reciprocal/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/reciprocal/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "reciprocal"),
+				matchTarget("lib/libc.a.meta_lic", "reciprocal"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchTarget("lib/libb.so.meta_lic", "notice"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/bin/bin1.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libc.a.meta_lic"),
+				matchTarget("testdata/reciprocal/bin/bin2.meta_lic"),
+				matchTarget("testdata/reciprocal/container.zip.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libb.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/container.zip.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/container.zip.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"testdata/reciprocal/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/container.zip.meta_lic",
+					"testdata/reciprocal/container.zip.meta_lic",
+					"testdata/reciprocal/container.zip.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/container.zip.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/container.zip.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/container.zip.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/application.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/bin/bin3.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libb.so.meta_lic"),
+				matchResolution(
+					"testdata/reciprocal/application.meta_lic",
+					"testdata/reciprocal/application.meta_lic",
+					"testdata/reciprocal/application.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/application.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin3.meta_lic",
+					"testdata/reciprocal/bin/bin3.meta_lic",
+					"testdata/reciprocal/bin/bin3.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"testdata/reciprocal/lib/libb.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/bin/bin1.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/liba.so.meta_lic"),
+				matchTarget("testdata/reciprocal/lib/libc.a.meta_lic"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/bin/bin1.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"testdata/reciprocal/lib/liba.so.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"testdata/reciprocal/lib/libc.a.meta_lic",
+					"reciprocal"),
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/reciprocal/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"testdata/reciprocal/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/bin/bin1.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libc.a.meta_lic"),
+				matchTarget("testdata/restricted/bin/bin2.meta_lic"),
+				matchTarget("testdata/restricted/lib/libb.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libd.so.meta_lic"),
+				matchTarget("testdata/restricted/highest.apex.meta_lic"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/restricted/highest.apex.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []getMatcher{},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/restricted/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/restricted/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "restricted"),
+				matchTarget("lib/libc.a.meta_lic", "reciprocal"),
+				matchTarget("bin/bin2.meta_lic", "notice"),
+				matchTarget("lib/libb.so.meta_lic", "restricted"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/bin/bin1.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libc.a.meta_lic"),
+				matchTarget("testdata/restricted/bin/bin2.meta_lic"),
+				matchTarget("testdata/restricted/lib/libb.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libd.so.meta_lic"),
+				matchTarget("testdata/restricted/container.zip.meta_lic"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/bin/bin2.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/container.zip.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/restricted/container.zip.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/application.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libb.so.meta_lic"),
+				matchTarget("testdata/restricted/bin/bin3.meta_lic"),
+				matchResolution(
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/application.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/application.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin3.meta_lic",
+					"testdata/restricted/bin/bin3.meta_lic",
+					"testdata/restricted/bin/bin3.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"testdata/restricted/lib/libb.so.meta_lic",
+					"restricted"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/bin/bin1.meta_lic"),
+				matchTarget("testdata/restricted/lib/liba.so.meta_lic"),
+				matchTarget("testdata/restricted/lib/libc.a.meta_lic"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/bin/bin1.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+				matchResolution(
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/liba.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"testdata/restricted/lib/libc.a.meta_lic",
+					"reciprocal"),
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/restricted/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"testdata/restricted/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/bin/bin1.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libc.a.meta_lic"),
+				matchTarget("testdata/proprietary/bin/bin2.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libb.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libd.so.meta_lic"),
+				matchTarget("testdata/proprietary/highest.apex.meta_lic"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/highest.apex.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/"},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("lib/libd.so.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_notice",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"notice"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_share",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"proprietary"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"proprietary"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_share_private",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx: context{
+				conditions:  []string{"reciprocal", "restricted", "proprietary"},
+				stripPrefix: "testdata/proprietary/",
+			},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic"),
+				matchTarget("lib/liba.so.meta_lic"),
+				matchTarget("lib/libc.a.meta_lic"),
+				matchTarget("bin/bin2.meta_lic"),
+				matchTarget("lib/libb.so.meta_lic"),
+				matchTarget("highest.apex.meta_lic"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"proprietary"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex_trimmed_labelled",
+			roots:     []string{"highest.apex.meta_lic"},
+			ctx:       context{stripPrefix: "testdata/proprietary/", labelConditions: true},
+			expectedOut: []getMatcher{
+				matchTarget("bin/bin1.meta_lic", "notice"),
+				matchTarget("lib/liba.so.meta_lic", "by_exception_only", "proprietary"),
+				matchTarget("lib/libc.a.meta_lic", "by_exception_only", "proprietary"),
+				matchTarget("bin/bin2.meta_lic", "by_exception_only", "proprietary"),
+				matchTarget("lib/libb.so.meta_lic", "restricted"),
+				matchTarget("lib/libd.so.meta_lic", "notice"),
+				matchTarget("highest.apex.meta_lic", "notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"bin/bin1.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"bin/bin2.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin1.meta_lic",
+					"bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"bin/bin2.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"notice"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"highest.apex.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/bin/bin1.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libc.a.meta_lic"),
+				matchTarget("testdata/proprietary/bin/bin2.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libb.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libd.so.meta_lic"),
+				matchTarget("testdata/proprietary/container.zip.meta_lic"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/bin/bin2.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/container.zip.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/container.zip.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/application.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libb.so.meta_lic"),
+				matchTarget("testdata/proprietary/bin/bin3.meta_lic"),
+				matchResolution(
+					"testdata/proprietary/application.meta_lic",
+					"testdata/proprietary/application.meta_lic",
+					"testdata/proprietary/application.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/application.meta_lic",
+					"testdata/proprietary/application.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/application.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/application.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/application.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/bin/bin3.meta_lic",
+					"testdata/proprietary/bin/bin3.meta_lic",
+					"testdata/proprietary/bin/bin3.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+				matchResolution(
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"testdata/proprietary/lib/libb.so.meta_lic",
+					"restricted"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/bin/bin1.meta_lic"),
+				matchTarget("testdata/proprietary/lib/liba.so.meta_lic"),
+				matchTarget("testdata/proprietary/lib/libc.a.meta_lic"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"notice"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/bin/bin1.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"testdata/proprietary/lib/liba.so.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+				matchResolution(
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"testdata/proprietary/lib/libc.a.meta_lic",
+					"by_exception_only",
+					"proprietary"),
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "library",
+			roots:     []string{"lib/libd.so.meta_lic"},
+			expectedOut: []getMatcher{
+				matchTarget("testdata/proprietary/lib/libd.so.meta_lic"),
+				matchResolution(
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"testdata/proprietary/lib/libd.so.meta_lic",
+					"notice"),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
+			ctx := &testContext{0, make(map[string]string)}
+
+			expectedOut := &bytes.Buffer{}
+			for _, eo := range tt.expectedOut {
+				m := eo(ctx)
+				expectedOut.WriteString(m.matchString(ctx))
+				expectedOut.WriteString("\n")
+			}
+
+			stdout := &bytes.Buffer{}
+			stderr := &bytes.Buffer{}
+
+			rootFiles := make([]string, 0, len(tt.roots))
+			for _, r := range tt.roots {
+				rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
+			}
+			tt.ctx.graphViz = true
+			err := dumpResolutions(&tt.ctx, stdout, stderr, rootFiles...)
+
+			if err != nil {
+				t.Fatalf("dumpresolutions: error = %v, stderr = %v", err, stderr)
+				return
+			}
+			if stderr.Len() > 0 {
+				t.Errorf("dumpresolutions: gotStderr = %v, want none", stderr)
+			}
+			outList := strings.Split(stdout.String(), "\n")
+			outLine := 0
+			if outList[outLine] != "strict digraph {" {
+				t.Errorf("dumpresolutions: got 1st line %v, want strict digraph {")
+			}
+			outLine++
+			if strings.HasPrefix(strings.TrimLeft(outList[outLine], " \t"), "rankdir") {
+				outLine++
+			}
+			endOut := len(outList)
+			for endOut > 0 && strings.TrimLeft(outList[endOut-1], " \t") == "" {
+				endOut--
+			}
+			if outList[endOut-1] != "}" {
+				t.Errorf("dumpresolutions: got last line %v, want }", outList[endOut-1])
+			}
+			endOut--
+			if strings.HasPrefix(strings.TrimLeft(outList[endOut-1], " \t"), "{rank=same") {
+				endOut--
+			}
+			expectedList := strings.Split(expectedOut.String(), "\n")
+			for len(expectedList) > 0 && expectedList[len(expectedList)-1] == "" {
+				expectedList = expectedList[0 : len(expectedList)-1]
+			}
+			matchLine := 0
+
+			for outLine < endOut && matchLine < len(expectedList) && strings.TrimLeft(outList[outLine], " \t") == expectedList[matchLine] {
+				outLine++
+				matchLine++
+			}
+			if outLine < endOut || matchLine < len(expectedList) {
+				if outLine >= endOut {
+					t.Errorf("dumpresolutions: missing lines at end of graph, want %d lines %v", len(expectedList)-matchLine, strings.Join(expectedList[matchLine:], "\n"))
+				} else if matchLine >= len(expectedList) {
+					t.Errorf("dumpresolutions: unexpected lines at end of graph starting line %d, got %v, want nothing", outLine+1, strings.Join(outList[outLine:], "\n"))
+				} else {
+					t.Errorf("dumpresolutions: at line %d, got %v, want %v", outLine+1, strings.Join(outList[outLine:], "\n"), strings.Join(expectedList[matchLine:], "\n"))
+				}
+			}
+		})
+	}
+}
diff --git a/tools/compliance/cmd/listshare.go b/tools/compliance/cmd/listshare.go
new file mode 100644
index 0000000..bba2308
--- /dev/null
+++ b/tools/compliance/cmd/listshare.go
@@ -0,0 +1,124 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"compliance"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"sort"
+)
+
+func init() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, `Usage: %s file.meta_lic {file.meta_lic...}
+
+Outputs a csv file with 1 project per line in the first field followed
+by target:condition pairs describing why the project must be shared.
+
+Each target is the path to a generated license metadata file for a
+Soong module or Make target, and the license condition is either
+restricted (e.g. GPL) or reciprocal (e.g. MPL).
+`, filepath.Base(os.Args[0]))
+	}
+}
+
+var (
+	failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
+	failNoLicenses = fmt.Errorf("No licenses found")
+)
+
+func main() {
+	flag.Parse()
+
+	// Must specify at least one root target.
+	if flag.NArg() == 0 {
+		flag.Usage()
+		os.Exit(2)
+	}
+
+	err := listShare(os.Stdout, os.Stderr, flag.Args()...)
+	if err != nil {
+		if err == failNoneRequested {
+			flag.Usage()
+		}
+		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
+		os.Exit(1)
+	}
+	os.Exit(0)
+}
+
+// listShare implements the listshare utility.
+func listShare(stdout, stderr io.Writer, files ...string) error {
+	// Must be at least one root file.
+	if len(files) < 1 {
+		return failNoneRequested
+	}
+
+	// Read the license graph from the license metadata files (*.meta_lic).
+	licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+	if err != nil {
+		return fmt.Errorf("Unable to read license metadata file(s) %q: %v\n", files, err)
+	}
+	if licenseGraph == nil {
+		return failNoLicenses
+	}
+
+	// shareSource contains all source-sharing resolutions.
+	shareSource := compliance.ResolveSourceSharing(licenseGraph)
+
+	// Group the resolutions by project.
+	presolution := make(map[string]*compliance.LicenseConditionSet)
+	for _, target := range shareSource.AttachesTo() {
+		rl := shareSource.Resolutions(target)
+		sort.Sort(rl)
+		for _, r := range rl {
+			for _, p := range r.ActsOn().Projects() {
+				if _, ok := presolution[p]; !ok {
+					presolution[p] = r.Resolves().Copy()
+					continue
+				}
+				presolution[p].AddSet(r.Resolves())
+			}
+		}
+	}
+
+	// Sort the projects for repeatability/stability.
+	projects := make([]string, 0, len(presolution))
+	for p := range presolution {
+		projects = append(projects, p)
+	}
+	sort.Strings(projects)
+
+	// Output the sorted projects and the source-sharing license conditions that each project resolves.
+	for _, p := range projects {
+		fmt.Fprintf(stdout, "%s", p)
+
+		// Sort the conditions for repeatability/stability.
+		conditions := presolution[p].AsList()
+		sort.Sort(conditions)
+
+		// Output the sorted origin:condition pairs.
+		for _, lc := range conditions {
+			fmt.Fprintf(stdout, ",%s:%s", lc.Origin().Name(), lc.Name())
+		}
+		fmt.Fprintf(stdout, "\n")
+	}
+
+	return nil
+}
diff --git a/tools/compliance/cmd/listshare_test.go b/tools/compliance/cmd/listshare_test.go
new file mode 100644
index 0000000..b4847e3
--- /dev/null
+++ b/tools/compliance/cmd/listshare_test.go
@@ -0,0 +1,405 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+)
+
+func Test(t *testing.T) {
+	type projectShare struct {
+		project    string
+		conditions []string
+	}
+	tests := []struct {
+		condition   string
+		name        string
+		roots       []string
+		expectedOut []projectShare
+	}{
+		{
+			condition:   "firstparty",
+			name:        "apex",
+			roots:       []string{"highest.apex.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "firstparty",
+			name:        "container",
+			roots:       []string{"container.zip.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "firstparty",
+			name:        "application",
+			roots:       []string{"application.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "firstparty",
+			name:        "binary",
+			roots:       []string{"bin/bin1.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "firstparty",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "notice",
+			name:        "apex",
+			roots:       []string{"highest.apex.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "notice",
+			name:        "container",
+			roots:       []string{"container.zip.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "notice",
+			name:        "application",
+			roots:       []string{"application.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "notice",
+			name:        "binary",
+			roots:       []string{"bin/bin1.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "notice",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition: "reciprocal",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "device/library",
+					conditions: []string{"lib/liba.so.meta_lic:reciprocal"},
+				},
+				{
+					project: "static/library",
+					conditions: []string{
+						"lib/libc.a.meta_lic:reciprocal",
+					},
+				},
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "device/library",
+					conditions: []string{"lib/liba.so.meta_lic:reciprocal"},
+				},
+				{
+					project: "static/library",
+					conditions: []string{
+						"lib/libc.a.meta_lic:reciprocal",
+					},
+				},
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "device/library",
+					conditions: []string{"lib/liba.so.meta_lic:reciprocal"},
+				},
+			},
+		},
+		{
+			condition: "reciprocal",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project: "device/library",
+					conditions: []string{
+						"lib/liba.so.meta_lic:reciprocal",
+					},
+				},
+				{
+					project: "static/library",
+					conditions: []string{
+						"lib/libc.a.meta_lic:reciprocal",
+					},
+				},
+			},
+		},
+		{
+			condition:   "reciprocal",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition: "restricted",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "base/library",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project:    "device/library",
+					conditions: []string{"lib/liba.so.meta_lic:restricted"},
+				},
+				{
+					project:    "dynamic/binary",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project: "highest/apex",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+						"lib/libb.so.meta_lic:restricted",
+					},
+				},
+				{
+					project: "static/binary",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+					},
+				},
+				{
+					project: "static/library",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+						"lib/libc.a.meta_lic:reciprocal",
+					},
+				},
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "base/library",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project: "container/zip",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+						"lib/libb.so.meta_lic:restricted",
+					},
+				},
+				{
+					project:    "device/library",
+					conditions: []string{"lib/liba.so.meta_lic:restricted"},
+				},
+				{
+					project:    "dynamic/binary",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project: "static/binary",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+					},
+				},
+				{
+					project: "static/library",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+						"lib/libc.a.meta_lic:reciprocal",
+					},
+				},
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project: "device/library",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+						"lib/libb.so.meta_lic:restricted",
+					},
+				},
+				{
+					project: "distributable/application",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+						"lib/libb.so.meta_lic:restricted",
+					},
+				},
+			},
+		},
+		{
+			condition: "restricted",
+			name:      "binary",
+			roots:     []string{"bin/bin1.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project: "device/library",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+					},
+				},
+				{
+					project: "static/binary",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+					},
+				},
+				{
+					project: "static/library",
+					conditions: []string{
+						"lib/liba.so.meta_lic:restricted",
+						"lib/libc.a.meta_lic:reciprocal",
+					},
+				},
+			},
+		},
+		{
+			condition:   "restricted",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition: "proprietary",
+			name:      "apex",
+			roots:     []string{"highest.apex.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "base/library",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project:    "dynamic/binary",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project:    "highest/apex",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "container",
+			roots:     []string{"container.zip.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "base/library",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project:    "container/zip",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project:    "dynamic/binary",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+			},
+		},
+		{
+			condition: "proprietary",
+			name:      "application",
+			roots:     []string{"application.meta_lic"},
+			expectedOut: []projectShare{
+				{
+					project:    "device/library",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+				{
+					project:    "distributable/application",
+					conditions: []string{"lib/libb.so.meta_lic:restricted"},
+				},
+			},
+		},
+		{
+			condition:   "proprietary",
+			name:        "binary",
+			roots:       []string{"bin/bin1.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+		{
+			condition:   "proprietary",
+			name:        "library",
+			roots:       []string{"lib/libd.so.meta_lic"},
+			expectedOut: []projectShare{},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
+			expectedOut := &bytes.Buffer{}
+			for _, p := range tt.expectedOut {
+				expectedOut.WriteString(p.project)
+				for _, lc := range p.conditions {
+					expectedOut.WriteString(",")
+					expectedOut.WriteString("testdata/")
+					expectedOut.WriteString(tt.condition)
+					expectedOut.WriteString("/")
+					expectedOut.WriteString(lc)
+				}
+				expectedOut.WriteString("\n")
+			}
+
+			stdout := &bytes.Buffer{}
+			stderr := &bytes.Buffer{}
+
+			rootFiles := make([]string, 0, len(tt.roots))
+			for _, r := range tt.roots {
+				rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
+			}
+			err := listShare(stdout, stderr, rootFiles...)
+			if err != nil {
+				t.Fatalf("listshare: error = %v, stderr = %v", err, stderr)
+				return
+			}
+			if stderr.Len() > 0 {
+				t.Errorf("listshare: gotStderr = %v, want none", stderr)
+			}
+			out := stdout.String()
+			expected := expectedOut.String()
+			if out != expected {
+				outList := strings.Split(out, "\n")
+				expectedList := strings.Split(expected, "\n")
+				startLine := 0
+				for len(outList) > startLine && len(expectedList) > startLine && outList[startLine] == expectedList[startLine] {
+					startLine++
+				}
+				t.Errorf("listshare: gotStdout = %v, want %v, somewhere near line %d Stdout = %v, want %v",
+					out, expected, startLine+1, outList[startLine], expectedList[startLine])
+			}
+		})
+	}
+}
diff --git a/tools/compliance/cmd/testdata/README.md b/tools/compliance/cmd/testdata/README.md
new file mode 100644
index 0000000..9872c04
--- /dev/null
+++ b/tools/compliance/cmd/testdata/README.md
@@ -0,0 +1,321 @@
+## Test data
+
+Each directory under testdata/ defines a similar build graph.
+All have the same structure, but different versions of the graph have different
+license metadata.
+
+### Testdata build graph structure:
+
+The structure is meant to simulate some common scenarios:
+
+*   a `lib/` directory with some libraries
+*   a `bin/` directory with some executables
+*   one of the binaries, `bin3`, is a toolchain executable like a compiler
+*   an `application` built with the `bin3` compiler and linking a couple libraries
+*   a pure aggregation `continer.zip` that merely bundles files together, and
+*   an apex file (more like an apk file) with some binaries and libraries.
+
+The testdata starts with a `firstparty/` version containng only first-party
+licenses, and each subsequent directory introduces more restrictive conditions:
+
+*   `notice/` starts with `firstparty/` adds third-party notice conditions
+*   `reciprocal/` starts with `notice/` and adds some reciprocal conditions
+*   `restricted/` starts with `reciprocal/` and adds some restricted conditions
+*   `proprietary/` starts with `restricted/` and add some privacy conditions
+
+#### a `lib/` directory with some libraries
+
+```dot
+strict digraph {
+	liba [label="lib/liba.so.meta_lic"];
+	libb [label="lib/libb.so.meta_lic"];
+	libc [label="lib/libc.a.meta_lic"];
+	libd [label="lib/libd.so.meta_lic"];
+}
+```
+
+#### a `bin/` directory with some executables
+
+strict digraph {
+	rankdir=LR;
+	bin1 [label="bin/bin1.meta_lic"];
+	bin2 [label="bin/bin2.meta_lic"];
+	bin3 [label="bin/bin3.meta_lic\ntoolchain"];
+	liba [label="lib/liba.so.meta_lic"];
+	libb [label="lib/libb.so.meta_lic"];
+	libc [label="lib/libc.a.meta_lic"];
+	libd [label="lib/libd.so.meta_lic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	{rank=same; bin1 bin2 bin3}
+}
+
+#### an `application` built with the `bin3` compiler and linking a couple libraries
+
+```dot
+strict digraph {
+	rankdir=LR;
+	app [label="application.meta_lic"];
+	bin3 [label="bin/bin3.meta_lic"];
+	liba [label="lib/liba.so.meta_lic"];
+	libb [label="lib/libb.so.meta_lic"];
+	app -> bin3 [label="toolchain"];
+	app -> liba [label="static"];
+	app -> libb [label="dynamic"];
+	{rank=same; app}
+}
+```
+
+#### a pure aggregation `container.zip` that merely bundles files together
+
+strict digraph {
+	rankdir=LR;
+	bin1 [label="bin/bin1.meta_lic"];
+	bin2 [label="bin/bin2.meta_lic"];
+	container [label="container.zip.meta_lic"];
+	liba [label="lib/liba.so.meta_lic"];
+	libb [label="lib/libb.so.meta_lic"];
+	libc [label="lib/libc.a.meta_lic"];
+	libd [label="lib/libd.so.meta_lic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	container -> bin1 [label="static"];
+	container -> bin2 [label="static"];
+	container -> liba [label="static"];
+	container -> libb [label="static"];
+	{rank=same; container}
+}
+
+#### an apex file (more like an apk file) with some binaries and libraries
+
+```dot
+strict digraph {
+	rankdir=LR;
+	apex [label="highest.apex.meta_lic"];
+	bin1 [label="bin/bin1.meta_lic"];
+	bin2 [label="bin/bin2.meta_lic"];
+	bin3 [label="bin/bin3.meta_lic"];
+	liba [label="lib/liba.so.meta_lic"];
+	libb [label="lib/libb.so.meta_lic"];
+	libc [label="lib/libc.a.meta_lic"];
+	libd [label="lib/libd.so.meta_lic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	apex -> bin1 [label="static"];
+	apex -> bin2 [label="static"];
+	apex -> liba [label="static"];
+	apex -> libb [label="static"];
+	{rank=same; apex}
+}
+```
+
+#### the whole build graph
+
+```dot
+strict digraph {
+	rankdir=LR;
+	apex [label="highest.apex.meta_lic"];
+	app [label="application.meta_lic"];
+	bin1 [label="bin/bin1.meta_lic"];
+	bin2 [label="bin/bin2.meta_lic"];
+	bin3 [label="bin/bin3.meta_lic"];
+	container [label="container.zip.meta_lic"];
+	liba [label="lib/liba.so.meta_lic"];
+	libb [label="lib/libb.so.meta_lic"];
+	libc [label="lib/libc.a.meta_lic"];
+	libd [label="lib/libd.so.meta_lic"];
+	app -> bin3 [label="toolchain"];
+	app -> liba [label="static"];
+	app -> libb [label="dynamic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	container -> bin1 [label="static"];
+	container -> bin2 [label="static"];
+	container -> liba [label="static"];
+	container -> libb [label="static"];
+	apex -> bin1 [label="static"];
+	apex -> bin2 [label="static"];
+	apex -> liba [label="static"];
+	apex -> libb [label="static"];
+	{rank=same; app container apex}
+}
+```
+
+
+### firstparty/ testdata starts with all first-party licensing
+
+```dot
+strict digraph {
+	rankdir=LR;
+	app [label="firstparty/application.meta_lic"];
+	bin1 [label="firstparty/bin/bin1.meta_lic"];
+	bin2 [label="firstparty/bin/bin2.meta_lic"];
+	bin3 [label="firstparty/bin/bin3.meta_lic"];
+	container [label="firstparty/container.zip.meta_lic"];
+	apex [label="firstparty/highest.apex.meta_lic"];
+	liba [label="firstparty/lib/liba.so.meta_lic"];
+	libb [label="firstparty/lib/libb.so.meta_lic"];
+	libc [label="firstparty/lib/libc.a.meta_lic"];
+	lib [label="firstparty/lib/libd.so.meta_lic"];
+	app -> bin3 [label="toolchain"];
+	app -> liba [label="static"];
+	app -> libb [label="dynamic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	container -> bin1 [label="static"];
+	container -> bin2 [label="static"];
+	container -> liba [label="static"];
+	container -> libb [label="static"];
+	apex -> bin1 [label="static"];
+	apex -> bin2 [label="static"];
+	apex -> liba [label="static"];
+	apex -> libb [label="static"];
+	{rank=same; app container apex}
+}
+```
+
+### notice/ testdata introduces third-party notice conditions
+
+```dot
+strict digraph {
+	rankdir=LR;
+	app [label="notice/application.meta_lic"];
+	bin1 [label="notice/bin/bin1.meta_lic"];
+	bin2 [label="notice/bin/bin2.meta_lic"];
+	bin3 [label="notice/bin/bin3.meta_lic\nnotice"];
+	container [label="notice/container.zip.meta_lic"];
+	apex [label="notice/highest.apex.meta_lic"];
+	liba [label="notice/lib/liba.so.meta_lic\nnotice"];
+	libb [label="notice/lib/libb.so.meta_lic"];
+	libc [label="notice/lib/libc.a.meta_lic\nnotice"];
+	libd [label="notice/lib/libd.so.meta_lic\nnotice"];
+	app -> bin3 [label="toolchain"];
+	app -> liba [label="static"];
+	app -> libb [label="dynamic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	container -> bin1 [label="static"];
+	container -> bin2 [label="static"];
+	container -> liba [label="static"];
+	container -> libb [label="static"];
+	apex -> bin1 [label="static"];
+	apex -> bin2 [label="static"];
+	apex -> liba [label="static"];
+	apex -> libb [label="static"];
+	{rank=same; app container apex}
+}
+```
+
+### reciprocal/ testdata introduces third-party reciprocal sharing conditions
+
+```dot
+strict digraph {
+	rankdir=LR;
+	app [label="reciprocal/application.meta_lic"];
+	bin1 [label="reciprocal/bin/bin1.meta_lic"];
+	bin2 [label="reciprocal/bin/bin2.meta_lic"];
+	bin3 [label="reciprocal/bin/bin3.meta_lic\nnotice"];
+	container [label="reciprocal/container.zip.meta_lic"];
+	apex [label="reciprocal/highest.apex.meta_lic"];
+	liba [label="reciprocal/lib/liba.so.meta_lic\nreciprocal"];
+	libb [label="reciprocal/lib/libb.so.meta_lic"];
+	libc [label="reciprocal/lib/libc.a.meta_lic\nreciprocal"];
+	libd [label="reciprocal/lib/libd.so.meta_lic\nnotice"];
+	app -> bin3 [label="toolchain"];
+	app -> liba [label="static"];
+	app -> libb [label="dynamic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	container -> bin1 [label="static"];
+	container -> bin2 [label="static"];
+	container -> liba [label="static"];
+	container -> libb [label="static"];
+	apex -> bin1 [label="static"];
+	apex -> bin2 [label="static"];
+	apex -> liba [label="static"];
+	apex -> libb [label="static"];
+	{rank=same; app container apex}
+}
+```
+
+### restricted/ testdata introduces restricted source sharing conditions
+
+```dot
+strict digraph {
+	rankdir=LR;
+	app [label="restricted/application.meta_lic"];
+	bin1 [label="restricted/bin/bin1.meta_lic"];
+	bin2 [label="restricted/bin/bin2.meta_lic"];
+	bin3 [label="restricted/bin/bin3.meta_lic\nrestricted"];
+	container [label="restricted/container.zip.meta_lic"];
+	apex [label="restricted/highest.apex.meta_lic"];
+	liba [label="restricted/lib/liba.so.meta_lic\nrestricted"];
+	libb [label="restricted/lib/libb.so.meta_lic\nrestricted"];
+	libc [label="restricted/lib/libc.a.meta_lic\nreciprocal"];
+	libd [label="restricted/lib/libd.so.meta_lic\nnotice"];
+	app -> bin3 [label="toolchain"];
+	app -> liba [label="static"];
+	app -> libb [label="dynamic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	container -> bin1 [label="static"];
+	container -> bin2 [label="static"];
+	container -> liba [label="static"];
+	container -> libb [label="static"];
+	apex -> bin1 [label="static"];
+	apex -> bin2 [label="static"];
+	apex -> liba [label="static"];
+	apex -> libb [label="static"];
+	{rank=same; app container apex}
+}
+```
+
+### proprietary/ testdata introduces privacy conditions
+
+```dot
+strict digraph {
+	rankdir=LR;
+	app [label="proprietary/application.meta_lic"];
+	bin1 [label="proprietary/bin/bin1.meta_lic"];
+	bin2 [label="proprietary/bin/bin2.meta_lic\nby_exception_only\nproprietary"];
+	bin3 [label="proprietary/bin/bin3.meta_lic\nrestricted"];
+	container [label="proprietary/container.zip.meta_lic"];
+	apex [label="proprietary/highest.apex.meta_lic"];
+	liba [label="proprietary/lib/liba.so.meta_lic\nby_exception_only\nproprietary"];
+	libb [label="proprietary/lib/libb.so.meta_lic\nrestricted"];
+	libc [label="proprietary/lib/libc.a.meta_lic\nby_exception_only\nproprietary"];
+	libd [label="proprietary/lib/libd.so.meta_lic\nnotice"];
+	app -> bin3 [label="toolchain"];
+	app -> liba [label="static"];
+	app -> libb [label="dynamic"];
+	bin1 -> liba [label="static"];
+	bin1 -> libc [label="static"];
+	bin2 -> libb [label="dynamic"];
+	bin2 -> libd [label="dynamic"];
+	container -> bin1 [label="static"];
+	container -> bin2 [label="static"];
+	container -> liba [label="static"];
+	container -> libb [label="static"];
+	apex -> bin1 [label="static"];
+	apex -> bin2 [label="static"];
+	apex -> liba [label="static"];
+	apex -> libb [label="static"];
+	{rank=same; app container apex}
+}
+```
diff --git a/tools/compliance/cmd/testdata/firstparty/application.meta_lic b/tools/compliance/cmd/testdata/firstparty/application.meta_lic
new file mode 100644
index 0000000..58a1566
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/application.meta_lic
@@ -0,0 +1,24 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "distributable/application"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/application_intermediates/application"
+installed:  "out/target/product/fictional/bin/application"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin3"
+deps:  {
+  file:  "testdata/firstparty/bin/bin3.meta_lic"
+  annotations:  "toolchain"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/firstparty/bin/bin1.meta_lic b/tools/compliance/cmd/testdata/firstparty/bin/bin1.meta_lic
new file mode 100644
index 0000000..34d81d9
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/bin/bin1.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "static/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libc.a"
+deps:  {
+  file:  "testdata/firstparty/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/libc.a.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/firstparty/bin/bin2.meta_lic b/tools/compliance/cmd/testdata/firstparty/bin/bin2.meta_lic
new file mode 100644
index 0000000..6154421
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/bin/bin2.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "dynamic/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/lib/libd.so"
+deps:  {
+  file:  "testdata/firstparty/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/libd.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/firstparty/bin/bin3.meta_lic b/tools/compliance/cmd/testdata/firstparty/bin/bin3.meta_lic
new file mode 100644
index 0000000..9b7908e
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/bin/bin3.meta_lic
@@ -0,0 +1,9 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "standalone/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin3"
+installed:  "out/target/product/fictional/system/bin/bin3"
diff --git a/tools/compliance/cmd/testdata/firstparty/container.zip.meta_lic b/tools/compliance/cmd/testdata/firstparty/container.zip.meta_lic
new file mode 100644
index 0000000..350b123
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/container.zip.meta_lic
@@ -0,0 +1,36 @@
+package_name:  "Android"
+projects:  "container/zip"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/container_intermediates/container.zip"
+installed:  "out/target/product/fictional/data/container.zip"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/"
+  container_path:  ""
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/"
+  container_path:  ""
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/firstparty/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/firstparty/highest.apex.meta_lic b/tools/compliance/cmd/testdata/firstparty/highest.apex.meta_lic
new file mode 100644
index 0000000..53f81a2
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/highest.apex.meta_lic
@@ -0,0 +1,44 @@
+package_name:  "Android"
+projects:  "highest/apex"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/highest_intermediates/highest.apex"
+installed:  "out/target/product/fictional/system/apex/highest.apex"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/liba.so"
+  container_path:  "lib/liba.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/libb.so"
+  container_path:  "lib/libb.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin1"
+  container_path:  "bin/bin1"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin2"
+  container_path:  "bin/bin2"
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/firstparty/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/firstparty/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/firstparty/lib/liba.so.meta_lic b/tools/compliance/cmd/testdata/firstparty/lib/liba.so.meta_lic
new file mode 100644
index 0000000..7913af0
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/lib/liba.so.meta_lic
@@ -0,0 +1,9 @@
+package_name:  "Android"
+projects:  "device/library"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.a"
+installed:  "out/target/product/fictional/system/lib/liba.so"
diff --git a/tools/compliance/cmd/testdata/firstparty/lib/libb.so.meta_lic b/tools/compliance/cmd/testdata/firstparty/lib/libb.so.meta_lic
new file mode 100644
index 0000000..a4935d4
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/lib/libb.so.meta_lic
@@ -0,0 +1,9 @@
+package_name:  "Android"
+projects:  "base/library"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.a"
+installed:  "out/target/product/fictional/system/lib/libb.so"
diff --git a/tools/compliance/cmd/testdata/firstparty/lib/libc.a.meta_lic b/tools/compliance/cmd/testdata/firstparty/lib/libc.a.meta_lic
new file mode 100644
index 0000000..fa7459a
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/lib/libc.a.meta_lic
@@ -0,0 +1,7 @@
+package_name:  "Android"
+projects:  "static/library"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libc.a"
diff --git a/tools/compliance/cmd/testdata/firstparty/lib/libd.so.meta_lic b/tools/compliance/cmd/testdata/firstparty/lib/libd.so.meta_lic
new file mode 100644
index 0000000..a2db94a
--- /dev/null
+++ b/tools/compliance/cmd/testdata/firstparty/lib/libd.so.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Android"
+projects:  "dynamic/library"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libd.so"
+installed:  "out/target/product/fictional/system/lib/libd.so"
diff --git a/tools/compliance/cmd/testdata/notice/application.meta_lic b/tools/compliance/cmd/testdata/notice/application.meta_lic
new file mode 100644
index 0000000..56c60ef
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/application.meta_lic
@@ -0,0 +1,24 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "distributable/application"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/application_intermediates/application"
+installed:  "out/target/product/fictional/bin/application"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin3"
+deps:  {
+  file:  "testdata/notice/bin/bin3.meta_lic"
+  annotations:  "toolchain"
+}
+deps:  {
+  file:  "testdata/notice/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/notice/bin/bin1.meta_lic b/tools/compliance/cmd/testdata/notice/bin/bin1.meta_lic
new file mode 100644
index 0000000..9bede1b
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/bin/bin1.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "static/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libc.a"
+deps:  {
+  file:  "testdata/notice/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/lib/libc.a.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/notice/bin/bin2.meta_lic b/tools/compliance/cmd/testdata/notice/bin/bin2.meta_lic
new file mode 100644
index 0000000..86e06c6
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/bin/bin2.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "dynamic/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/lib/libd.so"
+deps:  {
+  file:  "testdata/notice/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
+deps:  {
+  file:  "testdata/notice/lib/libd.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/notice/bin/bin3.meta_lic b/tools/compliance/cmd/testdata/notice/bin/bin3.meta_lic
new file mode 100644
index 0000000..285d899
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/bin/bin3.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Compiler"
+module_classes: "EXECUTABLES"
+projects:  "standalone/binary"
+license_kinds:  "SPDX-license-identifier-NCSA"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin3"
+installed:  "out/target/product/fictional/system/bin/bin3"
diff --git a/tools/compliance/cmd/testdata/notice/container.zip.meta_lic b/tools/compliance/cmd/testdata/notice/container.zip.meta_lic
new file mode 100644
index 0000000..e8af61c
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/container.zip.meta_lic
@@ -0,0 +1,36 @@
+package_name:  "Android"
+projects:  "container/zip"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/container_intermediates/container.zip"
+installed:  "out/target/product/fictional/data/container.zip"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/"
+  container_path:  ""
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/"
+  container_path:  ""
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/notice/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/notice/highest.apex.meta_lic b/tools/compliance/cmd/testdata/notice/highest.apex.meta_lic
new file mode 100644
index 0000000..9b90aa5
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/highest.apex.meta_lic
@@ -0,0 +1,44 @@
+package_name:  "Android"
+projects:  "highest/apex"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/highest_intermediates/highest.apex"
+installed:  "out/target/product/fictional/system/apex/highest.apex"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/liba.so"
+  container_path:  "lib/liba.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/libb.so"
+  container_path:  "lib/libb.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin1"
+  container_path:  "bin/bin1"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin2"
+  container_path:  "bin/bin2"
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/notice/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/notice/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/notice/lib/liba.so.meta_lic b/tools/compliance/cmd/testdata/notice/lib/liba.so.meta_lic
new file mode 100644
index 0000000..a69839f
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/lib/liba.so.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Device"
+projects:  "device/library"
+license_kinds:  "SPDX-license-identifier-BSD"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.a"
+installed:  "out/target/product/fictional/system/lib/liba.so"
diff --git a/tools/compliance/cmd/testdata/notice/lib/libb.so.meta_lic b/tools/compliance/cmd/testdata/notice/lib/libb.so.meta_lic
new file mode 100644
index 0000000..a4935d4
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/lib/libb.so.meta_lic
@@ -0,0 +1,9 @@
+package_name:  "Android"
+projects:  "base/library"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.a"
+installed:  "out/target/product/fictional/system/lib/libb.so"
diff --git a/tools/compliance/cmd/testdata/notice/lib/libc.a.meta_lic b/tools/compliance/cmd/testdata/notice/lib/libc.a.meta_lic
new file mode 100644
index 0000000..eb0f81f
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/lib/libc.a.meta_lic
@@ -0,0 +1,6 @@
+package_name:  "External"
+projects:  "static/library"
+license_kinds:  "SPDX-license-identifier-MIT"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libc.a"
diff --git a/tools/compliance/cmd/testdata/notice/lib/libd.so.meta_lic b/tools/compliance/cmd/testdata/notice/lib/libd.so.meta_lic
new file mode 100644
index 0000000..942d298
--- /dev/null
+++ b/tools/compliance/cmd/testdata/notice/lib/libd.so.meta_lic
@@ -0,0 +1,7 @@
+package_name:  "External"
+projects:  "dynamic/library"
+license_kinds:  "SPDX-license-identifier-MIT"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libd.so"
+installed:  "out/target/product/fictional/system/lib/libd.so"
diff --git a/tools/compliance/cmd/testdata/proprietary/application.meta_lic b/tools/compliance/cmd/testdata/proprietary/application.meta_lic
new file mode 100644
index 0000000..51b97c5
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/application.meta_lic
@@ -0,0 +1,24 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "distributable/application"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/application_intermediates/application"
+installed:  "out/target/product/fictional/bin/application"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin3"
+deps:  {
+  file:  "testdata/proprietary/bin/bin3.meta_lic"
+  annotations:  "toolchain"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/proprietary/bin/bin1.meta_lic b/tools/compliance/cmd/testdata/proprietary/bin/bin1.meta_lic
new file mode 100644
index 0000000..c815858
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/bin/bin1.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "static/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libc.a"
+deps:  {
+  file:  "testdata/proprietary/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/libc.a.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/proprietary/bin/bin2.meta_lic b/tools/compliance/cmd/testdata/proprietary/bin/bin2.meta_lic
new file mode 100644
index 0000000..6b89ba4
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/bin/bin2.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "dynamic/binary"
+license_kinds:  "legacy_proprietary"
+license_conditions:  "proprietary"
+license_conditions:  "by_exception_only"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/lib/libd.so"
+deps:  {
+  file:  "testdata/proprietary/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/libd.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/proprietary/bin/bin3.meta_lic b/tools/compliance/cmd/testdata/proprietary/bin/bin3.meta_lic
new file mode 100644
index 0000000..f93553d
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/bin/bin3.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Compiler"
+module_classes: "EXECUTABLES"
+projects:  "standalone/binary"
+license_kinds:  "SPDX-license-identifier-LGPL-2.0"
+license_conditions:  "restricted"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin3"
+installed:  "out/target/product/fictional/system/bin/bin3"
diff --git a/tools/compliance/cmd/testdata/proprietary/container.zip.meta_lic b/tools/compliance/cmd/testdata/proprietary/container.zip.meta_lic
new file mode 100644
index 0000000..889e17e
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/container.zip.meta_lic
@@ -0,0 +1,36 @@
+package_name:  "Android"
+projects:  "container/zip"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/container_intermediates/container.zip"
+installed:  "out/target/product/fictional/data/container.zip"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/"
+  container_path:  ""
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/"
+  container_path:  ""
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/proprietary/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/proprietary/highest.apex.meta_lic b/tools/compliance/cmd/testdata/proprietary/highest.apex.meta_lic
new file mode 100644
index 0000000..d615404
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/highest.apex.meta_lic
@@ -0,0 +1,44 @@
+package_name:  "Android"
+projects:  "highest/apex"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/highest_intermediates/highest.apex"
+installed:  "out/target/product/fictional/system/apex/highest.apex"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/liba.so"
+  container_path:  "lib/liba.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/libb.so"
+  container_path:  "lib/libb.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin1"
+  container_path:  "bin/bin1"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin2"
+  container_path:  "bin/bin2"
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/proprietary/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/proprietary/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/proprietary/lib/liba.so.meta_lic b/tools/compliance/cmd/testdata/proprietary/lib/liba.so.meta_lic
new file mode 100644
index 0000000..51141c8
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/lib/liba.so.meta_lic
@@ -0,0 +1,9 @@
+package_name:  "Device"
+projects:  "device/library"
+license_kinds:  "legacy_proprietary"
+license_conditions:  "proprietary"
+license_conditions:  "by_exception_only"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.a"
+installed:  "out/target/product/fictional/system/lib/liba.so"
diff --git a/tools/compliance/cmd/testdata/proprietary/lib/libb.so.meta_lic b/tools/compliance/cmd/testdata/proprietary/lib/libb.so.meta_lic
new file mode 100644
index 0000000..c1b86d7
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/lib/libb.so.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Android"
+projects:  "base/library"
+license_kinds:  "SPDX-license-identifier-GPL-2.0"
+license_conditions:  "restricted"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.a"
+installed:  "out/target/product/fictional/system/lib/libb.so"
diff --git a/tools/compliance/cmd/testdata/proprietary/lib/libc.a.meta_lic b/tools/compliance/cmd/testdata/proprietary/lib/libc.a.meta_lic
new file mode 100644
index 0000000..1ade7da
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/lib/libc.a.meta_lic
@@ -0,0 +1,7 @@
+package_name:  "External"
+projects:  "static/library"
+license_kinds:  "legacy_proprietary"
+license_conditions:  "proprietary"
+license_conditions:  "by_exception_only"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libc.a"
diff --git a/tools/compliance/cmd/testdata/proprietary/lib/libd.so.meta_lic b/tools/compliance/cmd/testdata/proprietary/lib/libd.so.meta_lic
new file mode 100644
index 0000000..942d298
--- /dev/null
+++ b/tools/compliance/cmd/testdata/proprietary/lib/libd.so.meta_lic
@@ -0,0 +1,7 @@
+package_name:  "External"
+projects:  "dynamic/library"
+license_kinds:  "SPDX-license-identifier-MIT"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libd.so"
+installed:  "out/target/product/fictional/system/lib/libd.so"
diff --git a/tools/compliance/cmd/testdata/reciprocal/application.meta_lic b/tools/compliance/cmd/testdata/reciprocal/application.meta_lic
new file mode 100644
index 0000000..015c2d9
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/application.meta_lic
@@ -0,0 +1,24 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "distributable/application"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/application_intermediates/application"
+installed:  "out/target/product/fictional/bin/application"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin3"
+deps:  {
+  file:  "testdata/reciprocal/bin/bin3.meta_lic"
+  annotations:  "toolchain"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/reciprocal/bin/bin1.meta_lic b/tools/compliance/cmd/testdata/reciprocal/bin/bin1.meta_lic
new file mode 100644
index 0000000..4ebf653
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/bin/bin1.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "static/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libc.a"
+deps:  {
+  file:  "testdata/reciprocal/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/libc.a.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/reciprocal/bin/bin2.meta_lic b/tools/compliance/cmd/testdata/reciprocal/bin/bin2.meta_lic
new file mode 100644
index 0000000..4d28608
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/bin/bin2.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "dynamic/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/lib/libd.so"
+deps:  {
+  file:  "testdata/reciprocal/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/libd.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/reciprocal/bin/bin3.meta_lic b/tools/compliance/cmd/testdata/reciprocal/bin/bin3.meta_lic
new file mode 100644
index 0000000..285d899
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/bin/bin3.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Compiler"
+module_classes: "EXECUTABLES"
+projects:  "standalone/binary"
+license_kinds:  "SPDX-license-identifier-NCSA"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin3"
+installed:  "out/target/product/fictional/system/bin/bin3"
diff --git a/tools/compliance/cmd/testdata/reciprocal/container.zip.meta_lic b/tools/compliance/cmd/testdata/reciprocal/container.zip.meta_lic
new file mode 100644
index 0000000..ea3598f
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/container.zip.meta_lic
@@ -0,0 +1,36 @@
+package_name:  "Android"
+projects:  "container/zip"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/container_intermediates/container.zip"
+installed:  "out/target/product/fictional/data/container.zip"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/"
+  container_path:  ""
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/"
+  container_path:  ""
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/reciprocal/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/reciprocal/highest.apex.meta_lic b/tools/compliance/cmd/testdata/reciprocal/highest.apex.meta_lic
new file mode 100644
index 0000000..1fec741
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/highest.apex.meta_lic
@@ -0,0 +1,44 @@
+package_name:  "Android"
+projects:  "highest/apex"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/highest_intermediates/highest.apex"
+installed:  "out/target/product/fictional/system/apex/highest.apex"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/liba.so"
+  container_path:  "lib/liba.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/libb.so"
+  container_path:  "lib/libb.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin1"
+  container_path:  "bin/bin1"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin2"
+  container_path:  "bin/bin2"
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/reciprocal/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/reciprocal/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/reciprocal/lib/liba.so.meta_lic b/tools/compliance/cmd/testdata/reciprocal/lib/liba.so.meta_lic
new file mode 100644
index 0000000..79d7a9e
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/lib/liba.so.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Device"
+projects:  "device/library"
+license_kinds:  "SPDX-license-identifier-MPL"
+license_conditions:  "reciprocal"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.a"
+installed:  "out/target/product/fictional/system/lib/liba.so"
diff --git a/tools/compliance/cmd/testdata/reciprocal/lib/libb.so.meta_lic b/tools/compliance/cmd/testdata/reciprocal/lib/libb.so.meta_lic
new file mode 100644
index 0000000..a4935d4
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/lib/libb.so.meta_lic
@@ -0,0 +1,9 @@
+package_name:  "Android"
+projects:  "base/library"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.a"
+installed:  "out/target/product/fictional/system/lib/libb.so"
diff --git a/tools/compliance/cmd/testdata/reciprocal/lib/libc.a.meta_lic b/tools/compliance/cmd/testdata/reciprocal/lib/libc.a.meta_lic
new file mode 100644
index 0000000..8f6d356
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/lib/libc.a.meta_lic
@@ -0,0 +1,6 @@
+package_name:  "External"
+projects:  "static/library"
+license_kinds:  "SPDX-license-identifier-MPL"
+license_conditions:  "reciprocal"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libc.a"
diff --git a/tools/compliance/cmd/testdata/reciprocal/lib/libd.so.meta_lic b/tools/compliance/cmd/testdata/reciprocal/lib/libd.so.meta_lic
new file mode 100644
index 0000000..942d298
--- /dev/null
+++ b/tools/compliance/cmd/testdata/reciprocal/lib/libd.so.meta_lic
@@ -0,0 +1,7 @@
+package_name:  "External"
+projects:  "dynamic/library"
+license_kinds:  "SPDX-license-identifier-MIT"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libd.so"
+installed:  "out/target/product/fictional/system/lib/libd.so"
diff --git a/tools/compliance/cmd/testdata/restricted/application.meta_lic b/tools/compliance/cmd/testdata/restricted/application.meta_lic
new file mode 100644
index 0000000..a06a2c8
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/application.meta_lic
@@ -0,0 +1,24 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "distributable/application"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/application_intermediates/application"
+installed:  "out/target/product/fictional/bin/application"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin3"
+deps:  {
+  file:  "testdata/restricted/bin/bin3.meta_lic"
+  annotations:  "toolchain"
+}
+deps:  {
+  file:  "testdata/restricted/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/restricted/bin/bin1.meta_lic b/tools/compliance/cmd/testdata/restricted/bin/bin1.meta_lic
new file mode 100644
index 0000000..dd8a2e0
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/bin/bin1.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "static/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/liba.a"
+sources:  "out/target/product/fictional/system/lib/libc.a"
+deps:  {
+  file:  "testdata/restricted/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/lib/libc.a.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/restricted/bin/bin2.meta_lic b/tools/compliance/cmd/testdata/restricted/bin/bin2.meta_lic
new file mode 100644
index 0000000..714b537
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/bin/bin2.meta_lic
@@ -0,0 +1,19 @@
+package_name:  "Android"
+module_classes: "EXECUTABLES"
+projects:  "dynamic/binary"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin1"
+installed:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/lib/libd.so"
+deps:  {
+  file:  "testdata/restricted/lib/libb.so.meta_lic"
+  annotations:  "dynamic"
+}
+deps:  {
+  file:  "testdata/restricted/lib/libd.so.meta_lic"
+  annotations:  "dynamic"
+}
diff --git a/tools/compliance/cmd/testdata/restricted/bin/bin3.meta_lic b/tools/compliance/cmd/testdata/restricted/bin/bin3.meta_lic
new file mode 100644
index 0000000..f93553d
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/bin/bin3.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Compiler"
+module_classes: "EXECUTABLES"
+projects:  "standalone/binary"
+license_kinds:  "SPDX-license-identifier-LGPL-2.0"
+license_conditions:  "restricted"
+is_container:  false
+built:  "out/target/product/fictional/obj/EXECUTABLES/bin_intermediates/bin3"
+installed:  "out/target/product/fictional/system/bin/bin3"
diff --git a/tools/compliance/cmd/testdata/restricted/container.zip.meta_lic b/tools/compliance/cmd/testdata/restricted/container.zip.meta_lic
new file mode 100644
index 0000000..a63263b
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/container.zip.meta_lic
@@ -0,0 +1,36 @@
+package_name:  "Android"
+projects:  "container/zip"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/container_intermediates/container.zip"
+installed:  "out/target/product/fictional/data/container.zip"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/"
+  container_path:  ""
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/"
+  container_path:  ""
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/restricted/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/restricted/highest.apex.meta_lic b/tools/compliance/cmd/testdata/restricted/highest.apex.meta_lic
new file mode 100644
index 0000000..dba419a
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/highest.apex.meta_lic
@@ -0,0 +1,44 @@
+package_name:  "Android"
+projects:  "highest/apex"
+license_kinds:  "SPDX-license-identifier-Apache-2.0"
+license_conditions:  "notice"
+license_texts:  "build/soong/licenses/LICENSE"
+is_container:  true
+built:  "out/target/product/fictional/obj/ETC/highest_intermediates/highest.apex"
+installed:  "out/target/product/fictional/system/apex/highest.apex"
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/liba.so"
+  container_path:  "lib/liba.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/lib/libb.so"
+  container_path:  "lib/libb.so"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin1"
+  container_path:  "bin/bin1"
+}
+install_map {
+  from_path:  "out/target/product/fictional/system/bin/bin2"
+  container_path:  "bin/bin2"
+}
+sources:  "out/target/product/fictional/system/lib/liba.so"
+sources:  "out/target/product/fictional/system/lib/libb.so"
+sources:  "out/target/product/fictional/system/bin/bin1"
+sources:  "out/target/product/fictional/system/bin/bin2"
+deps:  {
+  file:  "testdata/restricted/bin/bin1.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/bin/bin2.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/lib/liba.so.meta_lic"
+  annotations:  "static"
+}
+deps:  {
+  file:  "testdata/restricted/lib/libb.so.meta_lic"
+  annotations:  "static"
+}
diff --git a/tools/compliance/cmd/testdata/restricted/lib/liba.so.meta_lic b/tools/compliance/cmd/testdata/restricted/lib/liba.so.meta_lic
new file mode 100644
index 0000000..b1d4560
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/lib/liba.so.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Device"
+projects:  "device/library"
+license_kinds:  "SPDX-license-identifier-LGPL-2.0"
+license_conditions:  "restricted"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/liba.a"
+installed:  "out/target/product/fictional/system/lib/liba.so"
diff --git a/tools/compliance/cmd/testdata/restricted/lib/libb.so.meta_lic b/tools/compliance/cmd/testdata/restricted/lib/libb.so.meta_lic
new file mode 100644
index 0000000..c1b86d7
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/lib/libb.so.meta_lic
@@ -0,0 +1,8 @@
+package_name:  "Android"
+projects:  "base/library"
+license_kinds:  "SPDX-license-identifier-GPL-2.0"
+license_conditions:  "restricted"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.so"
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libb.a"
+installed:  "out/target/product/fictional/system/lib/libb.so"
diff --git a/tools/compliance/cmd/testdata/restricted/lib/libc.a.meta_lic b/tools/compliance/cmd/testdata/restricted/lib/libc.a.meta_lic
new file mode 100644
index 0000000..8f6d356
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/lib/libc.a.meta_lic
@@ -0,0 +1,6 @@
+package_name:  "External"
+projects:  "static/library"
+license_kinds:  "SPDX-license-identifier-MPL"
+license_conditions:  "reciprocal"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libc.a"
diff --git a/tools/compliance/cmd/testdata/restricted/lib/libd.so.meta_lic b/tools/compliance/cmd/testdata/restricted/lib/libd.so.meta_lic
new file mode 100644
index 0000000..942d298
--- /dev/null
+++ b/tools/compliance/cmd/testdata/restricted/lib/libd.so.meta_lic
@@ -0,0 +1,7 @@
+package_name:  "External"
+projects:  "dynamic/library"
+license_kinds:  "SPDX-license-identifier-MIT"
+license_conditions:  "notice"
+is_container:  false
+built:  "out/target/product/fictional/obj/SHARED_LIBRARIES/lib_intermediates/libd.so"
+installed:  "out/target/product/fictional/system/lib/libd.so"
diff --git a/tools/compliance/condition.go b/tools/compliance/condition.go
index e6d23ef..b5c8cec 100644
--- a/tools/compliance/condition.go
+++ b/tools/compliance/condition.go
@@ -77,6 +77,15 @@
 	return sb.String()
 }
 
+// Names returns the list of the conditions' names.
+func (cl ConditionList) Names() []string {
+	result := make([]string, 0, len(cl))
+	for _, lc := range cl {
+		result = append(result, lc.name)
+	}
+	return result
+}
+
 // HasByName returns true if the list contains any condition matching `name`.
 func (cl ConditionList) HasByName(name ConditionNames) bool {
 	for _, lc := range cl {
diff --git a/tools/compliance/conditionset.go b/tools/compliance/conditionset.go
index d972eb9..1ad15ca 100644
--- a/tools/compliance/conditionset.go
+++ b/tools/compliance/conditionset.go
@@ -150,6 +150,15 @@
 	return result
 }
 
+// Names returns a list of the names of the conditions in the set.
+func (cs *LicenseConditionSet) Names() []string {
+	result := make([]string, 0, len(cs.conditions))
+	for name := range cs.conditions {
+		result = append(result, name)
+	}
+	return result
+}
+
 // Count returns the number of conditions in the set.
 func (cs *LicenseConditionSet) Count() int {
 	size := 0
diff --git a/tools/compliance/doc.go b/tools/compliance/doc.go
new file mode 100644
index 0000000..a47c1cf
--- /dev/null
+++ b/tools/compliance/doc.go
@@ -0,0 +1,77 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+/*
+
+Package compliance provides an approved means for reading, consuming, and
+analyzing license metadata graphs.
+
+Assuming the license metadata and dependencies are fully and accurately
+recorded in the build system, any discrepancy between the official policy for
+open source license compliance and this code is a bug in this code.
+
+A few principal types to understand are LicenseGraph, LicenseCondition, and
+ResolutionSet.
+
+LicenseGraph
+------------
+
+A LicenseGraph is an immutable graph of the targets and dependencies reachable
+from a specific set of root targets. In general, the root targets will be the
+artifacts in a release or distribution. While conceptually immutable, parts of
+the graph may be loaded or evaluated lazily.
+
+LicenseCondition
+----------------
+
+A LicenseCondition is an immutable tuple pairing a condition name with an
+originating target. e.g. Per current policy, a static library licensed under an
+MIT license would pair a "notice" condition with the static library target, and
+a dynamic license licensed under GPL would pair a "restricted" condition with
+the dynamic library target.
+
+ResolutionSet
+-------------
+
+A ResolutionSet is an immutable set of `AttachesTo`, `ActsOn`, `Resolves`
+tuples describing how license conditions apply to targets.
+
+`AttachesTo` is the trigger for acting. Distribution of the target invokes
+the policy.
+
+`ActsOn` is the target to share, give notice for, hide etc.
+
+`Resolves` is the license condition that the action resolves.
+
+Remember: Each license condition pairs a condition name with an originating
+target so each resolution in a ResolutionSet has two targets it applies to and
+one target from which it originates, all of which may be the same target.
+
+For most condition types, `ActsOn` and `Resolves.Origin` will be the same
+target. For example, a notice condition policy means attribution or notice must
+be given for the target where the condition originates. Likewise, a proprietary
+condition policy means the privacy of the target where the condition originates
+must be respected. i.e. The thing acted on is the origin.
+
+Restricted conditions are different. The infectious nature of restricted often
+means sharing code that is not the target where the restricted condition
+originates. Linking an MIT library to a GPL library implies a policy to share
+the MIT library despite the MIT license having no source sharing requirement.
+
+In this case, one or more resolution tuples will have the MIT license module in
+`ActsOn` and the restricted condition originating at the GPL library module in
+`Resolves`. These tuples will `AttachTo` every target that depends on the GPL
+library because shipping any of those targets trigger the policy to share the
+code.
+*/
+package compliance
diff --git a/tools/compliance/policy/resolve.go b/tools/compliance/policy/resolve.go
index 9962e68..58547f8 100644
--- a/tools/compliance/policy/resolve.go
+++ b/tools/compliance/policy/resolve.go
@@ -41,59 +41,7 @@
 	// must be indexed for fast lookup
 	lg.indexForward()
 
-	rs = newResolutionSet()
-
-	// cmap contains an entry for every target that was previously walked as a pure aggregate only.
-	cmap := make(map[string]bool)
-
-	var walk func(f string, treatAsAggregate bool) actionSet
-
-	walk = func(f string, treatAsAggregate bool) actionSet {
-		target := lg.targets[f]
-		result := make(actionSet)
-		result[target] = newLicenseConditionSet()
-		result[target].add(target, target.proto.LicenseConditions...)
-		if preresolved, ok := rs.resolutions[target]; ok {
-			if treatAsAggregate {
-				result.addSet(preresolved)
-				return result
-			}
-			if _, asAggregate := cmap[f]; !asAggregate {
-				result.addSet(preresolved)
-				return result
-			}
-			// previously walked in a pure aggregate context,
-			// needs to walk again in non-aggregate context
-			delete(cmap, f)
-		}
-		if treatAsAggregate {
-			cmap[f] = true
-		}
-
-		// add all the conditions from all the dependencies
-		for _, edge := range lg.index[f] {
-			// walk dependency to get its conditions
-			as := walk(edge.dependency, treatAsAggregate && lg.targets[edge.dependency].IsContainer())
-
-			// turn those into the conditions that apply to the target
-			as = depActionsApplicableToTarget(TargetEdge{lg, edge}, as, treatAsAggregate)
-
-			// add them to the result
-			result.addSet(as)
-		}
-
-		// record these conditions as applicable to the target
-		rs.addConditions(target, result)
-		rs.addSelf(target, result.byName(ImpliesRestricted))
-
-		// return this up the tree
-		return result
-	}
-
-	// walk each of the roots
-	for _, r := range lg.rootFiles {
-		_ = walk(r, lg.targets[r].IsContainer())
-	}
+	rs = resolveBottomUp(lg, make(map[*TargetNode]actionSet) /* empty map; no prior resolves */)
 
 	// if not yet cached, save the result
 	lg.mu.Lock()
@@ -133,61 +81,61 @@
 	//
 	// rmap is the resulting ResolutionSet
 	rmap := make(map[*TargetNode]actionSet)
-	for attachesTo, as := range rs.resolutions {
-		rmap[attachesTo] = as.copy()
-	}
 
-	path := make([]*dependencyEdge, 0, 32)
+	// cmap contains the set of targets walked as pure aggregates. i.e. containers
+	cmap := make(map[*TargetNode]bool)
 
-	var walk func(f string, cs *LicenseConditionSet, treatAsAggregate bool)
+	var walk func(fnode *TargetNode, cs *LicenseConditionSet, treatAsAggregate bool)
 
-	walk = func(f string, cs *LicenseConditionSet, treatAsAggregate bool) {
-		fnode := lg.targets[f]
-		if !cs.IsEmpty() {
-			parentsAllAggregate := true
-			for _, e := range path {
-				target := lg.targets[e.target]
-				if _, ok := rmap[target]; !ok {
-					rmap[target] = make(actionSet)
-				}
-				rmap[target].add(fnode, cs)
-				if !target.IsContainer() {
-					parentsAllAggregate = false
-					break
-				}
-			}
-			if parentsAllAggregate {
-				if _, ok := rmap[fnode]; !ok {
-					rmap[fnode] = make(actionSet)
-				}
-				rmap[fnode].add(fnode, cs)
-			}
+	walk = func(fnode *TargetNode, cs *LicenseConditionSet, treatAsAggregate bool) {
+		if _, ok := rmap[fnode]; !ok {
+			rmap[fnode] = make(actionSet)
 		}
-		// add conditions attached to `f`
+		rmap[fnode].add(fnode, cs)
+		if treatAsAggregate {
+			cmap[fnode] = true
+		}
+		// add conditions attached to `fnode`
 		cs = cs.Copy()
 		for _, fcs := range rs.resolutions[fnode] {
 			cs.AddSet(fcs)
 		}
 		// for each dependency
-		for _, edge := range lg.index[f] {
+		for _, edge := range lg.index[fnode.name] {
 			e := TargetEdge{lg, edge}
 			// dcs holds the dpendency conditions inherited from the target
 			dcs := targetConditionsApplicableToDep(e, cs, treatAsAggregate)
-			if dcs.IsEmpty() {
-				if !treatAsAggregate || (!edgeIsDerivation(e) && !edgeIsDynamicLink(e)) {
-					continue
+			if dcs.IsEmpty() && !treatAsAggregate {
+				continue
+			}
+			dnode := lg.targets[edge.dependency]
+			if as, alreadyWalked := rmap[dnode]; alreadyWalked {
+				diff := dcs.Copy()
+				diff.RemoveSet(as.conditions())
+				if diff.IsEmpty() {
+					// no new conditions
+
+					// pure aggregates never need walking a 2nd time with same conditions
+					if treatAsAggregate {
+						continue
+					}
+					// non-aggregates don't need walking as non-aggregate a 2nd time
+					if _, asAggregate := cmap[dnode]; !asAggregate {
+						continue
+					}
+					// previously walked as pure aggregate; need to re-walk as non-aggregate
+					delete(cmap, dnode)
 				}
 			}
-			path = append(path, edge)
 			// add the conditions to the dependency
-			walk(edge.dependency, dcs, treatAsAggregate && lg.targets[edge.dependency].IsContainer())
-			path = path[:len(path)-1]
+			walk(dnode, dcs, treatAsAggregate && lg.targets[edge.dependency].IsContainer())
 		}
 	}
 
 	// walk each of the roots
 	for _, r := range lg.rootFiles {
-		as, ok := rs.resolutions[lg.targets[r]]
+		rnode := lg.targets[r]
+		as, ok := rs.resolutions[rnode]
 		if !ok {
 			// no conditions in root or transitive closure of dependencies
 			continue
@@ -196,12 +144,21 @@
 			continue
 		}
 
-		path = path[:0]
 		// add the conditions to the root and its transitive closure
-		walk(r, newLicenseConditionSet(), lg.targets[r].IsContainer())
+		walk(rnode, newLicenseConditionSet(), lg.targets[r].IsContainer())
 	}
 
-	rs = &ResolutionSet{rmap}
+	// back-fill any bottom-up conditions on targets missed by top-down walk
+	for attachesTo, as := range rs.resolutions {
+		if _, ok := rmap[attachesTo]; !ok {
+			rmap[attachesTo] = as.copy()
+		} else {
+			rmap[attachesTo].addSet(as)
+		}
+	}
+
+	// propagate any new conditions back up the graph
+	rs = resolveBottomUp(lg, rmap)
 
 	// if not yet cached, save the result
 	lg.mu.Lock()
@@ -215,3 +172,70 @@
 
 	return rs
 }
+
+// resolveBottomUp implements a bottom-up resolve propagating conditions both
+// from the graph, and from a `priors` map of resolutions.
+func resolveBottomUp(lg *LicenseGraph, priors map[*TargetNode]actionSet) *ResolutionSet {
+	rs := newResolutionSet()
+
+	// cmap contains an entry for every target that was previously walked as a pure aggregate only.
+	cmap := make(map[string]bool)
+
+	var walk func(f string, treatAsAggregate bool) actionSet
+
+	walk = func(f string, treatAsAggregate bool) actionSet {
+		target := lg.targets[f]
+		result := make(actionSet)
+		result[target] = newLicenseConditionSet()
+		result[target].add(target, target.proto.LicenseConditions...)
+		if pas, ok := priors[target]; ok {
+			result.addSet(pas)
+		}
+		if preresolved, ok := rs.resolutions[target]; ok {
+			if treatAsAggregate {
+				result.addSet(preresolved)
+				return result
+			}
+			if _, asAggregate := cmap[f]; !asAggregate {
+				result.addSet(preresolved)
+				return result
+			}
+			// previously walked in a pure aggregate context,
+			// needs to walk again in non-aggregate context
+			delete(cmap, f)
+		}
+		if treatAsAggregate {
+			cmap[f] = true
+		}
+
+		// add all the conditions from all the dependencies
+		for _, edge := range lg.index[f] {
+			// walk dependency to get its conditions
+			as := walk(edge.dependency, treatAsAggregate && lg.targets[edge.dependency].IsContainer())
+
+			// turn those into the conditions that apply to the target
+			as = depActionsApplicableToTarget(TargetEdge{lg, edge}, as, treatAsAggregate)
+
+			// add them to the result
+			result.addSet(as)
+		}
+
+		// record these conditions as applicable to the target
+		rs.addConditions(target, result)
+		if len(priors) == 0 {
+			// on the first bottom-up resolve, parents have their own sharing and notice needs
+			// on the later resolve, if priors is empty, there will be nothing new to add
+			rs.addSelf(target, result.byName(ImpliesRestricted))
+		}
+
+		// return this up the tree
+		return result
+	}
+
+	// walk each of the roots
+	for _, r := range lg.rootFiles {
+		_ = walk(r, lg.targets[r].IsContainer())
+	}
+
+	return rs
+}
diff --git a/tools/compliance/policy/resolve_test.go b/tools/compliance/policy/resolve_test.go
index aa5bb2a..4c99d35 100644
--- a/tools/compliance/policy/resolve_test.go
+++ b/tools/compliance/policy/resolve_test.go
@@ -434,6 +434,7 @@
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 				{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
@@ -480,6 +481,7 @@
 				{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
 				{"mitBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
+				{"mplLib.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"mplLib.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
 			},
 		},
@@ -512,6 +514,7 @@
 				{"apacheBin.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
@@ -540,6 +543,7 @@
 				{"gplLib.meta_lic", "gplLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"mitBin.meta_lic", "mitBin.meta_lic", "mitBin.meta_lic", "notice"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
+				{"mplLib.meta_lic", "mplLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"mplLib.meta_lic", "mplLib.meta_lic", "mplLib.meta_lic", "reciprocal"},
 			},
 		},
@@ -573,6 +577,7 @@
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
 				{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
@@ -612,6 +617,7 @@
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
 				{"lgplLib.meta_lic", "lgplLib.meta_lic", "lgplLib.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "lgplLib.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
@@ -687,6 +693,7 @@
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
@@ -704,6 +711,7 @@
 				{"dependentModule.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 				{"dependentModule.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
@@ -735,6 +743,7 @@
 				{"dependentModule.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 				{"dependentModule.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
diff --git a/tools/compliance/policy/resolvenotices_test.go b/tools/compliance/policy/resolvenotices_test.go
index b428d5b..275c0a5 100644
--- a/tools/compliance/policy/resolvenotices_test.go
+++ b/tools/compliance/policy/resolvenotices_test.go
@@ -153,6 +153,7 @@
 				{"apacheBin.meta_lic", "apacheBin.meta_lic", "apacheBin.meta_lic", "notice"},
 				{"apacheBin.meta_lic", "apacheBin.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"apacheBin.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
+				{"mitLib.meta_lic", "mitLib.meta_lic", "gplLib.meta_lic", "restricted"},
 				{"mitLib.meta_lic", "mitLib.meta_lic", "mitLib.meta_lic", "notice"},
 			},
 		},
diff --git a/tools/compliance/policy/resolveshare_test.go b/tools/compliance/policy/resolveshare_test.go
index 7371ccf..ad3630d 100644
--- a/tools/compliance/policy/resolveshare_test.go
+++ b/tools/compliance/policy/resolveshare_test.go
@@ -176,6 +176,7 @@
 			expectedResolutions: []res{
 				{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
 				{"gplBin.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
+				{"apacheLib.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
 			},
 		},
 		{
@@ -218,6 +219,7 @@
 			expectedResolutions: []res{
 				{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
+				{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 			},
 		},
 		{
diff --git a/tools/compliance/policy/walk_test.go b/tools/compliance/policy/walk_test.go
index 2eef702..07710aa 100644
--- a/tools/compliance/policy/walk_test.go
+++ b/tools/compliance/policy/walk_test.go
@@ -336,6 +336,7 @@
 			expectedResolutions: []res{
 				{"gplBin.meta_lic", "gplBin.meta_lic", "gplBin.meta_lic", "restricted"},
 				{"gplBin.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
+				{"apacheLib.meta_lic", "apacheLib.meta_lic", "gplBin.meta_lic", "restricted"},
 			},
 		},
 		{
@@ -428,6 +429,7 @@
 			expectedResolutions: []res{
 				{"gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 				{"gplWithClasspathException.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
+				{"dependentModule.meta_lic", "dependentModule.meta_lic", "gplWithClasspathException.meta_lic", "restricted"},
 			},
 		},
 		{