1 19 20 package org.netbeans.modules.localhistory.store; 21 22 import java.io.BufferedInputStream ; 23 import java.io.BufferedOutputStream ; 24 import java.io.DataInputStream ; 25 import java.io.File ; 26 import java.io.FileInputStream ; 27 import java.io.FileOutputStream ; 28 import java.io.InputStream ; 29 import java.lang.reflect.InvocationTargetException ; 30 import java.lang.reflect.Method ; 31 import java.util.HashMap ; 32 import java.util.Map ; 33 import org.netbeans.junit.NbTestCase; 34 import org.netbeans.modules.localhistory.utils.FileUtils; 35 36 38 public class LocalHistoryStoreTest extends NbTestCase { 39 40 private static int DELETED = 0; 41 private static int TOUCHED = 1; 42 43 public LocalHistoryStoreTest(String testName) { 44 super(testName); 45 System.setProperty("netbeans.user", getDataDir().getAbsolutePath()); 46 } 47 48 public void testFileCreate() throws Exception { 49 cleanUpStore(); 50 51 LocalHistoryStore store = LocalHistoryStoreFactory.getInstance().createLocalHistoryStorage(); 52 long ts = System.currentTimeMillis(); 53 54 File file = new File (getDataDir(), "file1"); 56 createFile(store, file, ts, "data"); 57 checkFile(file, ts, -1, 2, 1, "data", TOUCHED); 59 60 File storefile = getStoreFile(file, ts); 61 checkFile(file, ts, storefile.lastModified(), 2, 1, "data", TOUCHED); 67 68 file = new File (getDataDir(), "file2"); 70 createFile(store, file, ts, "data"); 71 checkFile(file, ts, -1, 2, 1, "data", TOUCHED); 73 74 83 File folder = new File (getDataDir(), "folder"); 85 ts = System.currentTimeMillis(); 86 createFile(store, folder, ts, null); 88 checkFile(folder, ts, -1, 1, 1, null, TOUCHED); 90 91 file = new File (folder, "file2"); 92 createFile(store, file, ts, "data"); 93 checkFile(file, ts, -1, 2, 2, "data", TOUCHED); 95 98 file = new File (folder, "file3"); 100 createFile(store, file, ts, "data"); 101 checkFile(file, ts, -1, 2, 2, "data", TOUCHED); 102 104 } 106 107 public void testFileChange() throws Exception { 108 cleanUpStore(); 109 110 LocalHistoryStore store = LocalHistoryStoreFactory.getInstance().createLocalHistoryStorage(); 111 long ts = System.currentTimeMillis(); 112 113 File file = new File (getDataDir(), "file1"); 115 createFile(store, file, ts, "data"); 116 117 File storefile = getStoreFile(file, ts); 118 checkFile(file, ts, storefile.lastModified(), 2, 1, "data", TOUCHED); 125 126 ts = System.currentTimeMillis(); 128 changeFile(store, file, ts, "data2"); 129 checkFile(file, ts, -1, 3, 1, "data2", TOUCHED); 131 } 132 133 public void testFileDelete() throws Exception { 134 cleanUpStore(); 135 136 LocalHistoryStore store = LocalHistoryStoreFactory.getInstance().createLocalHistoryStorage(); 137 long ts = System.currentTimeMillis(); 138 139 File file = new File (getDataDir(), "file1"); 141 createFile(store, file, ts, "data"); 142 143 store.fileDelete(file, ts); 144 File storefile = getStoreFile(file, ts); 146 checkFile(file, ts, storefile.lastModified(), 2, 1, "data", DELETED); 147 148 file = new File (getDataDir(), "file2"); 149 createFile(store, file, ts, "data"); 150 151 store.fileDelete(file, ts); 152 storefile = getStoreFile(file, ts); 154 checkFile(file, ts, storefile.lastModified(), 2, 1, "data", DELETED); 155 } 156 157 public void testRevertTo() throws Exception { 158 cleanUpStore(); 159 cleanUpDataFolder(); 160 161 LocalHistoryStore store = LocalHistoryStoreFactory.getInstance().createLocalHistoryStorage(); 162 163 File folder = new File (getDataDir(), "datafolder"); 165 setupFirstFolderToRevert(store, folder); 166 167 File [] files = folder.listFiles(); 168 assertEquals(files.length, 7); 177 store.fileDelete(folder, System.currentTimeMillis()); 178 Thread.sleep(1000); long revertToTS = System.currentTimeMillis(); 180 181 StoreEntry[] entries = store.getFolderState(folder, files , revertToTS); 182 assertEquals(entries.length, 0); 184 185 cleanUpStore(); 186 cleanUpDataFolder(); 187 folder = new File (getDataDir(), "datafolder"); 188 revertToTS = setupFirstFolderToRevert(store, folder); 189 files = folder.listFiles(); 190 files = folder.listFiles(); 191 assertEquals(files.length, 7); 199 202 203 entries = store.getFolderState(folder, files , revertToTS); 204 205 for(StoreEntry se : entries) { 206 System.out.println(se.getFile().getName()); 207 } 208 209 assertEquals(entries.length, 8); 210 219 222 Map <String , StoreEntry> entriesMap = new HashMap <String , StoreEntry>(); 223 for(StoreEntry se : entries) { 224 entriesMap.put(se.getFile().getName(), se); 225 } 226 assertNull(entriesMap.get("fileNotInStorage")); 227 228 assertNotNull(entriesMap.get("fileUnchanged")); 229 assertNotNull(entriesMap.get("fileChangedAfterRevert")); 230 assertNotNull(entriesMap.get("fileDeletedAfterRevert")); 231 assertNotNull(entriesMap.get("fileUndeletedBeforeRevert")); 232 assertNotNull(entriesMap.get("fileCreatedAfterRevert")); 233 assertNotNull(entriesMap.get("fileDeletedBeforeRevert")); 234 assertNotNull(entriesMap.get("folderDeletedAfterRevert")); 235 assertNotNull(entriesMap.get("folderCreatedAfterRevert")); 236 237 assertNotNull(entriesMap.get("fileUnchanged").getStoreFile()); 238 assertNotNull(entriesMap.get("fileChangedAfterRevert").getStoreFile()); 239 assertNotNull(entriesMap.get("fileDeletedAfterRevert").getStoreFile()); 240 assertNotNull(entriesMap.get("fileUndeletedBeforeRevert").getStoreFile()); 241 assertNotNull(entriesMap.get("folderDeletedAfterRevert").getStoreFile()); 242 assertNull(entriesMap.get("fileCreatedAfterRevert").getStoreFile()); 243 assertNull(entriesMap.get("fileDeletedBeforeRevert").getStoreFile()); 244 assertNull(entriesMap.get("folderCreatedAfterRevert").getStoreFile()); 245 246 String strStore = read(entriesMap.get("fileChangedAfterRevert").getStoreFileInputStream(), 1024); 247 String strFile = read(new FileInputStream (entriesMap.get("fileChangedAfterRevert").getFile()), 1024); 248 assertNotSame(strFile, strStore); 249 } 250 251 private long setupFirstFolderToRevert(LocalHistoryStore store, File folder) throws Exception { 252 253 File fileNotInStorage = new File (folder, "fileNotInStorage"); 254 File fileUnchanged = new File (folder, "fileUnchanged"); 255 File fileChangedAfterRevert = new File (folder, "fileChangedAfterRevert"); 256 File fileDeletedAfterRevert = new File (folder, "fileDeletedAfterRevert"); 257 File fileDeletedBeforeRevert = new File (folder, "fileDeletedBeforeRevert"); 258 File fileUndeletedBeforeRevert = new File (folder, "fileUndeletedBeforeRevert"); 259 File fileCreatedAfterRevert = new File (folder, "fileCreatedAfterRevert"); 260 261 File folderDeletedAfterRevert = new File (folder, "folderDeletedAfterRevert"); 262 File folderCreatedAfterRevert = new File (folder, "folderCreatedAfterRevert"); 263 264 createFile(store, folder, System.currentTimeMillis(), null); 265 write(fileNotInStorage, "fileNotInStorage".getBytes()); 266 createFile(store, fileUnchanged, System.currentTimeMillis(), "fileUnchanged"); 267 createFile(store, fileChangedAfterRevert, System.currentTimeMillis(), "fileChangedAfterRevert BEFORE change"); 268 createFile(store, fileDeletedAfterRevert, System.currentTimeMillis(), "fileDeletedAfterRevert BEFORE delete"); 269 createFile(store, fileDeletedBeforeRevert, System.currentTimeMillis(), "fileDeletedBeforeRevert BEFORE delete"); 270 createFile(store, fileUndeletedBeforeRevert, System.currentTimeMillis(), "fileUndeletedBeforeRevert"); 271 272 createFile(store, folderDeletedAfterRevert, System.currentTimeMillis(), null); 273 274 275 276 fileDeletedBeforeRevert.delete(); 277 store.fileDelete(fileDeletedBeforeRevert, System.currentTimeMillis()); 278 279 fileUndeletedBeforeRevert.delete(); 280 store.fileDelete(fileUndeletedBeforeRevert, System.currentTimeMillis()); 281 createFile(store, fileUndeletedBeforeRevert, System.currentTimeMillis(), "fileUndeletedBeforeRevert BEFORE revert"); 282 283 Thread.sleep(1000); long revertToTS = System.currentTimeMillis(); 286 Thread.sleep(1000); 289 changeFile(store, fileChangedAfterRevert, System.currentTimeMillis(), "fileChanged AFTER change"); 290 291 fileDeletedAfterRevert.delete(); 292 store.fileDelete(fileDeletedAfterRevert, System.currentTimeMillis()); 293 294 createFile(store, fileDeletedBeforeRevert, System.currentTimeMillis(), "fileDeletedBeforeRevert after delete"); 295 296 createFile(store, fileCreatedAfterRevert, System.currentTimeMillis(), "fileCreatedAfterRevert"); 297 298 folderDeletedAfterRevert.delete(); 299 store.fileDelete(folderDeletedAfterRevert, System.currentTimeMillis()); 300 301 createFile(store, folderCreatedAfterRevert, System.currentTimeMillis(), null); 302 303 304 assertTrue(folder.exists()); 306 assertTrue(fileNotInStorage.exists()); 307 assertTrue(fileUnchanged.exists()); 308 assertTrue(fileChangedAfterRevert.exists()); 309 assertTrue(!fileDeletedAfterRevert.exists()); 310 assertTrue(fileDeletedBeforeRevert.exists()); 311 assertTrue(fileCreatedAfterRevert.exists()); 312 assertTrue(!folderDeletedAfterRevert.exists()); 313 assertTrue(folderCreatedAfterRevert.exists()); 314 315 File [] files = folder.listFiles(); 316 assertEquals(files.length, 7); 325 return revertToTS; 326 } 327 328 private void checkFile(File file, long ts, long storeFileLastModified, int siblings, int parentChildren, String data, int action) throws Exception { 329 330 File storeFolder = getStoreFolder(file); 331 String [] files = storeFolder.list(); 332 assertTrue(files != null && files.length == siblings); 333 334 File storeParent = getStoreFolder(file.getParentFile()); 335 files = storeParent.list(); 336 assertTrue(files != null && files.length == parentChildren); 337 338 if(file.isFile()) { 339 File storefile = getStoreFile(file, ts); 340 assertTrue(storefile.exists()); 341 if(data != null) assertTrue(containsData(storefile, data.getBytes())); 342 } 343 344 File dataFle = getDataFile(file); 345 assertTrue(dataFle.exists()); 346 assertTrue(contains(dataFle, file.isFile(), action, ts, file.getAbsolutePath())); 347 if(storeFileLastModified!=-1) assertTrue(storeFileLastModified == storeFolder.lastModified()); 348 } 349 350 358 private void createFile(LocalHistoryStore store, File file, long ts, String data) throws Exception { 359 if(data != null) { 360 write(file, data.getBytes()); 361 } else { 362 file.mkdirs(); 363 } 364 store.fileCreate(file, ts); 365 } 366 367 private void changeFile(LocalHistoryStore store, File file, long ts, String data) throws Exception { 368 write(file, data.getBytes()); 369 store.fileChange(file, ts); 370 } 371 372 private void write(File file, byte[] data) throws Exception { 373 BufferedOutputStream bos = null; 374 try { 375 bos = new BufferedOutputStream (new FileOutputStream (file)); 376 bos.write(data); 377 } catch(Exception e) { 378 throw e; 379 } finally { 380 if(bos != null) { bos.close(); }; 381 } 382 } 383 384 private String read(InputStream is, int length) throws Exception { 385 try { 386 byte[] buffer = new byte[length]; 387 int len = is.read(buffer); 388 return new String (java.util.Arrays.copyOfRange(buffer, 0, len)); 389 } catch(Exception e) { 390 throw e; 391 } finally { 392 if(is != null) { is.close(); }; 393 } 394 } 395 396 private boolean contains(File file, boolean isFile, int action, long modified, String filePath) throws Exception { 397 DataInputStream dis = null; 398 try { 399 dis = new DataInputStream (new FileInputStream (file)); 400 boolean f = dis.readBoolean(); 401 int i = dis.readInt(); 402 long l = dis.readLong(); 403 int len = dis.readInt(); 404 StringBuffer fileName = new StringBuffer (); 405 while( len-- > 0 ) { 406 char c = dis.readChar(); 407 fileName.append(c); 408 } 409 return f == isFile && modified == l && action == i && fileName.toString().equals(filePath); 410 } catch(Exception e) { 411 throw e; 412 } finally { 413 if(dis != null) { dis.close(); }; 414 } 415 } 416 417 private boolean containsData(File file, byte[] data) throws Exception { 418 BufferedInputStream bis = null; 419 try { 420 bis = new BufferedInputStream (new FileInputStream (file)); 421 byte[] contents = new byte[data.length]; 422 int l = bis.read(contents); 423 if(l != data.length) return false; 424 for (int i = 0; i < contents.length; i++) { 425 if(contents[i] != data[i]) return false; 426 } 427 return true; 428 } catch(Exception e) { 429 throw e; 430 } finally { 431 if(bis != null) { bis.close(); }; 432 } 433 } 434 435 private Method getStoreFolderMethod; 436 private Method getDataDileMethod; 437 private Method getStoreFileMethod; 438 private Method cleanUpImplMethod; 439 private Object storage; 440 441 private File getStoreFolder(File file) throws ClassNotFoundException , NoSuchMethodException , InstantiationException , IllegalAccessException , IllegalArgumentException , InvocationTargetException { 442 if(getStoreFolderMethod == null) { 443 getStoreFolderMethod = getStorage().getClass().getDeclaredMethod("getStoreFolder", new Class [] {File .class}); 444 getStoreFolderMethod.setAccessible(true); 445 } 446 return (File ) getStoreFolderMethod.invoke(storage, new Object []{file}); 447 } 448 449 private File getDataFile(File file) throws ClassNotFoundException , NoSuchMethodException , InstantiationException , IllegalAccessException , IllegalArgumentException , InvocationTargetException { 450 if(getDataDileMethod == null) { 451 getDataDileMethod = getStorage().getClass().getDeclaredMethod("getDataFile", new Class [] {File .class}); 452 getDataDileMethod.setAccessible(true); 453 } 454 return (File ) getDataDileMethod.invoke(storage, new Object []{file}); 455 } 456 457 private File getStoreFile(File file, long ts) throws ClassNotFoundException , NoSuchMethodException , InstantiationException , IllegalAccessException , IllegalArgumentException , InvocationTargetException { 458 if(getStoreFileMethod == null) { 459 getStoreFileMethod = getStorage().getClass().getDeclaredMethod("getStoreFile", new Class [] {File .class, String .class, boolean.class}); 460 getStoreFileMethod.setAccessible(true); 461 } 462 return (File ) getStoreFileMethod.invoke(storage, new Object []{file, Long.toString(ts), true}); 463 } 464 465 private Object getStorage() throws ClassNotFoundException , InstantiationException , IllegalAccessException { 466 if(storage == null) { 467 storage = LocalHistoryStoreFactory.getInstance().createLocalHistoryStorage(); 468 } 472 return storage; 473 } 474 475 private File getStoreMainFolder() { 476 return new File (getDataDir(), "localhistory"); 477 } 478 479 private void cleanUpDataFolder() { 480 FileUtils.deleteRecursively(getDataDir()); 481 } 482 483 private void cleanUpStore() throws Exception { 484 if(cleanUpImplMethod == null) { 485 cleanUpImplMethod = getStorage().getClass().getDeclaredMethod("cleanUpImpl", new Class [] {long.class}); 486 cleanUpImplMethod.setAccessible(true); 487 } 488 cleanUpImplMethod.invoke(getStorage(), new Object []{1}); 489 } 490 } 491 | Popular Tags |