1/* 2 * Copyright 2008 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package org.mockftpserver.fake.filesystem 17 18import java.io.IOException 19import java.io.InputStream 20import java.io.OutputStream 21import java.lang.reflect.InvocationTargetException 22import java.lang.reflect.Method 23import java.util.Collections 24import java.util.HashSet 25import java.util.List 26 27import org.apache.log4j.Logger 28import org.mockftpserver.core.util.IoUtil 29import org.mockftpserver.test.AbstractGroovyTest 30 31/** 32 * Abstract superclass for tests of FileSystem implementation classes. Contains common 33 * tests and test infrastructure. 34 * 35 * @version $Revision: $ - $Date: $ 36 * 37 * @author Chris Mair 38 */ 39abstract class AbstractFileSystemTest extends AbstractGroovyTest { 40 41 public static final FILENAME1 = "file1.txt" 42 public static final FILENAME2 = "file2.txt" 43 public static final DIR1 = "dir1" 44 public static final NEW_DIRNAME = "testdir" 45 public static final ILLEGAL_FILE = "xx/yy////z!<>?*z.txt" 46 public static final EXISTING_FILE_CONTENTS = "abc 123 %^& xxx" 47 48 // These must be set by the concrete subclass (in its constructor) 49 protected String NEW_DIR = null 50 protected String NEW_FILE = null 51 protected String EXISTING_DIR = null 52 protected String EXISTING_FILE = null 53 protected NO_SUCH_DIR = null 54 protected NO_SUCH_FILE = null 55 56 protected FileSystem fileSystem 57 58 //------------------------------------------------------------------------- 59 // Common Tests 60 //------------------------------------------------------------------------- 61 62 /** 63 * Test the exists() method 64 */ 65 void testExists() { 66 assert !fileSystem.exists(NEW_FILE) 67 assert !fileSystem.exists(NEW_DIR) 68 assert !fileSystem.exists(ILLEGAL_FILE) 69 assert fileSystem.exists(EXISTING_FILE) 70 assert fileSystem.exists(EXISTING_DIR) 71 72 shouldFailWithMessageContaining("path") { fileSystem.exists(null) } 73 } 74 75 /** 76 * Test the isDirectory() method 77 */ 78 void testIsDirectory() { 79 assert fileSystem.isDirectory(EXISTING_DIR) 80 assert !fileSystem.isDirectory(EXISTING_FILE) 81 assert !fileSystem.isDirectory(NO_SUCH_DIR) 82 assert !fileSystem.isDirectory(NO_SUCH_FILE) 83 assert !fileSystem.isDirectory(ILLEGAL_FILE) 84 85 shouldFailWithMessageContaining("path") { fileSystem.isDirectory(null) } 86 } 87 88 /** 89 * Test the isFile() method 90 */ 91 void testIsFile() { 92 assert fileSystem.isFile(EXISTING_FILE) 93 assert !fileSystem.isFile(EXISTING_DIR) 94 assert !fileSystem.isFile(NO_SUCH_DIR) 95 assert !fileSystem.isFile(NO_SUCH_FILE) 96 assert !fileSystem.isFile(ILLEGAL_FILE) 97 98 shouldFailWithMessageContaining("path") { fileSystem.isFile(null) } 99 } 100 101 /** 102 * Test the createDirectory() method 103 */ 104 void testCreateDirectory() { 105 assert !fileSystem.exists(NEW_DIR), "Before createDirectory" 106 assert fileSystem.createDirectory(NEW_DIR) 107 assert fileSystem.exists(NEW_DIR), "After createDirectory" 108 109 // Duplicate directory 110 assert !fileSystem.createDirectory(NEW_DIR), "Duplicate directory" 111 112 // The parent of the path does not exist 113 assert !fileSystem.createDirectory(NEW_DIR + "/abc/def"), "Parent does not exist" 114 115 shouldFailWithMessageContaining("path") { fileSystem.createDirectory(null) } 116 } 117 118 /** 119 * Test the createFile() method 120 */ 121 void testCreateFile() { 122 assert !fileSystem.exists(NEW_FILE), "Before createFile" 123 assert fileSystem.createFile(NEW_FILE) 124 assert fileSystem.exists(NEW_FILE), "After createFile" 125 126 assert !fileSystem.createFile(NEW_FILE), "Duplicate" 127 128 // The parent of the path does not exist 129 shouldFail(FileSystemException) { fileSystem.createFile(NEW_DIR + "/abc/def") } 130 131 shouldFail(FileSystemException) { fileSystem.createFile(NO_SUCH_DIR) } 132 shouldFail(InvalidFilenameException) { fileSystem.createFile(ILLEGAL_FILE) } 133 134 shouldFailWithMessageContaining("path") { fileSystem.createFile(null) } 135 } 136 137 /** 138 * Test the createInputStream() method 139 */ 140 void testCreateInputStream() { 141 InputStream input = fileSystem.createInputStream(EXISTING_FILE) 142 assert EXISTING_FILE_CONTENTS.getBytes() == IoUtil.readBytes(input) 143 144 shouldFail(FileSystemException) { fileSystem.createInputStream(NO_SUCH_FILE) } 145 shouldFail(FileSystemException) { fileSystem.createInputStream(EXISTING_DIR) } 146 shouldFail(FileSystemException) { fileSystem.createInputStream("") } 147 148 shouldFailWithMessageContaining("path") { fileSystem.createInputStream(null) } 149 } 150 151 /** 152 * Test the createOutputStream() method 153 */ 154 void testCreateOutputStream() { 155 // New, empty file 156 OutputStream out = fileSystem.createOutputStream(NEW_FILE, false) 157 out.close() 158 verifyFileContents(fileSystem, NEW_FILE, "") 159 160 // Append = false 161 out = fileSystem.createOutputStream(NEW_FILE, false) 162 out.write(EXISTING_FILE_CONTENTS.getBytes()) 163 out.close() 164 verifyFileContents(fileSystem, NEW_FILE, EXISTING_FILE_CONTENTS) 165 166 // Append = true 167 out = fileSystem.createOutputStream(NEW_FILE, true) 168 out.write(EXISTING_FILE_CONTENTS.getBytes()) 169 String expectedContents = EXISTING_FILE_CONTENTS.concat(EXISTING_FILE_CONTENTS) 170 verifyFileContents(fileSystem, NEW_FILE, expectedContents) 171 172 // Yet another OutputStream, append=true (so should append to accumulated contents) 173 OutputStream out2 = fileSystem.createOutputStream(NEW_FILE, true) 174 out2.write("abc".getBytes()) 175 out2.close() 176 expectedContents = expectedContents + "abc" 177 verifyFileContents(fileSystem, NEW_FILE, expectedContents) 178 179 // Write with the previous OutputStream (simulate 2 OututStreams writing "concurrently") 180 out.write("def".getBytes()) 181 out.close() 182 expectedContents = expectedContents + "def" 183 verifyFileContents(fileSystem, NEW_FILE, expectedContents) 184 } 185 186 /** 187 * Test the createOutputStream() method, when a FileSystemException is expected 188 */ 189 void testCreateOutputStream_FileSystemException() { 190 // Parent directory does not exist 191 shouldFail(FileSystemException) { fileSystem.createOutputStream(NEW_DIR + "/abc.txt", true) } 192 193 shouldFail(FileSystemException) { fileSystem.createOutputStream(EXISTING_DIR, true) } 194 shouldFail(InvalidFilenameException) { fileSystem.createOutputStream(ILLEGAL_FILE, true) } 195 shouldFail(FileSystemException) { fileSystem.createOutputStream("", true) } 196 } 197 198 /** 199 * Test the createOutputStream() method, passing in a null path 200 */ 201 void testCreateOutputStream_NullPath() { 202 shouldFailWithMessageContaining("path") { fileSystem.createOutputStream(null, true) } 203 } 204 205 /** 206 * Test the rename() method, passing in a null fromPath 207 */ 208 void testRename_NullFromPath() { 209 shouldFailWithMessageContaining("fromPath") { fileSystem.rename(null, FILENAME1) } 210 } 211 212 /** 213 * Test the rename() method, passing in a null toPath 214 */ 215 void testRename_NullToPath() { 216 shouldFailWithMessageContaining("toPath") { fileSystem.rename(FILENAME1, null) } 217 } 218 219 /** 220 * Test the listNames() method 221 */ 222 void testListNames() { 223 assert fileSystem.createDirectory(NEW_DIR) 224 assert fileSystem.listNames(NEW_DIR) == [] 225 226 assert fileSystem.createFile(NEW_DIR + "/" + FILENAME1) 227 assert fileSystem.createFile(NEW_DIR + "/" + FILENAME2) 228 assert fileSystem.createDirectory(NEW_DIR + "/" + DIR1) 229 assert fileSystem.createFile(NEW_DIR + "/" + DIR1 + "/abc.def" ) 230 231 List filenames = fileSystem.listNames(NEW_DIR) 232 LOG.info("filenames=" + filenames) 233 assert [FILENAME1, FILENAME2, DIR1] as Set == filenames as Set 234 235 assert [] == fileSystem.listNames(NO_SUCH_DIR) 236 assert [] == fileSystem.listNames(NEW_DIR + "/" + FILENAME1) 237 238 shouldFailWithMessageContaining("path") { fileSystem.listNames(null) } 239 } 240 241 /** 242 * Test listFiles() method 243 */ 244 void testListFiles() { 245 final DATE = new Date() 246 assert fileSystem.createDirectory(NEW_DIR) 247 assert [] == fileSystem.listFiles(NEW_DIR) 248 249 assert fileSystem.createFile(p(NEW_DIR,FILENAME1)) 250 FileInfo fileInfo1 = FileInfo.forFile(FILENAME1, 0, DATE) 251 assert [fileInfo1] == fileSystem.listFiles(NEW_DIR) 252 253 // Specify a filename instead of a directory name 254 assert [fileInfo1] == fileSystem.listFiles(p(NEW_DIR,FILENAME1)) 255 256 assert fileSystem.createFile(p(NEW_DIR, FILENAME2)) 257 FileInfo fileInfo2 = FileInfo.forFile(FILENAME2, 0, DATE) 258 assert [fileInfo1, fileInfo2] as Set == fileSystem.listFiles(NEW_DIR) as Set 259 260 // Write to the file to get a non-zero length 261 final byte[] CONTENTS = "1234567890".getBytes() 262 OutputStream out = fileSystem.createOutputStream(NEW_DIR + "/" + FILENAME1, false) 263 out.write(CONTENTS) 264 out.close() 265 fileInfo1 = FileInfo.forFile(FILENAME1, CONTENTS.length, DATE) 266 assert [fileInfo1, fileInfo2] as Set == fileSystem.listFiles(NEW_DIR) as Set 267 268 assert fileSystem.createDirectory(p(NEW_DIR,DIR1)) 269 FileInfo fileInfo3 = FileInfo.forDirectory(DIR1, DATE) 270 assert [fileInfo1, fileInfo2, fileInfo3] as Set == fileSystem.listFiles(NEW_DIR) as Set 271 272 assert fileSystem.listFiles(NO_SUCH_DIR) == [] 273 274 shouldFailWithMessageContaining("path") { fileSystem.listFiles(null) } 275 } 276 277 /** 278 * Test the delete() method 279 */ 280 void testDelete() { 281 assert fileSystem.createFile(NEW_FILE) 282 assert fileSystem.delete(NEW_FILE) 283 assert !fileSystem.exists(NEW_FILE) 284 285 assert !fileSystem.delete(NO_SUCH_FILE) 286 287 assert fileSystem.createDirectory(NEW_DIR) 288 assert fileSystem.delete(NEW_DIR) 289 assert !fileSystem.exists(NEW_DIR) 290 291 assert fileSystem.createDirectory(NEW_DIR) 292 assert fileSystem.createFile(NEW_DIR + "/abc.txt") 293 294 assert !fileSystem.delete(NEW_DIR), "Directory containing files" 295 assert fileSystem.exists(NEW_DIR) 296 297 shouldFailWithMessageContaining("path") { fileSystem.delete(null) } 298 } 299 300 /** 301 * Test the rename() method 302 */ 303 void testRename() { 304 final String FROM_FILE = NEW_FILE + "2" 305 assert fileSystem.createFile(FROM_FILE) 306 307 assert fileSystem.rename(FROM_FILE, NEW_FILE) 308 assert fileSystem.exists(NEW_FILE) 309 310 fileSystem.createFile(NEW_FILE) 311 fileSystem.createDirectory(NEW_DIR) 312 313 // Rename existing directory 314 final String TO_DIR = NEW_DIR + "2" 315 assert fileSystem.rename(NEW_DIR, TO_DIR) 316 assert !fileSystem.exists(NEW_DIR) 317 assert fileSystem.exists(TO_DIR) 318 319 // Path of FROM file/dir does not exist 320 final String TO_FILE2 = NEW_FILE + "2" 321 assert !fileSystem.rename(NO_SUCH_FILE, TO_FILE2) 322 assert !fileSystem.exists(TO_FILE2), "After failed rename" 323 } 324 325 /** 326 * Test the rename() method on a directory that contains files 327 */ 328 public void testRename_DirectoryContainsFiles() { 329 fileSystem.createDirectory(NEW_DIR) 330 fileSystem.createFile(NEW_DIR + "/a.txt") 331 fileSystem.createFile(NEW_DIR + "/b.txt") 332 fileSystem.createDirectory(NEW_DIR + "/subdir") 333 334 final String TO_DIR = NEW_DIR + "2" 335 assert fileSystem.rename(NEW_DIR, TO_DIR) 336 assert !fileSystem.exists(NEW_DIR) 337 assert !fileSystem.exists(NEW_DIR + "/a.txt") 338 assert !fileSystem.exists(NEW_DIR + "/b.txt") 339 assert !fileSystem.exists(NEW_DIR + "/subdir") 340 341 assert fileSystem.exists(TO_DIR) 342 assert fileSystem.exists(TO_DIR + "/a.txt") 343 assert fileSystem.exists(TO_DIR + "/b.txt") 344 assert fileSystem.exists(TO_DIR + "/subdir") 345 } 346 347 /** 348 * Test the rename() method, when the parent of the TO path does not exist 349 */ 350 public void testRename_ParentOfToPathDoesNotExist() throws Exception { 351 final String FROM_FILE = NEW_FILE 352 final String TO_FILE = fileSystem.path(NO_SUCH_DIR, "abc") 353 assert fileSystem.createFile(FROM_FILE) 354 355 assert !fileSystem.rename(FROM_FILE, TO_FILE) 356 assert fileSystem.exists(FROM_FILE) 357 assert !fileSystem.exists(TO_FILE) 358 } 359 360 /** 361 * Test the getName() method, passing in a null 362 */ 363 void testGetName_Null() { 364 shouldFailWithMessageContaining("path") { fileSystem.getName(null) } 365 } 366 367 /** 368 * Test the getParent() method, passing in a null 369 */ 370 void testGetParent_Null() { 371 shouldFailWithMessageContaining("path") { fileSystem.getParent(null) } 372 } 373 374// /** 375// * Test the normalize() method, passing in an illegal filename 376// */ 377// void testNormalize_InvalidPaths() { 378// shouldFail(InvalidFilenameException) { fileSystem.normalize(ILLEGAL_FILE) } 379// LOG.info(fileSystem.normalize(ILLEGAL_FILE)) 380// } 381 382 /** 383 * Test the normalize() method, passing in a null 384 */ 385 void testNormalize_Null() { 386 shouldFailWithMessageContaining("path") { fileSystem.normalize(null) } 387 } 388 389 //------------------------------------------------------------------------- 390 // Test setup 391 //------------------------------------------------------------------------- 392 393 /** 394 * @see org.mockftpserver.test.AbstractTest#setUp() 395 */ 396 void setUp() { 397 super.setUp() 398 fileSystem = createFileSystem() 399 } 400 401 //------------------------------------------------------------------------- 402 // Helper Methods 403 //------------------------------------------------------------------------- 404 405 /** 406 * Return a new instance of the FileSystem implementation class under test 407 * @return a new FileSystem instance 408 * @throws Exception 409 */ 410 protected abstract FileSystem createFileSystem() 411 412 /** 413 * Verify the contents of the file at the specified path read from its InputSteam 414 * 415 * @param fileSystem - the FileSystem instance 416 * @param expectedContents - the expected contents 417 * @throws IOException 418 */ 419 protected abstract void verifyFileContents(FileSystem fileSystem, String path, String contents) throws Exception 420 421 protected String p(String[] paths) { 422 return paths.join("/") 423 } 424 425 426}