diff options
author | Guang Zhu <guangzhu@google.com> | 2017-01-03 17:59:55 -0800 |
---|---|---|
committer | Guang Zhu <guangzhu@google.com> | 2017-01-05 10:14:33 -0800 |
commit | 91fdf44e35897eceaa614d78300d5b370a2795aa (patch) | |
tree | a788f4957a36838b212c8b94f498a4499e96ded8 | |
parent | 0c7950f1f51ff8ad502da252c549f56130319c1a (diff) | |
download | tradefederation-91fdf44e35897eceaa614d78300d5b370a2795aa.tar.gz |
add new zip extraction util methods to cover file permissions
- the new util methods are meant to provide same interface as
before (modulus using a different ZipFile class)
- existing uses of the util methods are migrated
Bug: 33942619
Test: new & existing unit tests
Change-Id: I9b53cd822ef282e90832cc18c47d4672a6a375d5
-rw-r--r-- | src/com/android/tradefed/device/NativeDevice.java | 9 | ||||
-rw-r--r-- | src/com/android/tradefed/result/CodeCoverageReporter.java | 7 | ||||
-rw-r--r-- | src/com/android/tradefed/targetprep/CdmaDeviceFlasher.java | 7 | ||||
-rw-r--r-- | src/com/android/tradefed/targetprep/FastbootDeviceFlasher.java | 7 | ||||
-rw-r--r-- | src/com/android/tradefed/testtype/JackCodeCoverageTest.java | 8 | ||||
-rw-r--r-- | src/com/android/tradefed/util/Bugreport.java | 15 | ||||
-rw-r--r-- | src/com/android/tradefed/util/FileUtil.java | 34 | ||||
-rw-r--r-- | src/com/android/tradefed/util/ZipUtil2.java | 121 | ||||
-rw-r--r-- | tests/res/util/permission-test.zip | bin | 0 -> 460 bytes | |||
-rw-r--r-- | tests/src/com/android/tradefed/UnitTests.java | 2 | ||||
-rw-r--r-- | tests/src/com/android/tradefed/build/LocalDeviceBuildProviderTest.java | 11 | ||||
-rw-r--r-- | tests/src/com/android/tradefed/device/TestDeviceTest.java | 12 | ||||
-rw-r--r-- | tests/src/com/android/tradefed/util/FileUtilTest.java | 39 | ||||
-rw-r--r-- | tests/src/com/android/tradefed/util/ZipUtil2Test.java | 127 |
14 files changed, 365 insertions, 34 deletions
diff --git a/src/com/android/tradefed/device/NativeDevice.java b/src/com/android/tradefed/device/NativeDevice.java index d5bda74d7..8f82fb837 100644 --- a/src/com/android/tradefed/device/NativeDevice.java +++ b/src/com/android/tradefed/device/NativeDevice.java @@ -52,9 +52,11 @@ import com.android.tradefed.util.PsParser; import com.android.tradefed.util.RunUtil; import com.android.tradefed.util.SizeLimitedOutputStream; import com.android.tradefed.util.StreamUtil; -import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.ZipUtil2; import com.android.tradefed.util.sl4a.Sl4aClient; +import org.apache.commons.compress.archivers.zip.ZipFile; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FilenameFilter; @@ -75,7 +77,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.zip.ZipFile; import javax.annotation.concurrent.GuardedBy; @@ -1924,10 +1925,10 @@ public class NativeDevice implements IManagedTestDevice { } zip = new ZipFile(bugreportzFile); // We get the main_entry.txt that contains the bugreport name. - mainEntry = ZipUtil.extractFileFromZip(zip, "main_entry.txt"); + mainEntry = ZipUtil2.extractFileFromZip(zip, "main_entry.txt"); String bugreportName = FileUtil.readStringFromFile(mainEntry).trim(); CLog.d("bugreport name: '%s'", bugreportName); - File bugreport = ZipUtil.extractFileFromZip(zip, bugreportName); + File bugreport = ZipUtil2.extractFileFromZip(zip, bugreportName); return new FileInputStreamSource(bugreport, true); } catch (IOException e) { CLog.e("Error while unzipping bugreportz"); diff --git a/src/com/android/tradefed/result/CodeCoverageReporter.java b/src/com/android/tradefed/result/CodeCoverageReporter.java index 59e84f6cb..05abe8c0c 100644 --- a/src/com/android/tradefed/result/CodeCoverageReporter.java +++ b/src/com/android/tradefed/result/CodeCoverageReporter.java @@ -27,17 +27,18 @@ import com.android.tradefed.util.CommandStatus; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.IRunUtil; import com.android.tradefed.util.RunUtil; -import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.ZipUtil2; import junit.framework.Assert; import junit.framework.AssertionFailedError; +import org.apache.commons.compress.archivers.zip.ZipFile; + import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.zip.ZipFile; /** * A {@link ITestInvocationListener} that will generate code coverage reports. @@ -193,7 +194,7 @@ public class CodeCoverageReporter implements ITestInvocationListener { try { mLocalTmpDir = FileUtil.createTempDir("emma-meta"); ZipFile zipFile = new ZipFile(coverageZipFile); - ZipUtil.extractZip(zipFile, mLocalTmpDir); + ZipUtil2.extractZip(zipFile, mLocalTmpDir); File coverageMetaFile; if (mCoverageMetaFilePath == null) { coverageMetaFile = FileUtil.findFile(mLocalTmpDir, "coverage.em"); diff --git a/src/com/android/tradefed/targetprep/CdmaDeviceFlasher.java b/src/com/android/tradefed/targetprep/CdmaDeviceFlasher.java index db2d14663..85da73ea6 100644 --- a/src/com/android/tradefed/targetprep/CdmaDeviceFlasher.java +++ b/src/com/android/tradefed/targetprep/CdmaDeviceFlasher.java @@ -23,11 +23,12 @@ import com.android.tradefed.device.ITestDevice; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.IRunUtil; import com.android.tradefed.util.RunUtil; -import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.ZipUtil2; + +import org.apache.commons.compress.archivers.zip.ZipFile; import java.io.File; import java.io.IOException; -import java.util.zip.ZipFile; /** * A class that flashes an image on a physical Android device with a CDMA radio. @@ -141,7 +142,7 @@ public class CdmaDeviceFlasher extends FastbootDeviceFlasher { protected File extractSystemZip(IDeviceBuildInfo deviceBuild) throws IOException { File updateDir = FileUtil.createTempDir(LOG_TAG); ZipFile updater = new ZipFile(deviceBuild.getDeviceImageFile().getAbsolutePath()); - ZipUtil.extractZip(updater, updateDir); + ZipUtil2.extractZip(updater, updateDir); return updateDir; } diff --git a/src/com/android/tradefed/targetprep/FastbootDeviceFlasher.java b/src/com/android/tradefed/targetprep/FastbootDeviceFlasher.java index b0c20c396..f45b6676c 100644 --- a/src/com/android/tradefed/targetprep/FastbootDeviceFlasher.java +++ b/src/com/android/tradefed/targetprep/FastbootDeviceFlasher.java @@ -26,7 +26,9 @@ import com.android.tradefed.util.CommandStatus; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.IRunUtil; import com.android.tradefed.util.RunUtil; -import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.ZipUtil2; + +import org.apache.commons.compress.archivers.zip.ZipFile; import java.io.File; import java.io.IOException; @@ -35,7 +37,6 @@ import java.util.Collection; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.zip.ZipFile; /** * A class that relies on fastboot to flash an image on physical Android hardware. @@ -485,7 +486,7 @@ public class FastbootDeviceFlasher implements IDeviceFlasher { File userdataImg = null; try { try { - userdataImg = ZipUtil.extractFileFromZip( + userdataImg = ZipUtil2.extractFileFromZip( new ZipFile(deviceBuild.getDeviceImageFile()), "userdata.img"); } catch (IOException ioe) { throw new TargetSetupError("failed to extract userdata.img from image file", ioe, diff --git a/src/com/android/tradefed/testtype/JackCodeCoverageTest.java b/src/com/android/tradefed/testtype/JackCodeCoverageTest.java index 6f8b6866f..e3d3d93ad 100644 --- a/src/com/android/tradefed/testtype/JackCodeCoverageTest.java +++ b/src/com/android/tradefed/testtype/JackCodeCoverageTest.java @@ -21,19 +21,19 @@ import static com.android.tradefed.testtype.JackCodeCoverageReportFormat.XML; import com.android.tradefed.config.Option; import com.android.tradefed.config.OptionClass; -import com.android.tradefed.testtype.IRemoteTest; import com.android.tradefed.util.CommandResult; import com.android.tradefed.util.CommandStatus; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.RunUtil; -import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.ZipUtil2; + import com.google.common.collect.Lists; import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.FileSystem; import java.nio.file.FileSystems; +import java.nio.file.Files; import java.nio.file.PathMatcher; import java.security.CodeSource; import java.util.ArrayList; @@ -127,7 +127,7 @@ public class JackCodeCoverageTest extends CodeCoverageTestBase<JackCodeCoverageR // Extract the metadata files if we haven't already if (mMetadataCache == null) { File metadataZip = getBuild().getFile(getMetadataZipArtifact()); - mMetadataCache = ZipUtil.extractZipToTemp(metadataZip, "metadata"); + mMetadataCache = ZipUtil2.extractZipToTemp(metadataZip, "metadata"); } // Convert the filter strings to PathMatchers diff --git a/src/com/android/tradefed/util/Bugreport.java b/src/com/android/tradefed/util/Bugreport.java index 214b0d867..666ad1e57 100644 --- a/src/com/android/tradefed/util/Bugreport.java +++ b/src/com/android/tradefed/util/Bugreport.java @@ -21,14 +21,15 @@ import com.android.tradefed.result.FileInputStreamSource; import com.android.tradefed.result.InputStreamSource; import com.android.tradefed.result.LogDataType; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; + import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * Object holding the bugreport files references, compatible of flat bugreport and zipped bugreport @@ -80,14 +81,14 @@ public class Bugreport implements Closeable { try { zip = new ZipFile(mBugreport); // We get the main_entry.txt that contains the bugreport name. - mainEntry = ZipUtil.extractFileFromZip(zip, "main_entry.txt"); + mainEntry = ZipUtil2.extractFileFromZip(zip, "main_entry.txt"); if (mainEntry == null) { CLog.w("main_entry.txt was not found inside the bugreport"); return null; } String bugreportName = FileUtil.readStringFromFile(mainEntry).trim(); CLog.d("bugreport name: '%s'", bugreportName); - return ZipUtil.extractFileFromZip(zip, bugreportName); + return ZipUtil2.extractFileFromZip(zip, bugreportName); } catch (IOException e) { CLog.e("Error while unzipping bugreportz"); CLog.e(e); @@ -113,14 +114,14 @@ public class Bugreport implements Closeable { ZipFile zipBugreport = null; try { zipBugreport = new ZipFile(mBugreport); - for (ZipEntry entry : Collections.list(zipBugreport.entries())) { + for (ZipArchiveEntry entry : Collections.list(zipBugreport.getEntries())) { list.add(entry.getName()); } } catch (IOException e) { CLog.e("Error reading the list of files in the bugreport"); CLog.e(e); } finally { - ZipUtil.closeZip(zipBugreport); + ZipUtil2.closeZip(zipBugreport); } return list; } @@ -148,7 +149,7 @@ public class Bugreport implements Closeable { File bugreport = null; try { zip = new ZipFile(mBugreport); - bugreport = ZipUtil.extractFileFromZip(zip, name); + bugreport = ZipUtil2.extractFileFromZip(zip, name); return bugreport; } catch (IOException e) { CLog.e("Error while unzipping bugreportz"); diff --git a/src/com/android/tradefed/util/FileUtil.java b/src/com/android/tradefed/util/FileUtil.java index 02fa70151..e64aef409 100644 --- a/src/com/android/tradefed/util/FileUtil.java +++ b/src/com/android/tradefed/util/FileUtil.java @@ -31,10 +31,14 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.attribute.PosixFilePermission; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.zip.ZipFile; @@ -60,6 +64,20 @@ public class FileUtil { private static String CHMOD = "chmod"; + /** A map of {@link PosixFilePermission} to its corresponding Unix file mode */ + private static final Map<PosixFilePermission, Integer> PERM_MODE_MAP = new HashMap<>(); + static { + PERM_MODE_MAP.put(PosixFilePermission.OWNER_READ, 0b100000000); + PERM_MODE_MAP.put(PosixFilePermission.OWNER_WRITE, 0b010000000); + PERM_MODE_MAP.put(PosixFilePermission.OWNER_EXECUTE, 0b001000000); + PERM_MODE_MAP.put(PosixFilePermission.GROUP_READ, 0b000100000); + PERM_MODE_MAP.put(PosixFilePermission.GROUP_WRITE, 0b000010000); + PERM_MODE_MAP.put(PosixFilePermission.GROUP_EXECUTE, 0b000001000); + PERM_MODE_MAP.put(PosixFilePermission.OTHERS_READ, 0b000000100); + PERM_MODE_MAP.put(PosixFilePermission.OTHERS_WRITE, 0b000000010); + PERM_MODE_MAP.put(PosixFilePermission.OTHERS_EXECUTE, 0b000000001); + } + public static int FILESYSTEM_FILENAME_MAX_LENGTH = 255; /** @@ -912,4 +930,20 @@ public class FileUtil { FileInputStream inputSource = new FileInputStream(file); return StreamUtil.calculateMd5(inputSource); } + + /** + * Converts an integer representing unix mode to a set of {@link PosixFilePermission}s + * @param mode + * @return + */ + public static Set<PosixFilePermission> unixModeToPosix(int mode) { + Set<PosixFilePermission> result = EnumSet.noneOf(PosixFilePermission.class); + for (PosixFilePermission pfp : EnumSet.allOf(PosixFilePermission.class)) { + int m = PERM_MODE_MAP.get(pfp); + if ((m & mode) == m) { + result.add(pfp); + } + } + return result; + } } diff --git a/src/com/android/tradefed/util/ZipUtil2.java b/src/com/android/tradefed/util/ZipUtil2.java new file mode 100644 index 000000000..547790373 --- /dev/null +++ b/src/com/android/tradefed/util/ZipUtil2.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2016 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.tradefed.util; + +import com.android.tradefed.log.LogUtil.CLog; + +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Enumeration; + +/** + * A helper class for zip extraction that takes POSIX file permissions into account + */ +public class ZipUtil2 { + + /** + * A util method to apply unix mode from {@link ZipArchiveEntry} to the created local file + * system entry if necessary + * @param entry the entry inside zipfile (potentially contains mode info) + * @param localFile the extracted local file entry + * @throws IOException + */ + private static void applyUnixModeIfNecessary(ZipArchiveEntry entry, File localFile) + throws IOException { + if (entry.getPlatform() == ZipArchiveEntry.PLATFORM_UNIX) { + Files.setPosixFilePermissions(localFile.toPath(), + FileUtil.unixModeToPosix(entry.getUnixMode())); + } else { + CLog.i("Entry does not contain Unix mode info: %s", entry.getName()); + } + } + + /** + * Utility method to extract entire contents of zip file into given directory + * + * @param zipFile the {@link ZipFile} to extract + * @param destDir the local dir to extract file to + * @throws IOException if failed to extract file + */ + public static void extractZip(ZipFile zipFile, File destDir) throws IOException { + Enumeration<? extends ZipArchiveEntry> entries = zipFile.getEntries(); + while (entries.hasMoreElements()) { + ZipArchiveEntry entry = entries.nextElement(); + File childFile = new File(destDir, entry.getName()); + childFile.getParentFile().mkdirs(); + if (entry.isDirectory()) { + childFile.mkdirs(); + applyUnixModeIfNecessary(entry, childFile); + continue; + } else { + FileUtil.writeToFile(zipFile.getInputStream(entry), childFile); + applyUnixModeIfNecessary(entry, childFile); + } + } + } + + /** + * Utility method to extract one specific file from zip file into a tmp file + * + * @param zipFile the {@link ZipFile} to extract + * @param filePath the filePath of to extract + * @throws IOException if failed to extract file + * @return the {@link File} or null if not found + */ + public static File extractFileFromZip(ZipFile zipFile, String filePath) throws IOException { + ZipArchiveEntry entry = zipFile.getEntry(filePath); + if (entry == null) { + return null; + } + File createdFile = FileUtil.createTempFile("extracted", + FileUtil.getExtension(filePath)); + FileUtil.writeToFile(zipFile.getInputStream(entry), createdFile); + applyUnixModeIfNecessary(entry, createdFile); + return createdFile; + } + + /** + * Extract a zip file to a temp directory prepended with a string + * + * @param zipFile the zip file to extract + * @param nameHint a prefix for the temp directory + * @return a {@link File} pointing to the temp directory + */ + public static File extractZipToTemp(File zipFile, String nameHint) throws IOException { + File localRootDir = FileUtil.createTempDir(nameHint); + extractZip(new ZipFile(zipFile), localRootDir); + return localRootDir; + } + + /** + * Close an open {@link ZipFile}, ignoring any exceptions. + * + * @param zipFile the file to close + */ + public static void closeZip(ZipFile zipFile) { + if (zipFile != null) { + try { + zipFile.close(); + } catch (IOException e) { + // ignore + } + } + } +} diff --git a/tests/res/util/permission-test.zip b/tests/res/util/permission-test.zip Binary files differnew file mode 100644 index 000000000..5397ea500 --- /dev/null +++ b/tests/res/util/permission-test.zip diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java index d838c99fc..bbfbe197d 100644 --- a/tests/src/com/android/tradefed/UnitTests.java +++ b/tests/src/com/android/tradefed/UnitTests.java @@ -168,6 +168,7 @@ import com.android.tradefed.util.TarUtilTest; import com.android.tradefed.util.TestLoaderTest; import com.android.tradefed.util.TimeUtilTest; import com.android.tradefed.util.TimeValTest; +import com.android.tradefed.util.ZipUtil2Test; import com.android.tradefed.util.ZipUtilTest; import com.android.tradefed.util.keystore.JSONFileKeyStoreClientTest; import com.android.tradefed.util.net.HttpHelperTest; @@ -371,6 +372,7 @@ import org.junit.runners.Suite.SuiteClasses; TimeValTest.class, XmlRpcHelperTest.class, ZipUtilTest.class, + ZipUtil2Test.class, // util subdirs AndroidManifestWriterTest.class, diff --git a/tests/src/com/android/tradefed/build/LocalDeviceBuildProviderTest.java b/tests/src/com/android/tradefed/build/LocalDeviceBuildProviderTest.java index 3987553d3..fd5710bf4 100644 --- a/tests/src/com/android/tradefed/build/LocalDeviceBuildProviderTest.java +++ b/tests/src/com/android/tradefed/build/LocalDeviceBuildProviderTest.java @@ -15,17 +15,20 @@ */ package com.android.tradefed.build; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import com.android.tradefed.util.FileUtil; -import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.ZipUtil2; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.File; -import java.util.zip.ZipFile; /** @@ -118,7 +121,7 @@ public class LocalDeviceBuildProviderTest { File buildImageZip = mLocalDeviceBuildProvider.createBuildImageZip(); try { assertNotNull(buildImageZip); - ZipUtil.extractZip(new ZipFile(buildImageZip), mTmpDir); + ZipUtil2.extractZip(new ZipFile(buildImageZip), mTmpDir); File extractedFile1 = new File(mTmpDir, mAndroidInfo.getName()); File extractedFile2 = new File(mTmpDir, mBootImg.getName()); File extractedFile3 = new File(mTmpDir, mSystemImg.getName()); diff --git a/tests/src/com/android/tradefed/device/TestDeviceTest.java b/tests/src/com/android/tradefed/device/TestDeviceTest.java index e490a1670..4e10a9d0f 100644 --- a/tests/src/com/android/tradefed/device/TestDeviceTest.java +++ b/tests/src/com/android/tradefed/device/TestDeviceTest.java @@ -35,13 +35,17 @@ import com.android.tradefed.util.CommandStatus; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.IRunUtil; import com.android.tradefed.util.RunUtil; -import com.android.tradefed.util.ZipUtil; +import com.android.tradefed.util.ZipUtil2; import com.google.common.util.concurrent.SettableFuture; import junit.framework.Assert; import junit.framework.TestCase; +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.easymock.IExpectationSetters; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -55,10 +59,6 @@ import java.util.Set; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.easymock.EasyMock; -import org.easymock.IAnswer; -import org.easymock.IExpectationSetters; - /** * Unit tests for {@link TestDevice}. */ @@ -2769,7 +2769,7 @@ public class TestDeviceTest extends TestCase { File imageZipFile = FileUtil.createTempFile("rawImage", ".zip"); try { FileUtil.writeToFile(imageZip, imageZipFile); - File dir = ZipUtil.extractZipToTemp(imageZipFile, "test-raw-image"); + File dir = ZipUtil2.extractZipToTemp(imageZipFile, "test-raw-image"); return new File(dir, "rawImageScreenshot.raw"); } finally { FileUtil.deleteFile(imageZipFile); diff --git a/tests/src/com/android/tradefed/util/FileUtilTest.java b/tests/src/com/android/tradefed/util/FileUtilTest.java index 35fa968ae..f4de5497c 100644 --- a/tests/src/com/android/tradefed/util/FileUtilTest.java +++ b/tests/src/com/android/tradefed/util/FileUtilTest.java @@ -23,6 +23,8 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.file.attribute.PosixFilePermission; +import java.util.Set; /** * Unit tests for {@link FileUtil} @@ -288,4 +290,41 @@ public class FileUtilTest extends TestCase { FileUtil.deleteFile(testFile); } } + + /** + * Test {@link FileUtil#unixModeToPosix(int)} returns expected results; + */ + public void testUnixModeToPosix() { + Set<PosixFilePermission> perms = null; + // can't test all 8 * 8 * 8, so just a select few + perms = FileUtil.unixModeToPosix(0777); + assertTrue("failed unix mode conversion: 0777", + perms.remove(PosixFilePermission.OWNER_READ) && + perms.remove(PosixFilePermission.OWNER_WRITE) && + perms.remove(PosixFilePermission.OWNER_EXECUTE) && + perms.remove(PosixFilePermission.GROUP_READ) && + perms.remove(PosixFilePermission.GROUP_WRITE) && + perms.remove(PosixFilePermission.GROUP_EXECUTE) && + perms.remove(PosixFilePermission.OTHERS_READ) && + perms.remove(PosixFilePermission.OTHERS_WRITE) && + perms.remove(PosixFilePermission.OTHERS_EXECUTE) && + perms.isEmpty()); + perms = FileUtil.unixModeToPosix(0644); + assertTrue("failed unix mode conversion: 0644", + perms.remove(PosixFilePermission.OWNER_READ) && + perms.remove(PosixFilePermission.OWNER_WRITE) && + perms.remove(PosixFilePermission.GROUP_READ) && + perms.remove(PosixFilePermission.OTHERS_READ) && + perms.isEmpty()); + perms = FileUtil.unixModeToPosix(0755); + assertTrue("failed unix mode conversion: 0755", + perms.remove(PosixFilePermission.OWNER_READ) && + perms.remove(PosixFilePermission.OWNER_WRITE) && + perms.remove(PosixFilePermission.OWNER_EXECUTE) && + perms.remove(PosixFilePermission.GROUP_READ) && + perms.remove(PosixFilePermission.GROUP_EXECUTE) && + perms.remove(PosixFilePermission.OTHERS_READ) && + perms.remove(PosixFilePermission.OTHERS_EXECUTE) && + perms.isEmpty()); + } } diff --git a/tests/src/com/android/tradefed/util/ZipUtil2Test.java b/tests/src/com/android/tradefed/util/ZipUtil2Test.java new file mode 100644 index 000000000..b91aae45b --- /dev/null +++ b/tests/src/com/android/tradefed/util/ZipUtil2Test.java @@ -0,0 +1,127 @@ +/* + * 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.tradefed.util; + +import org.apache.commons.compress.archivers.zip.ZipFile; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.HashSet; +import java.util.Set; + +/** + * Unit tests for {@link ZipUtil2} + */ +public class ZipUtil2Test { + + private Set<File> mTempFiles = new HashSet<File>(); + + /** + * Cleans up temp test files + * @throws Exception + */ + @After + public void tempFileCleanUp() throws Exception { + for (File file : mTempFiles) { + FileUtil.recursiveDelete(file); + } + } + + /** + * Utility method to assert that provided file has expected permission per standard Unix + * notation, e.g. file should have permission "rwxrwxrwx" + * @param file + */ + private void verifyFilePermission(File file, String permString) throws IOException { + Set<PosixFilePermission> actual = Files.getPosixFilePermissions(file.toPath()); + Set<PosixFilePermission> expected = PosixFilePermissions.fromString(permString); + Assert.assertEquals(expected, actual); + } + + /** + * Utility method to assert that provided file has expected permission per its file name, i.e. + * a file (literally) named "rwxrwxrwx" should have the expected permission bits + * @param file + */ + private void verifyFilePermission(File file) throws IOException { + verifyFilePermission(file, file.getName()); + } + + @Test + public void testExtractFileFromZip() throws Exception { + final File zip = getTestDataFile("permission-test"); + final String fileName = "rwxr-x--x"; + ZipFile zipFile = null; + try { + zipFile = new ZipFile(zip); + File extracted = ZipUtil2.extractFileFromZip(zipFile, fileName); + mTempFiles.add(extracted); + verifyFilePermission(extracted, fileName); + } finally { + ZipFile.closeQuietly(zipFile); + } + } + + @Test + public void testExtractZip() throws Exception { + final File zip = getTestDataFile("permission-test"); + final File destDir = createTempDir("ZipUtil2Test"); + ZipFile zipFile = null; + try { + zipFile = new ZipFile(zip); + ZipUtil2.extractZip(zipFile, destDir); + // now loop over files to verify + for (File file : destDir.listFiles()) { + // the pmierssion-test.zip file has no hierarchy inside + verifyFilePermission(file); + } + } finally { + ZipFile.closeQuietly(zipFile); + } + } + + private File getTestDataFile(String name) throws IOException { + final InputStream inputStream = + getClass().getResourceAsStream(String.format("/util/%s.zip", name)); + final File zipFile = createTempFile(name, ".zip"); + FileUtil.writeToFile(inputStream, zipFile); + return zipFile; + } + + // Helpers + private File createTempDir(String prefix) throws IOException { + return createTempDir(prefix, null); + } + + private File createTempDir(String prefix, File parentDir) throws IOException { + File tempDir = FileUtil.createTempDir(prefix, parentDir); + mTempFiles.add(tempDir); + return tempDir; + } + + private File createTempFile(String prefix, String suffix) throws IOException { + File tempFile = FileUtil.createTempFile(prefix, suffix); + mTempFiles.add(tempFile); + return tempFile; + } +} |