Adding extra validation to TzDataBundleInstaller

Adding extra validation to TzDataBundleInstaller. This requires
that the test data the test is given is actually valid.
To provide valid test data the ZoneInfoTestHelper has been moved
into a support library under tzdata that can be used from the
installer and libcore test code.

Bug: 31008728
Test: CtsLibcoreTestCases
Change-Id: I5035b4b292f2574b2d58829fb0c2df9efac470d6
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 33b127c..856f4d3 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -212,7 +212,8 @@
 	core-tests-support \
 	mockwebserver \
 	nist-pkix-tests \
-	sqlite-jdbc
+	sqlite-jdbc \
+	tzdata-testing
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_ERROR_PRONE_FLAGS := -Xep:TryFailThrowable:ERROR
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -360,7 +361,7 @@
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
     LOCAL_NO_STANDARD_LIBRARIES := true
     LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex okhttp-hostdex bouncycastle-hostdex junit-hostdex core-tests-support-hostdex mockito-api-hostdex
-    LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host core-test-rules-hostdex
+    LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host core-test-rules-hostdex tzdata-testing-hostdex
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
     LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/luni/src/test/java/libcore/util/ZoneInfoDBTest.java b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
index f7a9add..99691d5 100644
--- a/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
+++ b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
@@ -21,6 +21,8 @@
 import java.io.IOException;
 import java.io.RandomAccessFile;
 
+import libcore.tzdata.testing.ZoneInfoTestHelper;
+
 import static libcore.util.ZoneInfoDB.TzData.SIZEOF_INDEX_ENTRY;
 
 public class ZoneInfoDBTest extends junit.framework.TestCase {
diff --git a/luni/src/test/java/libcore/util/ZoneInfoTest.java b/luni/src/test/java/libcore/util/ZoneInfoTest.java
index 26138fe..d2cd1fb 100644
--- a/luni/src/test/java/libcore/util/ZoneInfoTest.java
+++ b/luni/src/test/java/libcore/util/ZoneInfoTest.java
@@ -24,6 +24,7 @@
 import java.util.Arrays;
 import java.util.Date;
 import libcore.io.BufferIterator;
+import libcore.tzdata.testing.ZoneInfoTestHelper;
 
 /**
  * Tests for {@link ZoneInfo}
diff --git a/tzdata/Android.mk b/tzdata/Android.mk
index 23ebf0c..39499f6 100644
--- a/tzdata/Android.mk
+++ b/tzdata/Android.mk
@@ -14,7 +14,4 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# Subprojects with separate makefiles
-subdirs := tools tools2 update_test_app update update2
-subdir_makefiles := $(call all-named-subdir-makefiles,$(subdirs))
-include $(subdir_makefiles)
+include $(call all-subdir-makefiles)
\ No newline at end of file
diff --git a/tzdata/testing/Android.mk b/tzdata/testing/Android.mk
new file mode 100644
index 0000000..4765179
--- /dev/null
+++ b/tzdata/testing/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2015 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+# Library of test-support classes for tzdata updates. Shared between CTS and other tests.
+include $(CLEAR_VARS)
+LOCAL_MODULE := tzdata-testing
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main)
+LOCAL_JAVACFLAGS := -encoding UTF-8
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Host version of the above library. For libcore host testing.
+include $(CLEAR_VARS)
+LOCAL_MODULE := tzdata-testing-hostdex
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main)
+LOCAL_JAVACFLAGS := -encoding UTF-8
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY)
diff --git a/luni/src/test/java/libcore/util/ZoneInfoTestHelper.java b/tzdata/testing/src/main/libcore/tzdata/testing/ZoneInfoTestHelper.java
similarity index 99%
rename from luni/src/test/java/libcore/util/ZoneInfoTestHelper.java
rename to tzdata/testing/src/main/libcore/tzdata/testing/ZoneInfoTestHelper.java
index 5d62716..a3b2a14 100644
--- a/luni/src/test/java/libcore/util/ZoneInfoTestHelper.java
+++ b/tzdata/testing/src/main/libcore/tzdata/testing/ZoneInfoTestHelper.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package libcore.util;
+package libcore.tzdata.testing;
 
 import java.io.ByteArrayOutputStream;
 import java.nio.ByteBuffer;
diff --git a/tzdata/update2/Android.mk b/tzdata/update2/Android.mk
index 60be03d..b206021 100644
--- a/tzdata/update2/Android.mk
+++ b/tzdata/update2/Android.mk
@@ -30,6 +30,6 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES := $(call all-java-files-under, src/test)
 LOCAL_JAVACFLAGS := -encoding UTF-8
-LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update2 tzdata_tools2
+LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update2 tzdata_tools2 tzdata-testing
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tzdata/update2/src/main/libcore/tzdata/update2/TzDataBundleInstaller.java b/tzdata/update2/src/main/libcore/tzdata/update2/TzDataBundleInstaller.java
index 127baf8..1ffe860 100644
--- a/tzdata/update2/src/main/libcore/tzdata/update2/TzDataBundleInstaller.java
+++ b/tzdata/update2/src/main/libcore/tzdata/update2/TzDataBundleInstaller.java
@@ -96,6 +96,20 @@
                 return false;
             }
 
+            File zoneInfoFile = new File(workingDir, ConfigBundle.ZONEINFO_FILE_NAME);
+            ZoneInfoDB.TzData tzData = ZoneInfoDB.TzData.loadTzData(zoneInfoFile.getPath());
+            if (tzData == null) {
+                Slog.i(logTag, "Update not applied: " + zoneInfoFile + " could not be loaded");
+                return false;
+            }
+            try {
+                tzData.validate();
+            } catch (IOException e) {
+                Slog.i(logTag, "Update not applied: " + zoneInfoFile + " failed validation", e);
+                return false;
+            } finally {
+                tzData.close();
+            }
             // TODO(nfuller): Add deeper validity checks / canarying before applying.
             // http://b/31008728
 
diff --git a/tzdata/update2/src/test/libcore/tzdata/update2/TzDataBundleInstallerTest.java b/tzdata/update2/src/test/libcore/tzdata/update2/TzDataBundleInstallerTest.java
index b55a257..34afcf1 100644
--- a/tzdata/update2/src/test/libcore/tzdata/update2/TzDataBundleInstallerTest.java
+++ b/tzdata/update2/src/test/libcore/tzdata/update2/TzDataBundleInstallerTest.java
@@ -22,11 +22,11 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 import libcore.io.Streams;
+import libcore.tzdata.testing.ZoneInfoTestHelper;
 import libcore.tzdata.update2.tools.TzDataBundleBuilder;
 
 /**
@@ -334,12 +334,10 @@
     }
 
     private void createTzDataFile(File file, String rulesVersion) {
-        byte[] bytes = new byte[12];
-        // This just writes the part of the header that contains the rules version, which is enough
-        // to satisfy the installer.
-        byte[] headerBytes = ("tzdata" + rulesVersion).getBytes(StandardCharsets.US_ASCII);
-        System.arraycopy(headerBytes, 0, bytes, 0, headerBytes.length);
-
+        byte[] bytes = new ZoneInfoTestHelper.TzDataBuilder()
+                .initializeToValid()
+                .setHeaderMagic("tzdata" + rulesVersion)
+                .build();
         try (FileOutputStream fos = new FileOutputStream(file)) {
             fos.write(bytes);
         } catch (IOException e) {