Refactor existing android tz generation tools
Refactor existing android tz generation tools to enable the addition of
other, similar tools.
Also, switch to atest for the test code.
This commit contains small corrects to comments and a test fix.
Bug: 143451294
Test: atest tztools_common_tests
Test: atest tzlookup_generator_test
Change-Id: Ib1ca79afd711a8c7b133c8e85aba6ca6818905e5
diff --git a/input_tools/android/common/Android.bp b/input_tools/android/common/Android.bp
new file mode 100644
index 0000000..4baf656
--- /dev/null
+++ b/input_tools/android/common/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2019 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.
+
+
+// Code common to various time zone host tools.
+java_library_host {
+ name: "tztools_common",
+
+ srcs: ["src/main/java/**/*.java"],
+}
+
+// Code common to various time zone host tests.
+java_library_host {
+ name: "tztools_common_testing",
+
+ srcs: ["src/testing/java/**/*.java"],
+ libs: [
+ "junit",
+ ],
+}
+
+// Tests for tztools_common and tztools_common_testing.
+java_test_host {
+ name: "tztools_common_tests",
+
+ srcs: ["src/test/java/**/*.java"],
+ static_libs: [
+ "junit",
+ "tztools_common",
+ "tztools_common_testing",
+ ],
+}
diff --git a/input_tools/android/common/README.android b/input_tools/android/common/README.android
new file mode 100644
index 0000000..7c7b63f
--- /dev/null
+++ b/input_tools/android/common/README.android
@@ -0,0 +1 @@
+Common code used in several tools.
diff --git a/input_tools/android/common/src/main/java/com/android/libcore/timezone/util/Errors.java b/input_tools/android/common/src/main/java/com/android/libcore/timezone/util/Errors.java
new file mode 100644
index 0000000..24c608c
--- /dev/null
+++ b/input_tools/android/common/src/main/java/com/android/libcore/timezone/util/Errors.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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.libcore.timezone.util;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Stores context, errors and error severity for logging and flow control.
+ */
+public final class Errors {
+
+ private final static int LEVEL_WARNING = 1;
+ private final static int LEVEL_ERROR = 2;
+ private final static int LEVEL_FATAL = 3;
+
+ private int level = 0;
+
+ private final LinkedList<String> scopes = new LinkedList<>();
+ private final List<String> messages = new ArrayList<>();
+
+ public Errors() {
+ }
+
+ public void pushScope(String name) {
+ scopes.add(name);
+ }
+
+ public String popScope() {
+ return scopes.removeLast();
+ }
+
+ public void addFatal(String msg) {
+ level = Math.max(level, LEVEL_FATAL);
+ add(msg);
+ }
+
+ public void addError(String msg) {
+ level = Math.max(level, LEVEL_ERROR);
+ add(msg);
+ }
+
+ public void addWarning(String msg) {
+ level = Math.max(level, LEVEL_WARNING);
+ add(msg);
+ }
+
+ public String asString() {
+ StringBuilder sb = new StringBuilder();
+ for (String message : messages) {
+ sb.append(message);
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+ public boolean isEmpty() {
+ return messages.isEmpty();
+ }
+
+ public boolean hasError() {
+ return level >= LEVEL_ERROR;
+ }
+
+ public boolean hasFatal() {
+ return level >= LEVEL_FATAL;
+ }
+
+ private void add(String msg) {
+ messages.add(scopes.toString() + ": " + msg);
+ }
+}
diff --git a/input_tools/android/common/src/test/java/com/android/libcore/timezone/util/ErrorsTest.java b/input_tools/android/common/src/test/java/com/android/libcore/timezone/util/ErrorsTest.java
new file mode 100644
index 0000000..5a6e717
--- /dev/null
+++ b/input_tools/android/common/src/test/java/com/android/libcore/timezone/util/ErrorsTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 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.libcore.timezone.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.libcore.timezone.testing.TestUtils;
+
+public class ErrorsTest {
+
+ @Test
+ public void warnings() {
+ Errors errors = new Errors();
+ assertTrue(errors.isEmpty());
+ assertFalse(errors.hasError());
+ assertFalse(errors.hasFatal());
+
+ errors.addWarning("Hello");
+ assertFalse(errors.isEmpty());
+ assertFalse(errors.hasError());
+ assertFalse(errors.hasFatal());
+
+ TestUtils.assertContains(errors.asString(), "Hello");
+ }
+
+ @Test
+ public void error() {
+ Errors errors = new Errors();
+ assertTrue(errors.isEmpty());
+ assertFalse(errors.hasError());
+ assertFalse(errors.hasFatal());
+
+ errors.addError("Hello");
+ assertFalse(errors.isEmpty());
+ assertTrue(errors.hasError());
+ assertFalse(errors.hasFatal());
+
+ TestUtils.assertContains(errors.asString(), "Hello");
+ }
+
+ @Test
+ public void fatal() {
+ Errors errors = new Errors();
+ assertTrue(errors.isEmpty());
+ assertFalse(errors.hasError());
+ assertFalse(errors.hasFatal());
+
+ errors.addFatal("Hello");
+ assertFalse(errors.isEmpty());
+ assertTrue(errors.hasError());
+ assertTrue(errors.hasFatal());
+
+ TestUtils.assertContains(errors.asString(), "Hello");
+ }
+
+ @Test
+ public void scope() {
+ Errors errors = new Errors();
+
+ errors.addWarning("Hello");
+
+ errors.pushScope("Monty Python");
+ errors.addError("John Cleese");
+
+ errors.pushScope("Holy grail");
+ errors.addFatal("Silly place");
+ errors.popScope();
+
+ errors.addError("Michael Palin");
+
+ errors.pushScope("Parrot sketch");
+ errors.addFatal("Fjords");
+ errors.popScope();
+
+ String[] lines = errors.asString().split("\n");
+
+ String line0 = lines[0];
+ TestUtils.assertContains(line0, "Hello");
+ TestUtils.assertAbsent(line0, "Monty Python");
+
+ String line1 = lines[1];
+ TestUtils.assertContains(line1, "Monty Python");
+ TestUtils.assertAbsent(line1, "Holy grail");
+ TestUtils.assertContains(line1, "John Cleese");
+
+ String line2 = lines[2];
+ TestUtils.assertContains(line2, "Monty Python", "Holy grail");
+ TestUtils.assertAbsent(line2, "Parrot sketch");
+ TestUtils.assertContains(line2, "Silly place");
+
+ String line3 = lines[3];
+ TestUtils.assertContains(line3, "Monty Python");
+ TestUtils.assertAbsent(line3, "Holy grail");
+ TestUtils.assertContains(line3, "Michael Palin");
+
+ String line4 = lines[4];
+ TestUtils.assertContains(line4, "Monty Python", "Parrot sketch");
+ TestUtils.assertAbsent(line4, "Holy grail");
+ TestUtils.assertContains(line4, "Fjords");
+ }
+
+}
diff --git a/input_tools/android/common/src/testing/java/com/android/libcore/timezone/testing/TestUtils.java b/input_tools/android/common/src/testing/java/com/android/libcore/timezone/testing/TestUtils.java
new file mode 100644
index 0000000..55bb215
--- /dev/null
+++ b/input_tools/android/common/src/testing/java/com/android/libcore/timezone/testing/TestUtils.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 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.libcore.timezone.testing;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Arbitrary static utility methods to help with testing.
+ */
+public final class TestUtils {
+
+ private TestUtils() {}
+
+ public static String createFile(Path dir, String... lines) throws IOException {
+ Path tempFile = Files.createTempFile(dir, "tmp", null /* suffix */);
+ Files.write(tempFile, Arrays.asList(lines), StandardCharsets.US_ASCII);
+ return tempFile.toString();
+ }
+
+ public static void deleteDir(Path tempDir) throws IOException {
+ FileVisitor<? super Path> deleter = new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ return delete(file);
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+ throws IOException {
+ return delete(dir);
+ }
+
+ private FileVisitResult delete(Path file) throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+ };
+ Files.walkFileTree(tempDir, deleter);
+ }
+
+ public static void assertAbsent(String s, String... absents) {
+ for (String absent : absents) {
+ assertFalse(s + " must not contain " + absent, s.contains(absent));
+ }
+ }
+
+ public static void assertContains(String s, String... expecteds) {
+ for (String expected : expecteds) {
+ assertTrue(s + " must contain " + expected, s.contains(expected));
+ }
+ }
+}