2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
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;
35 import org.testng.Assert;
36 import org.testng.annotations.AfterClass;
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.Test;
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;
47 public class BackupFilesTest
49 @BeforeClass(alwaysRun = true)
50 public void setUpJvOptionPane()
52 JvOptionPane.setInteractiveMode(false);
53 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
56 private static boolean actuallyDeleteTmpFiles = true;
58 private static String testDir = "test/jalview/io";
60 private static String testBasename = "backupfilestest";
62 private static String testExt = ".fa";
64 private static String testFilename = testBasename + testExt;
66 private static String testFile = testDir + File.separatorChar
69 private static String newBasename = testBasename + "Temp";
71 private static String newFilename = newBasename + testExt;
73 private static String newFile = testDir + File.separatorChar
76 private static String sequenceName = "BACKUP_FILES";
78 private static String sequenceDescription = "backupfiles";
80 private static String sequenceData = "AAAARG";
82 private static String suffix = "_BACKUPTEST-%n";
84 private static int digits = 6;
86 private static int rollMax = 2;
88 private AlignFrame af;
90 // read and save with backupfiles disabled
91 @Test(groups = { "Functional" })
92 public void noBackupsEnabledTest() throws Exception
94 // set BACKUPFILES_ENABLED to false (i.e. turn off BackupFiles feature -- no
95 // backup files to be made when saving)
96 setBackupFilesOptions(false, true, true);
98 // init the newFile and backups (i.e. make sure newFile exists on its own
100 initNewFileForTesting();
105 // check no backup files
106 File[] backupFiles = getBackupFiles();
107 Assert.assertTrue(backupFiles.length == 0);
110 // save with no numbers in the backup file names
111 @Test(groups = { "Functional" })
112 public void backupsEnabledSingleFileBackupTest() throws Exception
114 // Enable BackupFiles and set noMax so all backupfiles get kept
115 String mysuffix = "~";
116 BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(mysuffix, 1,
117 false, true, 1, false);
118 setBackupFilesOptions(true, false, true,
119 "test/jalview/io/testProps_singlefilebackup.jvprops", bfpe);
121 // init the newFile and backups (i.e. make sure newFile exists on its own
122 // and has no backups)
123 initNewFileForTesting();
124 HashMap<Integer, String> correctindexmap = new HashMap<>();
125 correctindexmap.put(0, "backupfilestestTemp.fa~");
128 Assert.assertTrue(checkBackupFiles(correctindexmap, newFile, "~", 1));
130 // and a second time -- see JAL-3628
132 Assert.assertTrue(checkBackupFiles(correctindexmap, newFile, "~", 1));
134 cleanupTmpFiles(newFile, "~", 1);
137 // save keeping all backup files
138 @Test(groups = { "Functional" })
139 public void backupsEnabledNoRollMaxTest() throws Exception
141 // Enable BackupFiles and set noMax so all backupfiles get kept
142 setBackupFilesOptions(true, false, true);
144 // init the newFile and backups (i.e. make sure newFile exists on its own
145 // and has no backups)
146 initNewFileForTesting();
148 // now save a few times again. No rollMax so should have more than two
151 for (int i = 0; i < numSaves; i++)
156 // check 10 backup files
157 HashMap<Integer, String> correctindexmap = new HashMap<>();
158 correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-000001");
159 correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002");
160 correctindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-000003");
161 correctindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-000004");
162 correctindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-000005");
163 correctindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-000006");
164 correctindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-000007");
165 correctindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-000008");
166 correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009");
167 correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010");
168 HashMap<Integer, String> wrongindexmap = new HashMap<>();
169 wrongindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-1");
170 wrongindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002");
171 wrongindexmap.put(3, "backupfilestestTemp.fa_BACKUPTEST-000003");
172 wrongindexmap.put(4, "backupfilestestTemp.fa_BACKUPTEST-000004");
173 wrongindexmap.put(5, "backupfilestestTemp.fa_BACKUPTEST-000005");
174 wrongindexmap.put(6, "backupfilestestTemp.fa_BACKUPTEST-000006");
175 wrongindexmap.put(7, "backupfilestestTemp.fa_BACKUPTEST-000007");
176 wrongindexmap.put(8, "backupfilestestTemp.fa_BACKUPTEST-000008");
177 wrongindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009");
178 wrongindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010");
179 int[] indexes2 = { 3, 4, 5, 6, 7, 8, 9, 10 };
180 int[] indexes3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
181 Assert.assertTrue(checkBackupFiles(correctindexmap));
182 Assert.assertFalse(checkBackupFiles(wrongindexmap));
183 Assert.assertFalse(checkBackupFiles(indexes2));
184 Assert.assertFalse(checkBackupFiles(indexes3));
187 // save keeping only the last rollMax (2) backup files
188 @Test(groups = { "Functional" })
189 public void backupsEnabledRollMaxTest() throws Exception
191 // Enable BackupFiles and set noMax so all backupfiles get kept
192 setBackupFilesOptions(true, false, false);
194 // init the newFile and backups (i.e. make sure newFile exists on its own
195 // and has no backups)
196 initNewFileForTesting();
198 // now save a few times again. No rollMax so should have more than two
201 for (int i = 0; i < numSaves; i++)
206 // check there are "rollMax" backup files and they are all saved correctly
207 // check 10 backup files
208 HashMap<Integer, String> correctindexmap = new HashMap<>();
209 correctindexmap.put(9, "backupfilestestTemp.fa_BACKUPTEST-000009");
210 correctindexmap.put(10, "backupfilestestTemp.fa_BACKUPTEST-000010");
211 int[] indexes2 = { 10 };
212 int[] indexes3 = { 8, 9, 10 };
213 Assert.assertTrue(checkBackupFiles(correctindexmap));
214 Assert.assertFalse(checkBackupFiles(indexes2));
215 Assert.assertFalse(checkBackupFiles(indexes3));
218 // save keeping only the last rollMax (2) backup files
219 @Test(groups = { "Functional" })
220 public void backupsEnabledReverseRollMaxTest() throws Exception
222 // Enable BackupFiles and set noMax so all backupfiles get kept
223 setBackupFilesOptions(true, true, false);
225 // init the newFile and backups (i.e. make sure newFile exists on its own
226 // and has no backups)
227 initNewFileForTesting();
229 // now save a few times again. No rollMax so should have more than two
232 for (int i = 0; i < numSaves; i++)
237 // check there are "rollMax" backup files and they are all saved correctly
238 // check 10 backup files
239 HashMap<Integer, String> correctindexmap = new HashMap<>();
240 correctindexmap.put(1, "backupfilestestTemp.fa_BACKUPTEST-000001");
241 correctindexmap.put(2, "backupfilestestTemp.fa_BACKUPTEST-000002");
242 int[] indexes2 = { 1 };
243 int[] indexes3 = { 1, 2, 3 };
244 Assert.assertTrue(checkBackupFiles(correctindexmap));
245 Assert.assertFalse(checkBackupFiles(indexes2));
246 Assert.assertFalse(checkBackupFiles(indexes3));
249 private void setBackupFilesOptions()
251 setBackupFilesOptions(true, false, false);
254 private void setBackupFilesOptions(boolean enabled, boolean reverse,
257 BackupFilesPresetEntry bfpe = new BackupFilesPresetEntry(suffix, digits,
258 reverse, noMax, rollMax, false);
259 setBackupFilesOptions(enabled, reverse, noMax,
260 "test/jalview/io/testProps.jvprops", bfpe);
263 private void setBackupFilesOptions(boolean enabled, boolean reverse,
264 boolean noMax, String propsFile, BackupFilesPresetEntry bfpe)
266 Cache.loadProperties(propsFile);
268 Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
269 Boolean.toString(enabled));
270 Cache.applicationProperties.setProperty(
271 BackupFilesPresetEntry.SAVEDCONFIG, bfpe.toString());
273 Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
274 Boolean.toString(enabled));
275 Cache.applicationProperties.setProperty(BackupFiles.SUFFIX, suffix);
276 Cache.applicationProperties.setProperty(BackupFiles.SUFFIX_DIGITS,
277 Integer.toString(digits));
278 Cache.applicationProperties.setProperty(BackupFiles.REVERSE_ORDER,
279 Boolean.toString(reverse));
280 Cache.applicationProperties.setProperty(BackupFiles.NO_MAX,
281 Boolean.toString(noMax));
282 Cache.applicationProperties.setProperty(BackupFiles.ROLL_MAX,
283 Integer.toString(rollMax));
284 Cache.applicationProperties.setProperty(BackupFiles.CONFIRM_DELETE_OLD,
293 af.saveAlignment(newFile, jalview.io.FileFormat.Fasta);
297 // this runs cleanTmpFiles and then writes the newFile once as a starting
298 // point for all tests
299 private void initNewFileForTesting() throws Exception
303 AppletFormatAdapter afa = new AppletFormatAdapter();
304 AlignmentI al = afa.readFile(testFile, DataSourceType.FILE,
305 jalview.io.FileFormat.Fasta);
306 List<SequenceI> l = al.getSequences();
308 // check this is right
311 throw new Exception("single sequence from '" + testFile
312 + "' not read in correctly (should be a single short sequence). List<SequenceI> size is wrong.");
314 SequenceI s = l.get(0);
315 Sequence ref = new Sequence(sequenceName, sequenceData);
316 ref.setDescription(sequenceDescription);
317 if (!sequencesEqual(s, ref))
319 throw new Exception("single sequence from '" + testFile
320 + "' not read in correctly (should be a single short sequence). SequenceI name, description or data is wrong.");
322 // save alignment file to new filename -- this doesn't test backups disabled
323 // yet as this file shouldn't already exist
324 af = new AlignFrame(al, 0, 0);
325 af.saveAlignment(newFile, jalview.io.FileFormat.Fasta);
328 // this deletes the newFile (if it exists) and any saved backup file for it
329 @AfterClass(alwaysRun = true)
330 private void cleanupTmpFiles()
332 cleanupTmpFiles(newFile, suffix, digits);
335 protected static void cleanupTmpFiles(String file, String mysuffix,
338 File newfile = new File(file);
339 if (newfile.exists())
343 File[] tmpFiles = getBackupFiles(file, mysuffix, mydigits);
344 for (int i = 0; i < tmpFiles.length; i++)
346 if (actuallyDeleteTmpFiles)
348 tmpFiles[i].delete();
352 System.out.println("Pretending to delete " + tmpFiles[i].getPath());
357 private static File[] getBackupFiles(String f, String s, int i)
359 TreeMap<Integer, File> bfTreeMap = BackupFiles
360 .getBackupFilesAsTreeMap(f, s, i);
361 File[] backupFiles = new File[bfTreeMap.size()];
362 bfTreeMap.values().toArray(backupFiles);
366 private static File[] getBackupFiles()
368 return getBackupFiles(newFile, suffix, digits);
371 private static boolean checkBackupFiles(HashMap<Integer, String> indexmap)
374 return checkBackupFiles(indexmap, newFile, suffix, digits);
377 private static boolean checkBackupFiles(HashMap<Integer, String> indexmap,
378 String file, String mysuffix, int mydigits) throws IOException
380 TreeMap<Integer, File> map = BackupFiles.getBackupFilesAsTreeMap(file,
382 Enumeration<Integer> indexesenum = Collections
383 .enumeration(indexmap.keySet());
384 while (indexesenum.hasMoreElements())
386 int i = indexesenum.nextElement();
387 String indexfilename = indexmap.get(i);
388 if (!map.containsKey(i))
393 if (!filesContentEqual(newFile, f.getPath()))
402 if (!f.getName().equals(indexfilename))
407 // should be nothing left in map
416 private static boolean checkBackupFiles(int[] indexes) throws IOException
418 TreeMap<Integer, File> map = BackupFiles
419 .getBackupFilesAsTreeMap(newFile, suffix, digits);
420 for (int m = 0; m < indexes.length; m++)
423 if (!map.containsKey(i))
428 if (!filesContentEqual(newFile, f.getPath()))
437 // check the filename -- although this uses the same code to forumulate
438 // the filename so not much of a test!
439 String filename = BackupFilenameParts.getBackupFilename(i,
440 newBasename + testExt, suffix, digits);
441 if (!filename.equals(f.getName()))
443 System.out.println("Supposed filename '" + filename
444 + "' not equal to actual filename '" + f.getName() + "'");
448 // should be nothing left in map
457 private static String[] getBackupFilesAsStrings()
459 File[] files = getBackupFiles(newFile, suffix, digits);
460 String[] filenames = new String[files.length];
461 for (int i = 0; i < files.length; i++)
463 filenames[i] = files[i].getPath();
468 public static boolean sequencesEqual(SequenceI s1, SequenceI s2)
470 if (s1 == null && s2 == null)
474 else if (s1 == null || s2 == null)
478 return (s1.getName().equals(s2.getName())
479 && s1.getDescription().equals(s2.getDescription())
480 && Arrays.equals(s1.getSequence(), s2.getSequence()));
483 public static boolean filesContentEqual(String fileName1,
484 String fileName2) throws IOException
486 Path file1 = Paths.get(fileName1);
487 Path file2 = Paths.get(fileName2);
488 byte[] bytes1 = Files.readAllBytes(file1);
489 byte[] bytes2 = Files.readAllBytes(file2);
490 return Arrays.equals(bytes1, bytes2);