aboutsummaryrefslogtreecommitdiff
path: root/tools/product_config/src/com/android/build/config/OutputChecker.java
diff options
context:
space:
mode:
Diffstat (limited to 'tools/product_config/src/com/android/build/config/OutputChecker.java')
-rw-r--r--tools/product_config/src/com/android/build/config/OutputChecker.java190
1 files changed, 190 insertions, 0 deletions
diff --git a/tools/product_config/src/com/android/build/config/OutputChecker.java b/tools/product_config/src/com/android/build/config/OutputChecker.java
new file mode 100644
index 0000000000..d982dba7ed
--- /dev/null
+++ b/tools/product_config/src/com/android/build/config/OutputChecker.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package com.android.build.config;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Compares the make-based configuration as reported by dumpconfig.mk
+ * with what was computed from the new tool.
+ */
+public class OutputChecker {
+ // Differences that we know about, either know issues to be fixed or intentional.
+ private static final RegexSet IGNORED_VARIABLES = new RegexSet(
+ // TODO: Rewrite the enforce packages exist logic into this tool.
+ "PRODUCT_ENFORCE_PACKAGES_EXIST",
+ "PRODUCT_ENFORCE_PACKAGES_EXIST_ALLOW_LIST",
+ "PRODUCTS\\..*\\.PRODUCT_ENFORCE_PACKAGES_EXIST",
+ "PRODUCTS\\..*\\.PRODUCT_ENFORCE_PACKAGES_EXIST_ALLOW_LIST",
+
+ // This is generated by this tool, but comes later in the make build system.
+ "INTERNAL_PRODUCT",
+
+ // This can be set temporarily by product_config.mk
+ ".KATI_ALLOW_RULES"
+ );
+
+ private final FlatConfig mConfig;
+ private final TreeMap<String, Variable> mVariables;
+
+ /**
+ * Represents the before and after state of a variable.
+ */
+ public static class Variable {
+ public final String name;
+ public final VarType type;
+ public final Str original;
+ public final Value updated;
+
+ public Variable(String name, VarType type, Str original) {
+ this(name, type, original, null);
+ }
+
+ public Variable(String name, VarType type, Str original, Value updated) {
+ this.name = name;
+ this.type = type;
+ this.original = original;
+ this.updated = updated;
+ }
+
+ /**
+ * Return copy of this Variable with the updated field also set.
+ */
+ public Variable addUpdated(Value updated) {
+ return new Variable(name, type, original, updated);
+ }
+
+ /**
+ * Return whether normalizedOriginal and normalizedUpdate are equal.
+ */
+ public boolean isSame() {
+ final Str normalizedOriginal = Value.normalize(original);
+ final Str normalizedUpdated = Value.normalize(updated);
+ if (normalizedOriginal == null && normalizedUpdated == null) {
+ return true;
+ } else if (normalizedOriginal != null) {
+ return normalizedOriginal.equals(normalizedUpdated);
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Construct OutputChecker with the config it will check.
+ */
+ public OutputChecker(FlatConfig config) {
+ mConfig = config;
+ mVariables = getVariables(config);
+ }
+
+ /**
+ * Add a WARNING_DIFFERENT_FROM_KATI for each of the variables which have changed.
+ */
+ public void reportErrors(Errors errors) {
+ for (Variable var: getDifferences()) {
+ if (IGNORED_VARIABLES.matches(var.name)) {
+ continue;
+ }
+ errors.WARNING_DIFFERENT_FROM_KATI.add("product_config processing differs from"
+ + " kati processing for " + var.type + " variable " + var.name + ".\n"
+ + "original: "
+ + Value.oneLinePerWord(var.original, "<null>") + "\n"
+ + "updated: "
+ + Value.oneLinePerWord(var.updated, "<null>"));
+ }
+ }
+
+ /**
+ * Get the Variables that are different between the normalized form of the original
+ * and updated. If one is null and the other is not, even if one is an empty string,
+ * the values are considered different.
+ */
+ public List<Variable> getDifferences() {
+ final ArrayList<Variable> result = new ArrayList();
+ for (Variable var: mVariables.values()) {
+ if (!var.isSame()) {
+ result.add(var);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get all of the variables for this config.
+ *
+ * VisibleForTesting
+ */
+ static TreeMap<String, Variable> getVariables(FlatConfig config) {
+ final TreeMap<String, Variable> result = new TreeMap();
+
+ // Add the original values to mAll
+ for (Map.Entry<String, Str> entry: getModifiedVars(config.getInitialVariables(),
+ config.getFinalVariables()).entrySet()) {
+ final String name = entry.getKey();
+ result.put(name, new Variable(name, config.getVarType(name), entry.getValue()));
+ }
+
+ // Add the updated values to mAll
+ for (Map.Entry<String, Value> entry: config.getValues().entrySet()) {
+ final String name = entry.getKey();
+ final Value value = entry.getValue();
+ Variable var = result.get(name);
+ if (var == null) {
+ result.put(name, new Variable(name, config.getVarType(name), null, value));
+ } else {
+ result.put(name, var.addUpdated(value));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Get the entries that are different in the two maps.
+ */
+ public static Map<String, Str> getModifiedVars(Map<String, Str> before,
+ Map<String, Str> after) {
+ final HashMap<String, Str> result = new HashMap();
+
+ // Entries that were added or changed.
+ for (Map.Entry<String, Str> afterEntry: after.entrySet()) {
+ final String varName = afterEntry.getKey();
+ final Str afterValue = afterEntry.getValue();
+ final Str beforeValue = before.get(varName);
+ if (beforeValue == null || !beforeValue.equals(afterValue)) {
+ result.put(varName, afterValue);
+ }
+ }
+
+ // removed Entries that were removed, we just treat them as empty string
+ for (Map.Entry<String, Str> beforeEntry: before.entrySet()) {
+ final String varName = beforeEntry.getKey();
+ if (!after.containsKey(varName)) {
+ result.put(varName, new Str(""));
+ }
+ }
+
+ return result;
+ }
+}