summaryrefslogtreecommitdiff
path: root/errorprone/tests
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2020-10-15 15:38:38 -0600
committerJeff Sharkey <jsharkey@android.com>2020-10-16 13:44:22 -0600
commita52266b3e352e33bae1ce77cfef7b16219f4817e (patch)
tree9f08831f9cd2a3e03760d823901db74133a12034 /errorprone/tests
parentaf7c5f95cb963fcf482b84af434776337f69dbad (diff)
Recommend efficient String operations.
Android offers several efficient alternatives to some upstream String operations, such as the newly added TextUtils.formatSimple(). This checker also detects and discourages transparent StringBuilder operations related to Preconditions, where we always pay the cost of building the failure message string, even in the successful case. Bug: 170978902 Test: atest error_prone_android_framework_test Change-Id: I8cef4c50d8b0da3f1e66727dfa724ad44b88963b
Diffstat (limited to 'errorprone/tests')
-rw-r--r--errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java119
-rw-r--r--errorprone/tests/res/android/util/Preconditions.java43
2 files changed, 162 insertions, 0 deletions
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java
new file mode 100644
index 000000000000..a755564d52dd
--- /dev/null
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.google.errorprone.bugpatterns.android;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import com.google.errorprone.CompilationTestHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class EfficientStringsCheckerTest {
+ private CompilationTestHelper compilationHelper;
+
+ @Before
+ public void setUp() {
+ compilationHelper = CompilationTestHelper.newInstance(
+ EfficientStringsChecker.class, getClass());
+ }
+
+ @Test
+ public void testSimple() {
+ assertTrue(EfficientStringsChecker.isSimple(""));
+ assertTrue(EfficientStringsChecker.isSimple("%s"));
+ assertTrue(EfficientStringsChecker.isSimple("String %s%s and %%%% number %d%d together"));
+
+ assertFalse(EfficientStringsChecker.isSimple("%04d"));
+ assertFalse(EfficientStringsChecker.isSimple("%02x:%02x:%02x"));
+ }
+
+ @Test
+ public void testFormat() {
+ compilationHelper
+ .addSourceLines("Example.java",
+ "import java.util.Locale;",
+ "public class Example {",
+ " public void example(String str) {",
+ " String.format(str, str);",
+ " // BUG: Diagnostic contains:",
+ " String.format(\"foo %s bar\", str);",
+ " // BUG: Diagnostic contains:",
+ " String.format(\"foo %d bar\", 42);",
+ " String.format(\"foo %04d bar\", 42);",
+ " }",
+ " public void exampleLocale(String str) {",
+ " String.format(Locale.US, str, str);",
+ " // BUG: Diagnostic contains:",
+ " String.format(Locale.US, \"foo %s bar\", str);",
+ " // BUG: Diagnostic contains:",
+ " String.format(Locale.US, \"foo %d bar\", 42);",
+ " String.format(Locale.US, \"foo %04d bar\", 42);",
+ " }",
+ "}")
+ .doTest();
+ }
+
+ @Test
+ public void testPreconditions() {
+ compilationHelper
+ .addSourceFile("/android/util/Preconditions.java")
+ .addSourceLines("Example.java",
+ "import android.util.Preconditions;",
+ "import java.util.Objects;",
+ "public class Example {",
+ " String str;",
+ " public void checkState(boolean val) {",
+ " Preconditions.checkState(val);",
+ " Preconditions.checkState(val, str);",
+ " Preconditions.checkState(val, \"foo\");",
+ " Preconditions.checkState(val, \"foo\" + \"bar\");",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkState(val, \"foo \" + val);",
+ " }",
+ " public void checkArgument(boolean val) {",
+ " Preconditions.checkArgument(val);",
+ " Preconditions.checkArgument(val, str);",
+ " Preconditions.checkArgument(val, \"foo\");",
+ " Preconditions.checkArgument(val, \"foo\" + \"bar\");",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkArgument(val, \"foo \" + val);",
+ " }",
+ " public void checkNotNull(Object val) {",
+ " Preconditions.checkNotNull(val);",
+ " Preconditions.checkNotNull(val, str);",
+ " Preconditions.checkNotNull(val, \"foo\");",
+ " Preconditions.checkNotNull(val, \"foo\" + \"bar\");",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkNotNull(val, \"foo \" + val);",
+ " }",
+ " public void requireNonNull(Object val) {",
+ " Objects.requireNonNull(val);",
+ " Objects.requireNonNull(val, str);",
+ " Objects.requireNonNull(val, \"foo\");",
+ " Objects.requireNonNull(val, \"foo\" + \"bar\");",
+ " // BUG: Diagnostic contains:",
+ " Objects.requireNonNull(val, \"foo \" + val);",
+ " }",
+ "}")
+ .doTest();
+ }
+}
diff --git a/errorprone/tests/res/android/util/Preconditions.java b/errorprone/tests/res/android/util/Preconditions.java
new file mode 100644
index 000000000000..558cdaf483a4
--- /dev/null
+++ b/errorprone/tests/res/android/util/Preconditions.java
@@ -0,0 +1,43 @@
+/*
+ * 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 android.util;
+
+public class Preconditions {
+ public static void checkArgument(boolean expression) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static void checkArgument(boolean expression, Object errorMessage) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static <T> T checkNotNull(T reference) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static <T> T checkNotNull(T reference, Object errorMessage) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static void checkState(boolean expression) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static void checkState(boolean expression, String message) {
+ throw new UnsupportedOperationException();
+ }
+}