/** * Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite * contributors * * This file is part of EvoSuite. * * EvoSuite is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3.0 of the License, or * (at your option) any later version. * * EvoSuite is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>. */ package org.evosuite.runtime.mock.java.io; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.ArrayList; import org.evosuite.runtime.RuntimeSettings; import org.evosuite.runtime.mock.MockFramework; import org.evosuite.runtime.mock.OverrideMock; import org.evosuite.runtime.mock.java.lang.MockIllegalArgumentException; import org.evosuite.runtime.mock.java.net.MockURL; import org.evosuite.runtime.vfs.FSObject; import org.evosuite.runtime.vfs.VFile; import org.evosuite.runtime.vfs.VFolder; import org.evosuite.runtime.vfs.VirtualFileSystem; /** * This class is used in the mocking framework to replace File instances. * * <p> * All files are created in memory, and no access to disk is ever done * * @author arcuri * */ public class MockFile extends File implements OverrideMock { private static final long serialVersionUID = -8217763202925800733L; /* * Constructors, with same inputs as in File. Note: it is not possible to inherit JavaDocs for constructors. */ public MockFile(String pathname) { super(pathname); } public MockFile(String parent, String child) { this(combine(parent,child)); } public MockFile(File parent, String child) { this(parent == null ? (String) null : parent.getAbsolutePath() , child); } public MockFile(URI uri) { super(uri); } private static String combine(String parent, String child) { if (child == null) { throw new NullPointerException(); } if(parent == null) { return child; } if(parent.equals("")) { return VirtualFileSystem.getDefaultParent()+child; } return makeAbsolute(parent) + "/" + child; } private static String makeAbsolute(String path) { String base = VirtualFileSystem.getWorkingDirPath(); if(base.startsWith("/")) { //Mac/Linux if(path.startsWith("/")) { return path; } else { return base + "/" + path; } } else { //Windows //TODO: tmp, nasty hack, but anyway this class ll need refactoring when fully handling Java 8 String root = base.substring(0, 3); //eg, C:\ if(path.startsWith(root)) { return path; } else{ return base + "/" + path; } } } /* * TODO: Java 7 * * there is only one method in File that depends on Java 7: * * public Path toPath() * * * but if we include it here, we will break compatibility with Java 6. * Once we drop such backward compatibility, we will need to override * such method */ /* * --------- static methods ------------------ * * recall: it is not possible to override static methods. * In the SUT, all calls to those static methods of File, eg File.foo(), * will need to be replaced with EvoFile.foo() */ public static File[] listRoots() { if(!MockFramework.isEnabled()) { return File.listRoots(); } //FIXME: this is not going to work if tests are executed on different machine File[] roots = File.listRoots(); MockFile[] mocks = new MockFile[roots.length]; for(int i=0; i<roots.length; i++) { mocks[i] = new MockFile(roots[i].getAbsolutePath()); } return mocks; } public static File createTempFile(String prefix, String suffix, File directory) throws IOException{ if(!MockFramework.isEnabled()) { return File.createTempFile(prefix, suffix, directory); } VirtualFileSystem.getInstance().throwSimuledIOExceptionIfNeeded(""); String path = VirtualFileSystem.getInstance().createTempFile(prefix, suffix, directory); if(path==null) { throw new MockIOException(); } return new MockFile(path); } public static File createTempFile(String prefix, String suffix) throws IOException { return createTempFile(prefix, suffix, null); } // -------- modified methods ---------------- @Override public String getAbsolutePath() { if(!MockFramework.isEnabled()) { return super.getAbsolutePath(); } String absolute = makeAbsolute(getPath()); File tmp = new File(absolute); //be sure to force actual resolution return tmp.getAbsolutePath(); } @Override public int compareTo(File pathname) { if(!MockFramework.isEnabled()) { return super.compareTo(pathname); } return new File(getAbsolutePath()).compareTo(pathname); } @Override public File getParentFile() { if(!MockFramework.isEnabled()) { return super.getParentFile(); } String p = this.getParent(); if (p == null) return null; return new MockFile(p); } @Override public File getAbsoluteFile() { if(!MockFramework.isEnabled()) { return super.getAbsoluteFile(); } String absPath = getAbsolutePath(); return new MockFile(absPath); } @Override public File getCanonicalFile() throws IOException { if(!MockFramework.isEnabled()) { return super.getCanonicalFile(); } String canonPath = getCanonicalPath(); VirtualFileSystem.getInstance().throwSimuledIOExceptionIfNeeded(getAbsolutePath()); return new MockFile(canonPath); } @Override public boolean canRead() { if(!MockFramework.isEnabled()) { return super.canRead(); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } return file.isReadPermission(); } @Override public boolean setReadOnly() { if(!MockFramework.isEnabled()) { return super.setReadOnly(); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } file.setReadPermission(true); file.setExecutePermission(false); file.setWritePermission(false); return true; } @Override public boolean setReadable(boolean readable, boolean ownerOnly) { if(!MockFramework.isEnabled()) { return super.setReadable(readable, ownerOnly); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } file.setReadPermission(readable); return true; } @Override public boolean canWrite() { if(!MockFramework.isEnabled()) { return super.canWrite(); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } return file.isWritePermission(); } @Override public boolean setWritable(boolean writable, boolean ownerOnly) { if(!MockFramework.isEnabled()) { return super.setWritable(writable, ownerOnly); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } file.setWritePermission(writable); return true; } @Override public boolean setExecutable(boolean executable, boolean ownerOnly) { if(!MockFramework.isEnabled()) { return super.setExecutable(executable, ownerOnly); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } file.setExecutePermission(executable); return true; } @Override public boolean canExecute() { if(!MockFramework.isEnabled()) { return super.canExecute(); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } return file.isExecutePermission(); } @Override public boolean exists() { if(!MockFramework.isEnabled()) { return super.exists(); } return VirtualFileSystem.getInstance().exists(getAbsolutePath()); } @Override public boolean isDirectory() { if(!MockFramework.isEnabled()) { return super.isDirectory(); } FSObject file = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(file==null) { return false; } return file.isFolder(); } @Override public boolean isFile() { if(!MockFramework.isEnabled()) { return super.isFile(); } return !isDirectory(); } @Override public boolean isHidden() { if(!MockFramework.isEnabled()) { return super.isHidden(); } if(getName().startsWith(".")) { //this is not necessarily true in Windows return true; } else { return false; } } @Override public boolean setLastModified(long time) { if(!MockFramework.isEnabled()) { return super.setLastModified(time); } if (time < 0) { throw new MockIllegalArgumentException("Negative time"); } FSObject target = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(target==null) { return false; } return target.setLastModified(time); } @Override public long lastModified() { if(!MockFramework.isEnabled()) { return super.lastModified(); } FSObject target = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(target==null) { return 0; } return target.getLastModified(); } @Override public long length() { if(!MockFramework.isEnabled()) { return super.length(); } FSObject target = VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); if(target==null) { return 0; } if(target.isFolder() || target.isDeleted()) { return 0; } VFile file = (VFile) target; return file.getDataSize(); } //following 3 methods are never used in SF110 @Override public long getTotalSpace() { if(!MockFramework.isEnabled()) { return super.getTotalSpace(); } return 0; //TODO } @Override public long getFreeSpace() { if(!MockFramework.isEnabled()) { return super.getFreeSpace(); } return 0; //TODO } @Override public long getUsableSpace() { if(!MockFramework.isEnabled()) { return super.getUsableSpace(); } return 0; //TODO } @Override public boolean createNewFile() throws IOException { if(!MockFramework.isEnabled()) { return super.createNewFile(); } VirtualFileSystem.getInstance().throwSimuledIOExceptionIfNeeded(getAbsolutePath()); return VirtualFileSystem.getInstance().createFile(getAbsolutePath()); } @Override public boolean delete() { if(!MockFramework.isEnabled()) { return super.delete(); } return VirtualFileSystem.getInstance().deleteFSObject(getAbsolutePath()); } @Override public boolean renameTo(File dest) { if(!MockFramework.isEnabled()) { return super.renameTo(dest); } boolean renamed = VirtualFileSystem.getInstance().rename( this.getAbsolutePath(), dest.getAbsolutePath()); return renamed; } @Override public boolean mkdir() { if(!MockFramework.isEnabled()) { return super.mkdir(); } String parent = this.getParent(); if(parent==null || !VirtualFileSystem.getInstance().exists(parent)) { return false; } return VirtualFileSystem.getInstance().createFolder(getAbsolutePath()); } @Override public void deleteOnExit() { if(!MockFramework.isEnabled()) { super.deleteOnExit(); } /* * do nothing, as anyway no actual file is created */ } @Override public String[] list() { if(!MockFramework.isEnabled()) { return super.list(); } if(!isDirectory() || !exists()) { return null; } else { VFolder dir = (VFolder) VirtualFileSystem.getInstance().findFSObject(getAbsolutePath()); return dir.getChildrenNames(); } } @Override public File[] listFiles() { if(!MockFramework.isEnabled()) { return super.listFiles(); } String[] ss = list(); if (ss == null) return null; int n = ss.length; MockFile[] fs = new MockFile[n]; for (int i = 0; i < n; i++) { fs[i] = new MockFile(this,ss[i]); } return fs; } @Override public File[] listFiles(FileFilter filter) { if(!MockFramework.isEnabled()) { return super.listFiles(filter); } String ss[] = list(); if (ss == null) return null; ArrayList<File> files = new ArrayList<File>(); for (String s : ss) { File f = new MockFile(this,s); if ((filter == null) || filter.accept(f)) files.add(f); } return files.toArray(new File[files.size()]); } @Override public String getCanonicalPath() throws IOException { if(!MockFramework.isEnabled()) { return super.getCanonicalPath(); } VirtualFileSystem.getInstance().throwSimuledIOExceptionIfNeeded(getAbsolutePath()); return super.getCanonicalPath(); } @Override public URL toURL() throws MalformedURLException { if(!MockFramework.isEnabled() || !RuntimeSettings.useVNET) { return super.toURL(); } URL url = super.toURL(); return MockURL.URL(url.toString()); } // -------- unmodified methods -------------- @Override public String getName() { return super.getName(); } @Override public String getParent() { return super.getParent(); } @Override public String getPath() { return super.getPath(); } @Override public boolean isAbsolute() { return super.isAbsolute(); } @Override public URI toURI() { return super.toURI(); //no need of VNET here } @Override public String[] list(FilenameFilter filter) { //no need to mock it, as it uses the mocked list() return super.list(filter); } @Override public boolean mkdirs() { //no need to mock it, as all methods it calls are mocked return super.mkdirs(); } @Override public boolean setWritable(boolean writable) { return super.setWritable(writable); // it calls mocked method } @Override public boolean setReadable(boolean readable) { return super.setReadable(readable); //it calls mocked method } @Override public boolean setExecutable(boolean executable) { return super.setExecutable(executable); // it calls mocked method } // ------- Object methods ----------- @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public int hashCode() { return super.hashCode(); } @Override public String toString() { return super.toString(); } }