Refactor zipalign to allow unit tests
Test: Self-tested
Bug: NA
Change-Id: If5e42735853e1508fbeb9fb420a9a9f129c2218f
diff --git a/tools/zipalign/Android.bp b/tools/zipalign/Android.bp
index 8e6196d..b39c278 100644
--- a/tools/zipalign/Android.bp
+++ b/tools/zipalign/Android.bp
@@ -4,8 +4,8 @@
// Zip alignment tool
//
-cc_binary_host {
- name: "zipalign",
+cc_library_host_static {
+ name: "libzipalign",
srcs: [
"ZipAlign.cpp",
@@ -13,11 +13,15 @@
"ZipFile.cpp",
],
+ export_include_dirs: [
+ "include",
+ ],
+
cflags: ["-Wall", "-Werror"],
// NOTE: Do not add any shared_libs dependencies because they will break the
// static_sdk_tools target.
- static_libs: [
+ whole_static_libs: [
"libutils",
"libcutils",
"liblog",
@@ -34,3 +38,31 @@
},
},
}
+
+cc_binary_host {
+ name: "zipalign",
+
+ srcs: [
+ "ZipAlignMain.cpp",
+ ],
+
+ cflags: ["-Wall", "-Werror"],
+
+ static_libs: [
+ "libzipalign",
+ ]
+}
+
+cc_test_host {
+ name: "zipalign_tests",
+ srcs: [
+ "tests/src/*_test.cpp",
+ ],
+ static_libs: [
+ "libzipalign",
+ "libgmock",
+ ],
+ data: [
+ "tests/data/unaligned.zip",
+ ],
+}
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index eea1749..1851ac5 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -14,35 +14,13 @@
* limitations under the License.
*/
-/*
- * Zip alignment tool
- */
#include "ZipFile.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-using namespace android;
-
-/*
- * Show program usage.
- */
-void usage(void)
-{
- fprintf(stderr, "Zip alignment utility\n");
- fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
- fprintf(stderr,
- "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
- " zipalign -c [-p] [-v] <align> infile.zip\n\n" );
- fprintf(stderr,
- " <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
- fprintf(stderr, " -c: check alignment only (does not modify file)\n");
- fprintf(stderr, " -f: overwrite existing outfile.zip\n");
- fprintf(stderr, " -p: memory page alignment for stored shared object files\n");
- fprintf(stderr, " -v: verbose output\n");
- fprintf(stderr, " -z: recompress using Zopfli\n");
-}
+namespace android {
static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
ZipEntry* pEntry) {
@@ -126,7 +104,7 @@
* Process a file. We open the input and output files, failing if the
* output file exists and "force" wasn't specified.
*/
-static int process(const char* inFileName, const char* outFileName,
+int process(const char* inFileName, const char* outFileName,
int alignment, bool force, bool zopfli, bool pageAlignSharedLibs)
{
ZipFile zin, zout;
@@ -169,7 +147,7 @@
/*
* Verify the alignment of a zip archive.
*/
-static int verify(const char* fileName, int alignment, bool verbose,
+int verify(const char* fileName, int alignment, bool verbose,
bool pageAlignSharedLibs)
{
ZipFile zipFile;
@@ -218,92 +196,4 @@
return foundBad ? 1 : 0;
}
-/*
- * Parse args.
- */
-int main(int argc, char* const argv[])
-{
- bool wantUsage = false;
- bool check = false;
- bool force = false;
- bool verbose = false;
- bool zopfli = false;
- bool pageAlignSharedLibs = false;
- int result = 1;
- int alignment;
- char* endp;
-
- if (argc < 4) {
- wantUsage = true;
- goto bail;
- }
-
- argc--;
- argv++;
-
- while (argc && argv[0][0] == '-') {
- const char* cp = argv[0] +1;
-
- while (*cp != '\0') {
- switch (*cp) {
- case 'c':
- check = true;
- break;
- case 'f':
- force = true;
- break;
- case 'v':
- verbose = true;
- break;
- case 'z':
- zopfli = true;
- break;
- case 'p':
- pageAlignSharedLibs = true;
- break;
- default:
- fprintf(stderr, "ERROR: unknown flag -%c\n", *cp);
- wantUsage = true;
- goto bail;
- }
-
- cp++;
- }
-
- argc--;
- argv++;
- }
-
- if (!((check && argc == 2) || (!check && argc == 3))) {
- wantUsage = true;
- goto bail;
- }
-
- alignment = strtol(argv[0], &endp, 10);
- if (*endp != '\0' || alignment <= 0) {
- fprintf(stderr, "Invalid value for alignment: %s\n", argv[0]);
- wantUsage = true;
- goto bail;
- }
-
- if (check) {
- /* check existing archive for correct alignment */
- result = verify(argv[1], alignment, verbose, pageAlignSharedLibs);
- } else {
- /* create the new archive */
- result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs);
-
- /* trust, but verify */
- if (result == 0) {
- result = verify(argv[2], alignment, verbose, pageAlignSharedLibs);
- }
- }
-
-bail:
- if (wantUsage) {
- usage();
- result = 2;
- }
-
- return result;
-}
+} // namespace android
diff --git a/tools/zipalign/ZipAlignMain.cpp b/tools/zipalign/ZipAlignMain.cpp
new file mode 100644
index 0000000..49be916
--- /dev/null
+++ b/tools/zipalign/ZipAlignMain.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * Zip alignment tool
+ */
+
+#include "ZipAlign.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace android;
+
+/*
+ * Show program usage.
+ */
+void usage(void)
+{
+ fprintf(stderr, "Zip alignment utility\n");
+ fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
+ fprintf(stderr,
+ "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
+ " zipalign -c [-p] [-v] <align> infile.zip\n\n" );
+ fprintf(stderr,
+ " <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
+ fprintf(stderr, " -c: check alignment only (does not modify file)\n");
+ fprintf(stderr, " -f: overwrite existing outfile.zip\n");
+ fprintf(stderr, " -p: memory page alignment for stored shared object files\n");
+ fprintf(stderr, " -v: verbose output\n");
+ fprintf(stderr, " -z: recompress using Zopfli\n");
+}
+
+
+/*
+ * Parse args.
+ */
+int main(int argc, char* const argv[])
+{
+ bool wantUsage = false;
+ bool check = false;
+ bool force = false;
+ bool verbose = false;
+ bool zopfli = false;
+ bool pageAlignSharedLibs = false;
+ int result = 1;
+ int alignment;
+ char* endp;
+
+ if (argc < 4) {
+ wantUsage = true;
+ goto bail;
+ }
+
+ argc--;
+ argv++;
+
+ while (argc && argv[0][0] == '-') {
+ const char* cp = argv[0] +1;
+
+ while (*cp != '\0') {
+ switch (*cp) {
+ case 'c':
+ check = true;
+ break;
+ case 'f':
+ force = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'z':
+ zopfli = true;
+ break;
+ case 'p':
+ pageAlignSharedLibs = true;
+ break;
+ default:
+ fprintf(stderr, "ERROR: unknown flag -%c\n", *cp);
+ wantUsage = true;
+ goto bail;
+ }
+
+ cp++;
+ }
+
+ argc--;
+ argv++;
+ }
+
+ if (!((check && argc == 2) || (!check && argc == 3))) {
+ wantUsage = true;
+ goto bail;
+ }
+
+ alignment = strtol(argv[0], &endp, 10);
+ if (*endp != '\0' || alignment <= 0) {
+ fprintf(stderr, "Invalid value for alignment: %s\n", argv[0]);
+ wantUsage = true;
+ goto bail;
+ }
+
+ if (check) {
+ /* check existing archive for correct alignment */
+ result = verify(argv[1], alignment, verbose, pageAlignSharedLibs);
+ } else {
+ /* create the new archive */
+ result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs);
+
+ /* trust, but verify */
+ if (result == 0) {
+ result = verify(argv[2], alignment, verbose, pageAlignSharedLibs);
+ }
+ }
+
+bail:
+ if (wantUsage) {
+ usage();
+ result = 2;
+ }
+
+ return result;
+}
diff --git a/tools/zipalign/ZipEntry.cpp b/tools/zipalign/ZipEntry.cpp
index 810d74a..5233f0a 100644
--- a/tools/zipalign/ZipEntry.cpp
+++ b/tools/zipalign/ZipEntry.cpp
@@ -29,7 +29,7 @@
#include <string.h>
#include <time.h>
-using namespace android;
+namespace android {
/*
* Initialize a new ZipEntry structure from a FILE* positioned at a
@@ -696,3 +696,5 @@
ALOGD(" comment: '%s'\n", mFileComment);
}
+} // namespace android
+
diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp
index 88505b7..29d1bc6 100644
--- a/tools/zipalign/ZipFile.cpp
+++ b/tools/zipalign/ZipFile.cpp
@@ -35,7 +35,7 @@
#include <assert.h>
#include <inttypes.h>
-using namespace android;
+namespace android {
/*
* Some environments require the "b", some choke on it.
@@ -134,7 +134,7 @@
/*
* Return the Nth entry in the archive.
*/
-android::ZipEntry* ZipFile::getEntryByIndex(int idx) const
+ZipEntry* ZipFile::getEntryByIndex(int idx) const
{
if (idx < 0 || idx >= (int) mEntries.size())
return NULL;
@@ -145,7 +145,7 @@
/*
* Find an entry by name.
*/
-android::ZipEntry* ZipFile::getEntryByName(const char* fileName) const
+ZipEntry* ZipFile::getEntryByName(const char* fileName) const
{
/*
* Do a stupid linear string-compare search.
@@ -1397,3 +1397,4 @@
mCentralDirSize, mCentralDirOffset, mCommentLen);
}
+} // namespace android
diff --git a/tools/zipalign/include/ZipAlign.h b/tools/zipalign/include/ZipAlign.h
new file mode 100644
index 0000000..ab36086
--- /dev/null
+++ b/tools/zipalign/include/ZipAlign.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef ZIPALIGN_H
+#define ZIPALIGN_H
+
+namespace android {
+
+/*
+ * Generate a new, aligned, zip "output" from an "input" zip.
+ * - alignTo: Alignment (in bytes) for uncompressed entries.
+ * - force : Overwrite output if it exists, fail otherwise.
+ * - zopfli : Recompress compressed entries with more efficient algorithm.
+ * Copy compressed entries as-is, and unaligned, otherwise.
+ * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * alignTo, or all files to alignTo if false..
+ *
+ * Returns 0 on success.
+ */
+int process(const char* input, const char* output, int alignTo, bool force,
+ bool zopfli, bool pageAlignSharedLibs);
+
+/*
+ * Verify the alignment of a zip archive.
+ * - alignTo: Alignment (in bytes) for uncompressed entries.
+ * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * alignTo, or all files to alignTo if false..
+ *
+ * Returns 0 on success.
+ */
+int verify(const char* fileName, int alignTo, bool verbose,
+ bool pageAlignSharedLibs);
+
+} // namespace android
+
+#endif // ZIPALIGN_H
diff --git a/tools/zipalign/tests/data/unaligned.zip b/tools/zipalign/tests/data/unaligned.zip
new file mode 100644
index 0000000..d572b1a
--- /dev/null
+++ b/tools/zipalign/tests/data/unaligned.zip
Binary files differ
diff --git a/tools/zipalign/tests/src/align_test.cpp b/tools/zipalign/tests/src/align_test.cpp
new file mode 100644
index 0000000..b8f2e15
--- /dev/null
+++ b/tools/zipalign/tests/src/align_test.cpp
@@ -0,0 +1,15 @@
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "ZipAlign.h"
+
+#include <stdio.h>
+
+using namespace android;
+
+TEST(Align, Unaligned) {
+ const char* src = "tests/data/unaligned.zip";
+ const char* dst = "tests/data/unaligned_out.zip";
+ int result = process(src, dst, 4, true, false, 4096);
+ ASSERT_EQ(0, result);
+}