FilePermissionsTest.java
package org.zeroturnaround.zip;
/**
* Copyright (C) 2012 ZeroTurnaround LLC <support@zeroturnaround.com>
*
* 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.
*/
import java.io.File;
import java.io.IOException;
import org.junit.Assume;
import org.zeroturnaround.zip.commons.FileUtils;
import org.junit.Test;
import static org.junit.Assert.*;
public class FilePermissionsTest {
private final File testFile = new File(getClass().getClassLoader().getResource("TestFile.txt").getPath());
@Test
public void testPreserveExecuteFlag() throws Exception {
String dirName = "FilePermissionsTest-e";
File tmpDir = File.createTempFile(dirName, null);
tmpDir.delete();
tmpDir.mkdir();
File fileA = new File(tmpDir, "fileA.txt");
File fileB = new File(tmpDir, "fileB.txt");
FileUtils.copyFile(testFile, fileA);
FileUtils.copyFile(testFile, fileB);
Assume.assumeTrue(setExecutable(fileA, false));
//Avoids failing test on Windows: File.setExecutable(): "If executable is false and the underlying file system does not implement an execute permission, then the operation will fail."
setExecutable(fileA, true);
setExecutable(fileB, false);
//TESTS BEFORE ZIP
assertTrue(fileA.exists() && fileB.exists());
assertTrue(canExecute(fileA));
assertFalse(canExecute(fileB));
assertTrue(doZipAndUnpack(dirName, ".zip", tmpDir));
//SAME TESTS AFTER ZIP & UNZIP
assertTrue(fileA.exists() && fileB.exists());
assertTrue(canExecute(fileA));
assertFalse(canExecute(fileB));
}
@Test
public void testPreserveReadFlag() throws Exception {
String dirName = "FilePermissionsTest-r";
File tmpDir = File.createTempFile(dirName, null);
tmpDir.delete();
tmpDir.mkdir();
File fileA = new File(tmpDir, "fileA.txt");
File fileB = new File(tmpDir, "fileB.txt");
FileUtils.copyFile(testFile, fileA);
FileUtils.copyFile(testFile, fileB);
Assume.assumeTrue(setReadable(fileA, false));
//Avoids failing test on Windows: File.setReadable(): "If readable is false and the underlying file system does not implement a read permission, then the operation will fail."
setReadable(fileA, true);
setReadable(fileB, false);
setReadable(fileB, true);//if we set read permission to false, then we can't zip the file, causing the test to fail with a permission exception
//TESTS BEFORE ZIP
assertTrue(fileA.exists() && fileB.exists());
assertTrue(canRead(fileA));
assertTrue(canRead(fileB));
assertTrue(doZipAndUnpack(dirName, ".zip", tmpDir));
//SAME TESTS AFTER ZIP & UNZIP
assertTrue(fileA.exists() && fileB.exists());
assertTrue(canRead(fileA));
assertTrue(canRead(fileB));
}
/** This is the only test that can be run on Windows to test that permissions are kept after zip and unzip. */
@Test
public void testPreserveWriteFlag() throws Exception {
String dirName = "FilePermissionsTest-w";
File tmpDir = File.createTempFile(dirName, null);
tmpDir.delete();
tmpDir.mkdir();
File fileA = new File(tmpDir, "fileA.txt");
File fileB = new File(tmpDir, "fileB.txt");
FileUtils.copyFile(testFile, fileA, true);
FileUtils.copyFile(testFile, fileB, true);
//Assume.assumeTrue(setWritable(fileA, false));
//this is commented because there is no OS-specific logic for returning false in File.setWritable(), only "The operation will fail if the user does not have permission to change the access permissions of this abstract pathname."
setWritable(fileA, true);
setWritable(fileB, false);
//TESTS BEFORE ZIP
assertTrue(fileA.exists() && fileB.exists());
assertTrue(canWrite(fileA));
assertFalse(canWrite(fileB));
assertTrue(doZipAndUnpack(dirName, ".zip", tmpDir));
//SAME TESTS AFTER ZIP & UNZIP
assertTrue(fileA.exists() && fileB.exists());
assertTrue(canWrite(fileA));
assertFalse(canWrite(fileB));
}
private boolean doZipAndUnpack(String prefix, String suffix, File rootDir) throws IOException {
File tmpZip = File.createTempFile(prefix, suffix);
ZipUtil.pack(rootDir, tmpZip);
FileUtils.deleteDirectory(rootDir);
if(directoryHasFiles(rootDir)) {return false;}//if the directory isn't empty after the delete, we can't (easily) test to see if the unzip created files in that directory
ZipUtil.unpack(tmpZip, rootDir);
return directoryHasFiles(rootDir);//if the directory has files after they were all previously deleted, then the unzip worked
}
private static boolean directoryHasFiles(File directory) {
if(directory==null || !directory.exists() || directory.listFiles()==null) {return false;}
return directory.listFiles().length > 0;
}
private boolean canExecute(File file) throws Exception {
return (Boolean) File.class.getDeclaredMethod("canExecute").invoke(file);
}
private boolean setExecutable(File file, boolean executable) throws Exception {
return (Boolean) File.class.getDeclaredMethod("setExecutable", boolean.class).invoke(file, executable);
}
private boolean canWrite(File file) throws Exception {
return (Boolean) File.class.getDeclaredMethod("canWrite").invoke(file);
}
private boolean setWritable(File file, boolean writable) throws Exception {
return (Boolean) File.class.getDeclaredMethod("setWritable", boolean.class).invoke(file, writable);
}
private boolean canRead(File file) throws Exception {
return (Boolean) File.class.getDeclaredMethod("canRead").invoke(file);
}
private boolean setReadable(File file, boolean readable) throws Exception {
return (Boolean) File.class.getDeclaredMethod("setReadable", boolean.class).invoke(file, readable);
}
}