Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
BackupFilesTest | 47 | 164 | 47 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.io; | |
22 | ||
23 | import java.io.File; | |
24 | import java.io.IOException; | |
25 | import java.nio.file.Files; | |
26 | import java.nio.file.Path; | |
27 | import java.nio.file.Paths; | |
28 | import java.util.Arrays; | |
29 | import java.util.Collections; | |
30 | import java.util.Enumeration; | |
31 | import java.util.HashMap; | |
32 | import java.util.List; | |
33 | import java.util.TreeMap; | |
34 | ||
35 | import org.testng.Assert; | |
36 | import org.testng.annotations.AfterClass; | |
37 | import org.testng.annotations.BeforeClass; | |
38 | import org.testng.annotations.Test; | |
39 | ||
40 | import jalview.bin.Cache; | |
41 | import jalview.datamodel.AlignmentI; | |
42 | import jalview.datamodel.Sequence; | |
43 | import jalview.datamodel.SequenceI; | |
44 | import jalview.gui.AlignFrame; | |
45 | import jalview.gui.JvOptionPane; | |
46 | ||
47 | public class BackupFilesTest | |
48 | { | |
49 | 1 | @BeforeClass(alwaysRun = true) |
50 | public void setUpJvOptionPane() | |
51 | { | |
52 | 1 | JvOptionPane.setInteractiveMode(false); |
53 | 1 | JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); |
54 | } | |
55 | ||
56 | private static boolean actuallyDeleteTmpFiles = true; | |
57 | ||
58 | private static String testDir = "test/jalview/io"; | |
59 | ||
60 | private static String testBasename = "backupfilestest"; | |
61 | ||
62 | private static String testExt = ".fa"; | |
63 | ||
64 | private static String testFilename = testBasename + testExt; | |
65 | ||
66 | private static String testFile = testDir + File.separatorChar | |
67 | + testFilename; | |
68 | ||
69 | private static String newBasename = testBasename + "Temp"; | |
70 | ||
71 | private static String newFilename = newBasename + testExt; | |
72 | ||
73 | private static String newFile = testDir + File.separatorChar | |
74 | + newFilename; | |
75 | ||
76 | private static String sequenceName = "BACKUP_FILES"; | |
77 | ||
78 | private static String sequenceDescription = "backupfiles"; | |
79 | ||
80 | private static String sequenceData = "AAAARG"; | |
81 | ||
82 | private static String suffix = "_BACKUPTEST-%n"; | |
83 | ||
84 | private static int digits = 6; | |
85 | ||
86 | private static int rollMax = 2; | |
87 | ||
88 | private AlignFrame af; | |
89 | ||
90 | // read and save with backupfiles disabled | |
91 | 1 | @Test(groups = { "Functional" }) |
92 | public void noBackupsEnabledTest() throws Exception | |
93 | { | |
94 | // set BACKUPFILES_ENABLED to false (i.e. turn off BackupFiles feature -- no | |
95 | // backup files to be made when saving) | |
96 | 1 | setBackupFilesOptions(false, true, true); |
97 | ||
98 | // init the newFile and backups (i.e. make sure newFile exists on its own | |
99 | // and has no backups | |
100 | 1 | initNewFileForTesting(); |
101 | ||
102 | // now save again | |
103 | 1 | save(); |
104 | ||
105 | // check no backup files | |
106 | 1 | File[] backupFiles = getBackupFiles(); |
107 | 1 | Assert.assertEquals(backupFiles.length, 0, "Number of backup files is " |
108 | + backupFiles.length + ", not " + 0); | |
109 | } | |
110 | ||
111 | // save with no numbers in the backup file names | |
112 | 1 | @Test(groups = { "Functional" }) |
113 | public void backupsEnabledSingleFileBackupTest() throws Exception | |
114 | { | |
115 | // Enable BackupFiles and set noMax so all backupfiles get kept | |
116 | 1 | String mysuffix = "~"; |
117 | 1 | BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(mysuffix, 1, |
118 | false, true, 1, false); | |
119 | 1 | setBackupFilesOptions(true, false, true, |
120 | "test/jalview/io/testProps_singlefilebackup.jvprops", bfpe); | |
121 | ||
122 | // init the newFile and backups (i.e. make sure newFile exists on its own | |
123 | // and has no backups) | |
124 | 1 | initNewFileForTesting(); |
125 | 1 | HashMap<Integer, String> correctindexmap = new HashMap<>(); |
126 | 1 | correctindexmap.put(0, "backupfilestestTemp.fa~"); |
127 | ||
128 | 1 | save(); |
129 | 1 | Assert.assertTrue(checkBackupFiles(correctindexmap, newFile, "~", 1)); |
130 | ||
131 | // and a second time -- see JAL-3628 | |
132 | 1 | save(); |
133 | 1 | Assert.assertTrue(checkBackupFiles(correctindexmap, newFile, "~", 1)); |
134 | ||
135 | 1 | cleanupTmpFiles(newFile, "~", 1); |
136 | } | |
137 | ||
138 | // save keeping all backup files | |
139 | 1 | @Test(groups = { "Functional" }) |
140 | public void backupsEnabledNoRollMaxTest() throws Exception | |
141 | { | |
142 | // Enable BackupFiles and set noMax so all backupfiles get kept | |
143 | 1 | setBackupFilesOptions(true, false, true); |
144 | ||
145 | // init the newFile and backups (i.e. make sure newFile exists on its own | |
146 | // and has no backups) | |
147 | 1 | initNewFileForTesting(); |
148 | ||
149 | // now save a few times again. No rollMax so should have more than two | |
150 | // backup files | |
151 | 1 | int numSaves = 10; |
152 | 11 | for (int i = 0; i < numSaves; i++) |
153 | { | |
154 | 10 | save(); |
155 | } | |
156 | ||
157 | // check 10 backup files | |
158 | 1 | HashMap<Integer, String> correctindexmap = new HashMap<>(); |
159 | 1 | correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-000001"); |
160 | 1 | correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002"); |
161 | 1 | correctindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-000003"); |
162 | 1 | correctindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-000004"); |
163 | 1 | correctindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-000005"); |
164 | 1 | correctindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-000006"); |
165 | 1 | correctindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-000007"); |
166 | 1 | correctindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-000008"); |
167 | 1 | correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009"); |
168 | 1 | correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010"); |
169 | 1 | HashMap<Integer, String> wrongindexmap = new HashMap<>(); |
170 | 1 | wrongindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-1"); |
171 | 1 | wrongindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002"); |
172 | 1 | wrongindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-000003"); |
173 | 1 | wrongindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-000004"); |
174 | 1 | wrongindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-000005"); |
175 | 1 | wrongindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-000006"); |
176 | 1 | wrongindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-000007"); |
177 | 1 | wrongindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-000008"); |
178 | 1 | wrongindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009"); |
179 | 1 | wrongindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010"); |
180 | 1 | int[] indexes2 = { 3, 4, 5, 6, 7, 8, 9, 10 }; |
181 | 1 | int[] indexes3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; |
182 | 1 | Assert.assertTrue(checkBackupFiles(correctindexmap)); |
183 | 1 | Assert.assertFalse(checkBackupFiles(wrongindexmap)); |
184 | 1 | Assert.assertFalse(checkBackupFiles(indexes2)); |
185 | 1 | Assert.assertFalse(checkBackupFiles(indexes3)); |
186 | } | |
187 | ||
188 | // save keeping only the last rollMax (2) backup files | |
189 | 1 | @Test(groups = { "Functional" }) |
190 | public void backupsEnabledRollMaxTest() throws Exception | |
191 | { | |
192 | // Enable BackupFiles and set noMax so all backupfiles get kept | |
193 | 1 | setBackupFilesOptions(true, false, false); |
194 | ||
195 | // init the newFile and backups (i.e. make sure newFile exists on its own | |
196 | // and has no backups) | |
197 | 1 | initNewFileForTesting(); |
198 | ||
199 | // now save a few times again. No rollMax so should have more than two | |
200 | // backup files | |
201 | 1 | int numSaves = 10; |
202 | 11 | for (int i = 0; i < numSaves; i++) |
203 | { | |
204 | 10 | save(); |
205 | } | |
206 | ||
207 | // check there are "rollMax" backup files and they are all saved correctly | |
208 | // check 10 backup files | |
209 | 1 | HashMap<Integer, String> correctindexmap = new HashMap<>(); |
210 | 1 | correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009"); |
211 | 1 | correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010"); |
212 | 1 | int[] indexes2 = { 10 }; |
213 | 1 | int[] indexes3 = { 8, 9, 10 }; |
214 | 1 | Assert.assertTrue(checkBackupFiles(correctindexmap)); |
215 | 1 | Assert.assertFalse(checkBackupFiles(indexes2)); |
216 | 1 | Assert.assertFalse(checkBackupFiles(indexes3)); |
217 | } | |
218 | ||
219 | // save keeping only the last rollMax (2) backup files | |
220 | 1 | @Test(groups = { "Functional" }) |
221 | public void backupsEnabledReverseRollMaxTest() throws Exception | |
222 | { | |
223 | // Enable BackupFiles and set noMax so all backupfiles get kept | |
224 | 1 | setBackupFilesOptions(true, true, false); |
225 | ||
226 | // init the newFile and backups (i.e. make sure newFile exists on its own | |
227 | // and has no backups) | |
228 | 1 | initNewFileForTesting(); |
229 | ||
230 | // now save a few times again. No rollMax so should have more than two | |
231 | // backup files | |
232 | 1 | int numSaves = 10; |
233 | 11 | for (int i = 0; i < numSaves; i++) |
234 | { | |
235 | 10 | save(); |
236 | } | |
237 | ||
238 | // check there are "rollMax" backup files and they are all saved correctly | |
239 | // check 10 backup files | |
240 | 1 | HashMap<Integer, String> correctindexmap = new HashMap<>(); |
241 | 1 | correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-000001"); |
242 | 1 | correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002"); |
243 | 1 | int[] indexes2 = { 1 }; |
244 | 1 | int[] indexes3 = { 1, 2, 3 }; |
245 | 1 | Assert.assertTrue(checkBackupFiles(correctindexmap)); |
246 | 1 | Assert.assertFalse(checkBackupFiles(indexes2)); |
247 | 1 | Assert.assertFalse(checkBackupFiles(indexes3)); |
248 | } | |
249 | ||
250 | 0 | private void setBackupFilesOptions() |
251 | { | |
252 | 0 | setBackupFilesOptions(true, false, false); |
253 | } | |
254 | ||
255 | 4 | private void setBackupFilesOptions(boolean enabled, boolean reverse, |
256 | boolean noMax) | |
257 | { | |
258 | 4 | BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(suffix, digits, |
259 | reverse, noMax, rollMax, false); | |
260 | 4 | setBackupFilesOptions(enabled, reverse, noMax, |
261 | "test/jalview/io/testProps.jvprops", bfpe); | |
262 | } | |
263 | ||
264 | 5 | private void setBackupFilesOptions(boolean enabled, boolean reverse, |
265 | boolean noMax, String propsFile, BackupFilesPresetEntry bfpe) | |
266 | { | |
267 | 5 | Cache.loadProperties(propsFile); |
268 | ||
269 | 5 | Cache.applicationProperties.setProperty(BackupFiles.ENABLED, |
270 | Boolean.toString(enabled)); | |
271 | 5 | Cache.applicationProperties.setProperty( |
272 | BackupFilesPresetEntry.SAVEDCONFIG, bfpe.toString()); | |
273 | /* | |
274 | Cache.applicationProperties.setProperty(BackupFiles.ENABLED, | |
275 | Boolean.toString(enabled)); | |
276 | Cache.applicationProperties.setProperty(BackupFiles.SUFFIX, suffix); | |
277 | Cache.applicationProperties.setProperty(BackupFiles.SUFFIX_DIGITS, | |
278 | Integer.toString(digits)); | |
279 | Cache.applicationProperties.setProperty(BackupFiles.REVERSE_ORDER, | |
280 | Boolean.toString(reverse)); | |
281 | Cache.applicationProperties.setProperty(BackupFiles.NO_MAX, | |
282 | Boolean.toString(noMax)); | |
283 | Cache.applicationProperties.setProperty(BackupFiles.ROLL_MAX, | |
284 | Integer.toString(rollMax)); | |
285 | Cache.applicationProperties.setProperty(BackupFiles.CONFIRM_DELETE_OLD, | |
286 | "false"); | |
287 | */ | |
288 | } | |
289 | ||
290 | 33 | private void save() |
291 | { | |
292 | 33 | if (af != null) |
293 | { | |
294 | 33 | af.saveAlignment(newFile, jalview.io.FileFormat.Fasta); |
295 | } | |
296 | } | |
297 | ||
298 | // this runs cleanTmpFiles and then writes the newFile once as a starting | |
299 | // point for all tests | |
300 | 5 | private void initNewFileForTesting() throws Exception |
301 | { | |
302 | 5 | cleanupTmpFiles(); |
303 | ||
304 | 5 | AppletFormatAdapter afa = new AppletFormatAdapter(); |
305 | 5 | AlignmentI al = afa.readFile(testFile, DataSourceType.FILE, |
306 | jalview.io.FileFormat.Fasta); | |
307 | 5 | List<SequenceI> l = al.getSequences(); |
308 | ||
309 | // check this is right | |
310 | 5 | if (l.size() != 1) |
311 | { | |
312 | 0 | throw new Exception("single sequence from '" + testFile |
313 | + "' not read in correctly (should be a single short sequence). List<SequenceI> size is wrong."); | |
314 | } | |
315 | 5 | SequenceI s = l.get(0); |
316 | 5 | Sequence ref = new Sequence(sequenceName, sequenceData); |
317 | 5 | ref.setDescription(sequenceDescription); |
318 | 5 | if (!sequencesEqual(s, ref)) |
319 | { | |
320 | 0 | throw new Exception("single sequence from '" + testFile |
321 | + "' not read in correctly (should be a single short sequence). SequenceI name, description or data is wrong."); | |
322 | } | |
323 | // save alignment file to new filename -- this doesn't test backups disabled | |
324 | // yet as this file shouldn't already exist | |
325 | 5 | af = new AlignFrame(al, 0, 0); |
326 | 5 | af.saveAlignment(newFile, jalview.io.FileFormat.Fasta); |
327 | } | |
328 | ||
329 | // this deletes the newFile (if it exists) and any saved backup file for it | |
330 | 6 | @AfterClass(alwaysRun = true) |
331 | private void cleanupTmpFiles() | |
332 | { | |
333 | 6 | cleanupTmpFiles(newFile, suffix, digits); |
334 | } | |
335 | ||
336 | 8 | protected static void cleanupTmpFiles(String file, String mysuffix, |
337 | int mydigits) | |
338 | { | |
339 | 8 | File newfile = new File(file); |
340 | 8 | if (newfile.exists()) |
341 | { | |
342 | 6 | newfile.delete(); |
343 | } | |
344 | 8 | File[] tmpFiles = getBackupFiles(file, mysuffix, mydigits); |
345 | 24 | for (int i = 0; i < tmpFiles.length; i++) |
346 | { | |
347 | 16 | if (actuallyDeleteTmpFiles) |
348 | { | |
349 | 16 | tmpFiles[i].delete(); |
350 | } | |
351 | else | |
352 | { | |
353 | 0 | System.out.println("Pretending to delete " + tmpFiles[i].getPath()); |
354 | } | |
355 | } | |
356 | } | |
357 | ||
358 | 9 | private static File[] getBackupFiles(String f, String s, int i) |
359 | { | |
360 | 9 | TreeMap<Integer, File> bfTreeMap = BackupFiles |
361 | .getBackupFilesAsTreeMap(f, s, i); | |
362 | 9 | File[] backupFiles = new File[bfTreeMap.size()]; |
363 | 9 | bfTreeMap.values().toArray(backupFiles); |
364 | 9 | return backupFiles; |
365 | } | |
366 | ||
367 | 1 | private static File[] getBackupFiles() |
368 | { | |
369 | 1 | return getBackupFiles(newFile, suffix, digits); |
370 | } | |
371 | ||
372 | 4 | private static boolean checkBackupFiles(HashMap<Integer, String> indexmap) |
373 | throws IOException | |
374 | { | |
375 | 4 | return checkBackupFiles(indexmap, newFile, suffix, digits); |
376 | } | |
377 | ||
378 | 6 | private static boolean checkBackupFiles(HashMap<Integer, String> indexmap, |
379 | String file, String mysuffix, int mydigits) throws IOException | |
380 | { | |
381 | 6 | TreeMap<Integer, File> map = BackupFiles.getBackupFilesAsTreeMap(file, |
382 | mysuffix, mydigits); | |
383 | 6 | Enumeration<Integer> indexesenum = Collections |
384 | .enumeration(indexmap.keySet()); | |
385 | 22 | while (indexesenum.hasMoreElements()) |
386 | { | |
387 | 17 | int i = indexesenum.nextElement(); |
388 | 17 | String indexfilename = indexmap.get(i); |
389 | 17 | if (!map.containsKey(i)) |
390 | { | |
391 | 0 | return false; |
392 | } | |
393 | 17 | File f = map.get(i); |
394 | 17 | if (!filesContentEqual(newFile, f.getPath())) |
395 | { | |
396 | 0 | return false; |
397 | } | |
398 | 17 | map.remove(i); |
399 | 17 | if (f == null) |
400 | { | |
401 | 0 | return false; |
402 | } | |
403 | 17 | if (!f.getName().equals(indexfilename)) |
404 | { | |
405 | 1 | return false; |
406 | } | |
407 | } | |
408 | // should be nothing left in map | |
409 | 5 | if (map.size() > 0) |
410 | { | |
411 | 0 | return false; |
412 | } | |
413 | ||
414 | 5 | return true; |
415 | } | |
416 | ||
417 | 6 | private static boolean checkBackupFiles(int[] indexes) throws IOException |
418 | { | |
419 | 6 | TreeMap<Integer, File> map = BackupFiles |
420 | .getBackupFilesAsTreeMap(newFile, suffix, digits); | |
421 | 28 | for (int m = 0; m < indexes.length; m++) |
422 | { | |
423 | 25 | int i = indexes[m]; |
424 | 25 | if (!map.containsKey(i)) |
425 | { | |
426 | 3 | return false; |
427 | } | |
428 | 22 | File f = map.get(i); |
429 | 22 | if (!filesContentEqual(newFile, f.getPath())) |
430 | { | |
431 | 0 | return false; |
432 | } | |
433 | 22 | map.remove(i); |
434 | 22 | if (f == null) |
435 | { | |
436 | 0 | return false; |
437 | } | |
438 | // check the filename -- although this uses the same code to forumulate | |
439 | // the filename so not much of a test! | |
440 | 22 | String filename = BackupFilenameParts.getBackupFilename(i, |
441 | newBasename + testExt, suffix, digits); | |
442 | 22 | if (!filename.equals(f.getName())) |
443 | { | |
444 | 0 | System.out.println("Supposed filename '" + filename |
445 | + "' not equal to actual filename '" + f.getName() + "'"); | |
446 | 0 | return false; |
447 | } | |
448 | } | |
449 | // should be nothing left in map | |
450 | 3 | if (map.size() > 0) |
451 | { | |
452 | 3 | return false; |
453 | } | |
454 | ||
455 | 0 | return true; |
456 | } | |
457 | ||
458 | 0 | private static String[] getBackupFilesAsStrings() |
459 | { | |
460 | 0 | File[] files = getBackupFiles(newFile, suffix, digits); |
461 | 0 | String[] filenames = new String[files.length]; |
462 | 0 | for (int i = 0; i < files.length; i++) |
463 | { | |
464 | 0 | filenames[i] = files[i].getPath(); |
465 | } | |
466 | 0 | return filenames; |
467 | } | |
468 | ||
469 | 5 | public static boolean sequencesEqual(SequenceI s1, SequenceI s2) |
470 | { | |
471 | 5 | if (s1 == null && s2 == null) |
472 | { | |
473 | 0 | return true; |
474 | } | |
475 | 5 | else if (s1 == null || s2 == null) |
476 | { | |
477 | 0 | return false; |
478 | } | |
479 | 5 | return (s1.getName().equals(s2.getName()) |
480 | && s1.getDescription().equals(s2.getDescription()) | |
481 | && Arrays.equals(s1.getSequence(), s2.getSequence())); | |
482 | } | |
483 | ||
484 | 39 | public static boolean filesContentEqual(String fileName1, |
485 | String fileName2) throws IOException | |
486 | { | |
487 | 39 | Path file1 = Paths.get(fileName1); |
488 | 39 | Path file2 = Paths.get(fileName2); |
489 | 39 | byte[] bytes1 = Files.readAllBytes(file1); |
490 | 39 | byte[] bytes2 = Files.readAllBytes(file2); |
491 | 39 | return Arrays.equals(bytes1, bytes2); |
492 | } | |
493 | ||
494 | } |