diff options
author | Tor Norbye <tnorbye@google.com> | 2012-09-11 12:47:13 -0700 |
---|---|---|
committer | android code review <noreply-gerritcodereview@google.com> | 2012-09-11 12:47:13 -0700 |
commit | b081e294e4b217f956b969a12400ea3f920cef41 (patch) | |
tree | 2a6da9e1b832e41874c0511a815d92d1cdfb6e39 | |
parent | 89fec25870f875b9ca02677ed9070139fcfed2f0 (diff) | |
parent | d1f0bd93d0bee5b300154719726a7353732f571f (diff) | |
download | sdk-b081e294e4b217f956b969a12400ea3f920cef41.zip sdk-b081e294e4b217f956b969a12400ea3f920cef41.tar.gz sdk-b081e294e4b217f956b969a12400ea3f920cef41.tar.bz2 |
Merge "Add unit test for lint CLI"
4 files changed, 198 insertions, 3 deletions
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java index cf45b2e..e780d79 100644 --- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java +++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java @@ -18,6 +18,7 @@ package com.android.tools.lint.client.api; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.annotations.VisibleForTesting; import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.Detector; import com.android.tools.lint.detector.api.Issue; @@ -238,4 +239,15 @@ public abstract class IssueRegistry { } return sIdToIssue.get(id); } + + /** + * Reset the registry such that it recomputes its available issues. + * <p> + * NOTE: This is only intended for testing purposes. + */ + @VisibleForTesting + protected static void reset() { + sIdToIssue = null; + sCategories = null; + } } diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java index 8915e81..ca73df0 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java @@ -20,6 +20,7 @@ import static com.android.tools.lint.detector.api.LintUtils.assertionsEnabled; import static com.android.tools.lint.detector.api.LintUtils.endsWith; import com.android.annotations.NonNull; +import com.android.annotations.VisibleForTesting; import com.android.prefs.AndroidLocation; import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.tools.lint.client.api.IssueRegistry; @@ -319,4 +320,14 @@ public class BuiltinIssueRegistry extends IssueRegistry { return sAdtFixes.contains(issue); } + + /** + * Reset the registry such that it recomputes its available issues. + * <p> + * NOTE: This is only intended for testing purposes. + */ + @VisibleForTesting + public static void reset() { + IssueRegistry.reset(); + } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/MainTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/MainTest.java index d4fd069..6b4ca31 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/MainTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/MainTest.java @@ -16,10 +16,25 @@ package com.android.tools.lint; -import junit.framework.TestCase; +import com.android.tools.lint.checks.AbstractCheckTest; +import com.android.tools.lint.checks.AccessibilityDetector; +import com.android.tools.lint.checks.BuiltinIssueRegistry; +import com.android.tools.lint.detector.api.Detector; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintStream; +import java.security.Permission; +import java.util.List; @SuppressWarnings("javadoc") -public class MainTest extends TestCase { +public class MainTest extends AbstractCheckTest { + @Override + protected void setUp() throws Exception { + super.setUp(); + BuiltinIssueRegistry.reset(); + } + public void testWrap() { String s = "Hardcoding text attributes directly in layout files is bad for several reasons:\n" + @@ -65,4 +80,143 @@ public class MainTest extends TestCase { " adding new translations for existing string resources.\n", wrapped); } + + protected String checkLint(String[] args, List<File> files) throws Exception { + PrintStream previousOut = System.out; + try { + final ByteArrayOutputStream output = new ByteArrayOutputStream(); + System.setOut(new PrintStream(output)); + + Main.main(args); + + return output.toString(); + } finally { + System.setOut(previousOut); + } + } + + private void checkDriver(String expectedOutput, String expectedError, String[] args) + throws Exception { + PrintStream previousOut = System.out; + PrintStream previousErr = System.err; + try { + // Trap System.exit calls: + System.setSecurityManager(new SecurityManager() { + @Override + public void checkPermission(Permission perm) + { + // allow anything. + } + @Override + public void checkPermission(Permission perm, Object context) + { + // allow anything. + } + @Override + public void checkExit(int status) { + throw new ExitException(); + } + }); + + final ByteArrayOutputStream output = new ByteArrayOutputStream(); + System.setOut(new PrintStream(output)); + final ByteArrayOutputStream error = new ByteArrayOutputStream(); + System.setErr(new PrintStream(error)); + + try { + Main.main(args); + } catch (ExitException e) { + // Allow + } + + assertEquals(expectedError, cleanup(error.toString())); + assertEquals(expectedOutput, cleanup(output.toString())); + } finally { + // Re-enable system exit for unit test + System.setSecurityManager(null); + + System.setOut(previousOut); + System.setErr(previousErr); + } + } + + + public void testArguments() throws Exception { + checkDriver( + // Expected output + "\n" + + "Scanning MainTest_testArguments: .\n" + + "res/layout/accessibility.xml:4: Warning: [Accessibility] Missing contentDescription attribute on image [ContentDescription]\n" + + " <ImageView android:id=\"@+id/android_logo\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "res/layout/accessibility.xml:5: Warning: [Accessibility] Missing contentDescription attribute on image [ContentDescription]\n" + + " <ImageButton android:importantForAccessibility=\"yes\" android:id=\"@+id/android_logo2\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:src=\"@drawable/android_button\" android:focusable=\"false\" android:clickable=\"false\" android:layout_weight=\"1.0\" />\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "0 errors, 2 warnings\n", + + // Expected error + "", + + // Args + new String[] { + "--check", + "ContentDescription", + "--disable", + "LintError", + getProjectDir(null, "res/layout/accessibility.xml").getPath() + + }); + } + + public void testShowDescription() throws Exception { + checkDriver( + // Expected output + "NewApi\n" + + "------\n" + + "Summary: Finds API accesses to APIs that are not supported in all targeted API\n" + + "versions\n" + + "\n" + + "Priority: 6 / 10\n" + + "Severity: Error\n" + + "Category: Correctness\n" + + "\n" + + "This check scans through all the Android API calls in the application and\n" + + "warns about any calls that are not available on all versions targeted by this\n" + + "application (according to its minimum SDK attribute in the manifest).\n" + + "\n" + + "If you really want to use this API and don't need to support older devices\n" + + "just set the minSdkVersion in your AndroidManifest.xml file.\n" + + "If your code is deliberately accessing newer APIs, and you have ensured (e.g.\n" + + "with conditional execution) that this code will only ever be called on a\n" + + "supported platform, then you can annotate your class or method with the\n" + + "@TargetApi annotation specifying the local minimum SDK to apply, such as\n" + + "@TargetApi(11), such that this check considers 11 rather than your manifest\n" + + "file's minimum SDK as the required API level.\n" + + "\n" + + "\n", + + // Expected error + "", + + // Args + new String[] { + "--show", + "NewApi" + }); + } + + + @Override + protected Detector getDetector() { + // Sample issue to check by the main driver + return new AccessibilityDetector(); + } + + private static class ExitException extends SecurityException { + private static final long serialVersionUID = 1L; + + private ExitException() { + super("Unit test"); + } + } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java index de5b65e..8469644 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java @@ -188,7 +188,8 @@ public abstract class AbstractCheckTest extends TestCase { private StringBuilder mOutput = null; - private static File sTempDir = null; + protected static File sTempDir = null; + protected File getTempDir() { if (sTempDir == null) { File base = new File(System.getProperty("java.io.tmpdir")); //$NON-NLS-1$ @@ -286,6 +287,23 @@ public abstract class AbstractCheckTest extends TestCase { return false; } + protected static String cleanup(String result) throws IOException { + if (sTempDir != null && result.contains(sTempDir.getPath())) { + result = result.replace(sTempDir.getCanonicalFile().getPath(), "/TESTROOT"); + result = result.replace(sTempDir.getAbsoluteFile().getPath(), "/TESTROOT"); + result = result.replace(sTempDir.getPath(), "/TESTROOT"); + } + + // The output typically contains a few directory/filenames. + // On Windows we need to change the separators to the unix-style + // forward slash to make the test as OS-agnostic as possible. + if (File.separatorChar != '/') { + result = result.replace(File.separatorChar, '/'); + } + + return result; + } + public class TestLintClient extends Main { private StringWriter mWriter = new StringWriter(); |