Add skeleton for product-config tool.
There's also a bunch of boilerplate error handling and option parsing stuff that I wish someone would put into a library that's available to the android tree. Test: atest product-config-test Change-Id: Ieebcc7bd47a8644d1374fb02c146e9038859f4a2
This commit is contained in:
parent
95bd22edb6
commit
841c3e3ea6
|
@ -0,0 +1,23 @@
|
|||
java_defaults {
|
||||
name: "product-config-defaults",
|
||||
srcs: ["src/**/*.java"],
|
||||
}
|
||||
|
||||
java_binary_host {
|
||||
name: "product-config",
|
||||
defaults: ["product-config-defaults"],
|
||||
manifest: "MANIFEST.MF"
|
||||
}
|
||||
|
||||
java_test_host {
|
||||
name: "product-config-test",
|
||||
defaults: ["product-config-defaults"],
|
||||
srcs: [
|
||||
"test/**/*.java",
|
||||
],
|
||||
static_libs: [
|
||||
"junit"
|
||||
],
|
||||
test_suites: ["general-tests"]
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: com.android.build.config.Main
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "product_config_test"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Base class for reporting errors.
|
||||
*/
|
||||
public class ErrorReporter {
|
||||
/**
|
||||
* List of Entries that have occurred.
|
||||
*/
|
||||
// Also used as the lock for this object.
|
||||
private final ArrayList<Entry> mEntries = new ArrayList();
|
||||
|
||||
/**
|
||||
* The categories that are for this Errors object.
|
||||
*/
|
||||
private Map<Integer, Category> mCategories;
|
||||
|
||||
/**
|
||||
* Whether there has been a warning or an error yet.
|
||||
*/
|
||||
private boolean mHadWarningOrError;
|
||||
|
||||
/**
|
||||
* Whether there has been an error yet.
|
||||
*/
|
||||
private boolean mHadError;
|
||||
|
||||
/**
|
||||
* Whether errors are errors, warnings or hidden.
|
||||
*/
|
||||
public static enum Level {
|
||||
HIDDEN("hidden"),
|
||||
WARNING("warning"),
|
||||
ERROR("error");
|
||||
|
||||
private final String mLabel;
|
||||
|
||||
Level(String label) {
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The available error codes.
|
||||
*/
|
||||
public class Category {
|
||||
private final int mCode;
|
||||
private boolean mIsLevelSettable;
|
||||
private Level mLevel;
|
||||
private String mHelp;
|
||||
|
||||
/**
|
||||
* Construct a Category object.
|
||||
*/
|
||||
public Category(int code, boolean isLevelSettable, Level level, String help) {
|
||||
if (!isLevelSettable && level != Level.ERROR) {
|
||||
throw new RuntimeException("Don't have WARNING or HIDDEN without isLevelSettable");
|
||||
}
|
||||
mCode = code;
|
||||
mIsLevelSettable = isLevelSettable;
|
||||
mLevel = level;
|
||||
mHelp = help;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the numeric code for the Category, which can be used to set the level.
|
||||
*/
|
||||
public int getCode() {
|
||||
return mCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the level of this Category can be changed.
|
||||
*/
|
||||
public boolean isLevelSettable() {
|
||||
return mIsLevelSettable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the level of this category.
|
||||
*/
|
||||
public void setLevel(Level level) {
|
||||
if (!mIsLevelSettable) {
|
||||
throw new RuntimeException("Can't set level for error " + mCode);
|
||||
}
|
||||
mLevel = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the level, including any overrides.
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return mLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the category's help text.
|
||||
*/
|
||||
public String getHelp() {
|
||||
return mHelp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of an error happening.
|
||||
*/
|
||||
public class Entry {
|
||||
private final Category mCategory;
|
||||
private final Position mPosition;
|
||||
private final String mMessage;
|
||||
|
||||
Entry(Category category, Position position, String message) {
|
||||
mCategory = category;
|
||||
mPosition = position;
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
public Category getCategory() {
|
||||
return mCategory;
|
||||
}
|
||||
|
||||
public Position getPosition() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return mMessage;
|
||||
}
|
||||
}
|
||||
|
||||
private void initLocked() {
|
||||
if (mCategories == null) {
|
||||
HashMap<Integer, Category> categories = new HashMap();
|
||||
for (Field field: getClass().getFields()) {
|
||||
if (Category.class.isAssignableFrom(field.getType())) {
|
||||
Category category = null;
|
||||
try {
|
||||
category = (Category)field.get(this);
|
||||
} catch (IllegalAccessException ex) {
|
||||
// Wrap and rethrow, this is always on this class, so it's
|
||||
// our programming error if this happens.
|
||||
throw new RuntimeException("Categories on Errors should be public.", ex);
|
||||
}
|
||||
Category prev = categories.put(category.getCode(), category);
|
||||
if (prev != null) {
|
||||
throw new RuntimeException("Duplicate categories with code "
|
||||
+ category.getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
mCategories = Collections.unmodifiableMap(categories);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of the category codes to the categories.
|
||||
*/
|
||||
public Map<Integer, Category> getCategories() {
|
||||
synchronized (mEntries) {
|
||||
initLocked();
|
||||
return mCategories;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an error with no source position.
|
||||
*/
|
||||
public void add(Category category, String message) {
|
||||
add(category, new Position(), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an error.
|
||||
*/
|
||||
public void add(Category category, Position pos, String message) {
|
||||
synchronized (mEntries) {
|
||||
initLocked();
|
||||
if (mCategories.get(category.getCode()) != category) {
|
||||
throw new RuntimeException("Errors.Category used from the wrong Errors object.");
|
||||
}
|
||||
mEntries.add(new Entry(category, pos, message));
|
||||
final Level level = category.getLevel();
|
||||
if (level == Level.WARNING || level == Level.ERROR) {
|
||||
mHadWarningOrError = true;
|
||||
}
|
||||
if (level == Level.ERROR) {
|
||||
mHadError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there has been a warning or an error yet.
|
||||
*/
|
||||
public boolean hadWarningOrError() {
|
||||
synchronized (mEntries) {
|
||||
return mHadWarningOrError;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there has been an error yet.
|
||||
*/
|
||||
public boolean hadError() {
|
||||
synchronized (mEntries) {
|
||||
return mHadError;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all entries that were added.
|
||||
*/
|
||||
public List<Entry> getEntries() {
|
||||
synchronized (mEntries) {
|
||||
return new ArrayList<Entry>(mEntries);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the errors.
|
||||
*/
|
||||
public void printErrors(PrintStream out) {
|
||||
synchronized (mEntries) {
|
||||
for (Entry entry: mEntries) {
|
||||
final Category category = entry.getCategory();
|
||||
final Level level = category.getLevel();
|
||||
if (level == Level.HIDDEN) {
|
||||
continue;
|
||||
}
|
||||
out.println(entry.getPosition() + "[" + level.getLabel() + " "
|
||||
+ category.getCode() + "] " + entry.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Error constants and error reporting.
|
||||
* <p>
|
||||
* <b>Naming Convention:</b>
|
||||
* <ul>
|
||||
* <li>ERROR_ for Categories with isLevelSettable false and Level.ERROR
|
||||
* <li>WARNING_ for Categories with isLevelSettable false and default WARNING or HIDDEN
|
||||
* <li>Don't have isLevelSettable true and not ERROR. (The constructor asserts this).
|
||||
* </ul>
|
||||
*/
|
||||
public class Errors extends ErrorReporter {
|
||||
|
||||
public final Category ERROR_COMMAND_LINE = new Category(1, false, Level.ERROR,
|
||||
"Error on the command line.");
|
||||
|
||||
public final Category WARNING_UNKNOWN_COMMAND_LINE_ERROR = new Category(2, true, Level.HIDDEN,
|
||||
"Passing unknown errors on the command line. Hidden by default for\n"
|
||||
+ "forward compatibility.");
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
public class Main {
|
||||
private final Errors mErrors;
|
||||
private final Options mOptions;
|
||||
|
||||
public Main(Errors errors, Options options) {
|
||||
mErrors = errors;
|
||||
mOptions = options;
|
||||
}
|
||||
|
||||
void run() {
|
||||
System.out.println("Hello World");
|
||||
|
||||
// TODO: Check the build environment to make sure we're running in a real
|
||||
// build environment, e.g. actually inside a source tree, with TARGET_PRODUCT
|
||||
// and TARGET_BUILD_VARIANT defined, etc.
|
||||
|
||||
// TODO: Run kati and extract the variables and convert all that into starlark files.
|
||||
|
||||
// TODO: Run starlark with all the generated ones and the hand written ones.
|
||||
|
||||
// TODO: Get the variables that were defined in starlark and use that to write
|
||||
// out the make, soong and bazel input files.
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Errors errors = new Errors();
|
||||
|
||||
Options options = Options.parse(errors, args);
|
||||
if (errors.hadError()) {
|
||||
Options.printHelp(System.err);
|
||||
System.err.println();
|
||||
errors.printErrors(System.err);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
switch (options.getAction()) {
|
||||
case DEFAULT:
|
||||
(new Main(errors, options)).run();
|
||||
errors.printErrors(System.err);
|
||||
return;
|
||||
case HELP:
|
||||
Options.printHelp(System.out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class Options {
|
||||
public enum Action {
|
||||
DEFAULT,
|
||||
HELP
|
||||
}
|
||||
|
||||
private Action mAction = Action.DEFAULT;
|
||||
|
||||
public Action getAction() {
|
||||
return mAction;
|
||||
}
|
||||
|
||||
public static void printHelp(PrintStream out) {
|
||||
out.println("usage: product_config");
|
||||
out.println();
|
||||
out.println("OPTIONS");
|
||||
out.println(" --hide ERROR_ID Suppress this error.");
|
||||
out.println(" --error ERROR_ID Make this ERROR_ID a fatal error.");
|
||||
out.println(" --help -h This message.");
|
||||
out.println(" --warning ERROR_ID Make this ERROR_ID a warning.");
|
||||
out.println();
|
||||
out.println("ERRORS");
|
||||
out.println(" The following are the errors that can be controlled on the");
|
||||
out.println(" commandline with the --hide --warning --error flags.");
|
||||
|
||||
TreeMap<Integer,Errors.Category> sorted = new TreeMap((new Errors()).getCategories());
|
||||
|
||||
for (final Errors.Category category: sorted.values()) {
|
||||
if (category.isLevelSettable()) {
|
||||
out.println(String.format(" %-3d %s", category.getCode(),
|
||||
category.getHelp().replace("\n", "\n ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Parser {
|
||||
private class ParseException extends Exception {
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private Errors mErrors;
|
||||
private String[] mArgs;
|
||||
private Options mResult = new Options();
|
||||
private int mIndex;
|
||||
|
||||
public Parser(Errors errors, String[] args) {
|
||||
mErrors = errors;
|
||||
mArgs = args;
|
||||
}
|
||||
|
||||
public Options parse() {
|
||||
try {
|
||||
while (mIndex < mArgs.length) {
|
||||
final String arg = mArgs[mIndex];
|
||||
|
||||
if ("--hide".equals(arg)) {
|
||||
handleErrorCode(arg, Errors.Level.HIDDEN);
|
||||
} else if ("--error".equals(arg)) {
|
||||
handleErrorCode(arg, Errors.Level.ERROR);
|
||||
} else if ("--help".equals(arg) || "-h".equals(arg)) {
|
||||
// Help overrides all other commands if there isn't an error, but
|
||||
// we will stop here.
|
||||
if (!mErrors.hadError()) {
|
||||
mResult.mAction = Action.HELP;
|
||||
}
|
||||
return mResult;
|
||||
} else if ("--warning".equals(arg)) {
|
||||
handleErrorCode(arg, Errors.Level.WARNING);
|
||||
} else {
|
||||
throw new ParseException("Unknown command line argument: " + arg);
|
||||
}
|
||||
|
||||
mIndex++;
|
||||
}
|
||||
} catch (ParseException ex) {
|
||||
mErrors.add(mErrors.ERROR_COMMAND_LINE, ex.getMessage());
|
||||
}
|
||||
|
||||
return mResult;
|
||||
}
|
||||
|
||||
private void addWarning(Errors.Category category, String message) {
|
||||
mErrors.add(category, message);
|
||||
}
|
||||
|
||||
private String getNextNonFlagArg() {
|
||||
if (mIndex == mArgs.length - 1) {
|
||||
return null;
|
||||
}
|
||||
if (mArgs[mIndex + 1].startsWith("-")) {
|
||||
return null;
|
||||
}
|
||||
mIndex++;
|
||||
return mArgs[mIndex];
|
||||
}
|
||||
|
||||
private int requireNextNumberArg(String arg) throws ParseException {
|
||||
final String val = getNextNonFlagArg();
|
||||
if (val == null) {
|
||||
throw new ParseException(arg + " requires a numeric argument.");
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(val);
|
||||
} catch (NumberFormatException ex) {
|
||||
throw new ParseException(arg + " requires a numeric argument. found: " + val);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleErrorCode(String arg, Errors.Level level) throws ParseException {
|
||||
final int code = requireNextNumberArg(arg);
|
||||
final Errors.Category category = mErrors.getCategories().get(code);
|
||||
if (category == null) {
|
||||
mErrors.add(mErrors.WARNING_UNKNOWN_COMMAND_LINE_ERROR,
|
||||
"Unknown error code: " + code);
|
||||
return;
|
||||
}
|
||||
if (!category.isLevelSettable()) {
|
||||
mErrors.add(mErrors.ERROR_COMMAND_LINE, "Can't set level for error " + code);
|
||||
return;
|
||||
}
|
||||
category.setLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the arguments and return an options object.
|
||||
* <p>
|
||||
* Updates errors with the hidden / warning / error levels.
|
||||
* <p>
|
||||
* Adds errors encountered to Errors object.
|
||||
*/
|
||||
public static Options parse(Errors errors, String[] args) {
|
||||
return (new Parser(errors, args)).parse();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
/**
|
||||
* Position in a source file.
|
||||
*/
|
||||
public class Position implements Comparable<Position> {
|
||||
/**
|
||||
* Sentinel line number for when there is no known line number.
|
||||
*/
|
||||
public static final int NO_LINE = -1;
|
||||
|
||||
private final String mFile;
|
||||
private final int mLine;
|
||||
|
||||
public Position() {
|
||||
mFile = null;
|
||||
mLine = NO_LINE;
|
||||
}
|
||||
|
||||
public Position(String file) {
|
||||
mFile = file;
|
||||
mLine = NO_LINE;
|
||||
}
|
||||
|
||||
public Position(String file, int line) {
|
||||
if (line < NO_LINE) {
|
||||
throw new IllegalArgumentException("Negative line number. file=" + file
|
||||
+ " line=" + line);
|
||||
}
|
||||
mFile = file;
|
||||
mLine = line;
|
||||
}
|
||||
|
||||
public int compareTo(Position that) {
|
||||
int result = mFile.compareTo(that.mFile);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
return mLine - that.mLine;
|
||||
}
|
||||
|
||||
public String getFile() {
|
||||
return mFile;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return mLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (mFile == null && mLine == NO_LINE) {
|
||||
return "";
|
||||
} else if (mFile == null && mLine != NO_LINE) {
|
||||
return "<unknown>:" + mLine + ": ";
|
||||
} else if (mFile != null && mLine == NO_LINE) {
|
||||
return mFile + ": ";
|
||||
} else { // if (mFile != null && mLine != NO_LINE)
|
||||
return mFile + ':' + mLine + ": ";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class ErrorReporterTest {
|
||||
/**
|
||||
* Test that errors can be recorded and retrieved.
|
||||
*/
|
||||
@Test
|
||||
public void testAdding() {
|
||||
TestErrors errors = new TestErrors();
|
||||
|
||||
errors.add(errors.ERROR, new Position("a", 12), "Errrororrrr");
|
||||
|
||||
Assert.assertTrue(errors.hadWarningOrError());
|
||||
Assert.assertTrue(errors.hadError());
|
||||
|
||||
List<TestErrors.Entry> entries = errors.getEntries();
|
||||
Assert.assertEquals(1, entries.size());
|
||||
|
||||
TestErrors.Entry entry = entries.get(0);
|
||||
Assert.assertEquals(errors.ERROR, entry.getCategory());
|
||||
Assert.assertEquals("a", entry.getPosition().getFile());
|
||||
Assert.assertEquals(12, entry.getPosition().getLine());
|
||||
Assert.assertEquals("Errrororrrr", entry.getMessage());
|
||||
|
||||
Assert.assertNotEquals("", errors.getErrorMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that not adding an error doesn't record errors.
|
||||
*/
|
||||
@Test
|
||||
public void testNoError() {
|
||||
TestErrors errors = new TestErrors();
|
||||
|
||||
Assert.assertFalse(errors.hadWarningOrError());
|
||||
Assert.assertFalse(errors.hadError());
|
||||
Assert.assertEquals("", errors.getErrorMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that not adding a warning doesn't record errors.
|
||||
*/
|
||||
@Test
|
||||
public void testWarning() {
|
||||
TestErrors errors = new TestErrors();
|
||||
|
||||
errors.add(errors.WARNING, "Waaaaarninggggg");
|
||||
|
||||
Assert.assertTrue(errors.hadWarningOrError());
|
||||
Assert.assertFalse(errors.hadError());
|
||||
Assert.assertNotEquals("", errors.getErrorMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that hidden warnings don't report.
|
||||
*/
|
||||
@Test
|
||||
public void testHidden() {
|
||||
TestErrors errors = new TestErrors();
|
||||
|
||||
errors.add(errors.HIDDEN, "Hidddeennn");
|
||||
|
||||
Assert.assertFalse(errors.hadWarningOrError());
|
||||
Assert.assertFalse(errors.hadError());
|
||||
Assert.assertEquals("", errors.getErrorMessages());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test changing an error level.
|
||||
*/
|
||||
@Test
|
||||
public void testSetLevel() {
|
||||
TestErrors errors = new TestErrors();
|
||||
Assert.assertEquals(TestErrors.Level.ERROR, errors.ERROR.getLevel());
|
||||
|
||||
errors.ERROR.setLevel(TestErrors.Level.WARNING);
|
||||
|
||||
Assert.assertEquals(TestErrors.Level.WARNING, errors.ERROR.getLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that changing a fixed error fails.
|
||||
*/
|
||||
@Test
|
||||
public void testSetLevelFails() {
|
||||
TestErrors errors = new TestErrors();
|
||||
Assert.assertEquals(TestErrors.Level.ERROR, errors.ERROR_FIXED.getLevel());
|
||||
|
||||
boolean exceptionThrown = false;
|
||||
try {
|
||||
errors.ERROR_FIXED.setLevel(TestErrors.Level.WARNING);
|
||||
} catch (RuntimeException ex) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
|
||||
Assert.assertTrue(exceptionThrown);
|
||||
Assert.assertEquals(TestErrors.Level.ERROR, errors.ERROR_FIXED.getLevel());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class OptionsTest {
|
||||
@Test
|
||||
public void testErrorMissingLast() {
|
||||
final Errors errors = new Errors();
|
||||
|
||||
final Options options = Options.parse(errors, new String[] {
|
||||
"--error"
|
||||
});
|
||||
|
||||
Assert.assertNotEquals("", TestErrors.getErrorMessages(errors));
|
||||
Assert.assertEquals(Options.Action.DEFAULT, options.getAction());
|
||||
TestErrors.assertHasEntry(errors.ERROR_COMMAND_LINE, errors);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorMissingNotLast() {
|
||||
final Errors errors = new Errors();
|
||||
|
||||
final Options options = Options.parse(errors, new String[] {
|
||||
"--error", "--warning", "2"
|
||||
});
|
||||
|
||||
Assert.assertNotEquals("", TestErrors.getErrorMessages(errors));
|
||||
Assert.assertEquals(Options.Action.DEFAULT, options.getAction());
|
||||
TestErrors.assertHasEntry(errors.ERROR_COMMAND_LINE, errors);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorNotNumeric() {
|
||||
final Errors errors = new Errors();
|
||||
|
||||
final Options options = Options.parse(errors, new String[] {
|
||||
"--error", "notgood"
|
||||
});
|
||||
|
||||
Assert.assertNotEquals("", TestErrors.getErrorMessages(errors));
|
||||
Assert.assertEquals(Options.Action.DEFAULT, options.getAction());
|
||||
TestErrors.assertHasEntry(errors.ERROR_COMMAND_LINE, errors);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorInvalidError() {
|
||||
final Errors errors = new Errors();
|
||||
|
||||
final Options options = Options.parse(errors, new String[] {
|
||||
"--error", "50000"
|
||||
});
|
||||
|
||||
Assert.assertEquals("", TestErrors.getErrorMessages(errors));
|
||||
Assert.assertEquals(Options.Action.DEFAULT, options.getAction());
|
||||
TestErrors.assertHasEntry(errors.WARNING_UNKNOWN_COMMAND_LINE_ERROR, errors);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorOne() {
|
||||
final Errors errors = new Errors();
|
||||
|
||||
final Options options = Options.parse(errors, new String[] {
|
||||
"--error", "2"
|
||||
});
|
||||
|
||||
Assert.assertEquals("", TestErrors.getErrorMessages(errors));
|
||||
Assert.assertEquals(Options.Action.DEFAULT, options.getAction());
|
||||
Assert.assertFalse(errors.hadWarningOrError());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWarningOne() {
|
||||
final Errors errors = new Errors();
|
||||
|
||||
final Options options = Options.parse(errors, new String[] {
|
||||
"--warning", "2"
|
||||
});
|
||||
|
||||
Assert.assertEquals("", TestErrors.getErrorMessages(errors));
|
||||
Assert.assertEquals(Options.Action.DEFAULT, options.getAction());
|
||||
Assert.assertFalse(errors.hadWarningOrError());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHideOne() {
|
||||
final Errors errors = new Errors();
|
||||
|
||||
final Options options = Options.parse(errors, new String[] {
|
||||
"--hide", "2"
|
||||
});
|
||||
|
||||
Assert.assertEquals("", TestErrors.getErrorMessages(errors));
|
||||
Assert.assertEquals(Options.Action.DEFAULT, options.getAction());
|
||||
Assert.assertFalse(errors.hadWarningOrError());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.build.config;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Errors for testing.
|
||||
*/
|
||||
public class TestErrors extends ErrorReporter {
|
||||
|
||||
public static final int ERROR_CODE = 1;
|
||||
|
||||
public final Category ERROR = new Category(ERROR_CODE, true, Level.ERROR,
|
||||
"An error.");
|
||||
|
||||
public static final int WARNING_CODE = 2;
|
||||
|
||||
public final Category WARNING = new Category(WARNING_CODE, true, Level.WARNING,
|
||||
"A warning.");
|
||||
|
||||
public static final int HIDDEN_CODE = 3;
|
||||
|
||||
public final Category HIDDEN = new Category(HIDDEN_CODE, true, Level.HIDDEN,
|
||||
"A hidden warning.");
|
||||
|
||||
public static final int ERROR_FIXED_CODE = 4;
|
||||
|
||||
public final Category ERROR_FIXED = new Category(ERROR_FIXED_CODE, false, Level.ERROR,
|
||||
"An error that can't have its level changed.");
|
||||
|
||||
public void assertHasEntry(Errors.Category category) {
|
||||
assertHasEntry(category, this);
|
||||
}
|
||||
|
||||
public String getErrorMessages() {
|
||||
return getErrorMessages(this);
|
||||
}
|
||||
|
||||
public static void assertHasEntry(Errors.Category category, ErrorReporter errors) {
|
||||
StringBuilder found = new StringBuilder();
|
||||
for (Errors.Entry entry: errors.getEntries()) {
|
||||
if (entry.getCategory() == category) {
|
||||
return;
|
||||
}
|
||||
found.append(' ');
|
||||
found.append(entry.getCategory().getCode());
|
||||
}
|
||||
throw new AssertionError("No error category " + category.getCode() + " found."
|
||||
+ " Found category codes were:" + found);
|
||||
}
|
||||
|
||||
public static String getErrorMessages(ErrorReporter errors) {
|
||||
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
try {
|
||||
errors.printErrors(new PrintStream(stream, true, StandardCharsets.UTF_8.name()));
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
// utf-8 is always supported
|
||||
}
|
||||
return new String(stream.toByteArray(), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue