JAL-3141 Tests now available and working, bringing to light a problem with the classI...
[jalview.git] / test / jalview / io / BackupFilesTest.java
1 package jalview.io;
2
3 import jalview.bin.Cache;
4 import jalview.datamodel.AlignmentI;
5 import jalview.datamodel.Sequence;
6 import jalview.datamodel.SequenceI;
7 import jalview.gui.AlignFrame;
8 import jalview.gui.JvOptionPane;
9
10 import java.io.File;
11 import java.io.IOException;
12 import java.nio.file.Files;
13 import java.nio.file.Path;
14 import java.nio.file.Paths;
15 import java.util.Arrays;
16 import java.util.List;
17 import java.util.TreeMap;
18
19 import org.junit.Assert;
20 import org.testng.annotations.AfterClass;
21 import org.testng.annotations.BeforeClass;
22 import org.testng.annotations.Test;
23
24 public class BackupFilesTest
25 {
26   @BeforeClass(alwaysRun = true)
27   public void setUpJvOptionPane()
28   {
29     JvOptionPane.setInteractiveMode(false);
30     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
31   }
32
33   private static boolean actuallyDeleteTmpFiles = true;
34   private static String testDir = "examples";
35
36   private static String testFilename = "backupfilestest.fa";
37
38
39   private static String testFile = testDir + File.separatorChar
40           + testFilename;
41
42   private static String newFilename = "backupfilestestTemp.fa";
43
44   private static String newFile = testDir + File.separatorChar
45           + newFilename;
46
47   private static String sequenceName = "BACKUP_FILES";
48
49   private static String sequenceDescription = "backupfiles";
50
51   private static String sequenceData = "AAAARG";
52
53   private static String suffix = "_BACKUPTEST-%n";
54
55   private static int digits = 8;
56
57   private static int rollMax = 2;
58
59   private AlignFrame af;
60
61   // read and save with backupfiles disabled
62   @Test(groups = { "Functional" })
63   public void noBackupsEnabledTest() throws Exception
64   {
65     // set BACKUPFILES_ENABLED to false (i.e. turn off BackupFiles feature -- no
66     // backup files to be made when saving)
67     setBackupFilesOptions(false, true, true);
68
69     // init the newFile and backups (i.e. make sure newFile exists on its own
70     // and has no backups)
71     initNewFileForTesting();
72
73     // now save again
74     save();
75
76     // check no backup files
77     File[] backupFiles = getBackupFiles();
78     Assert.assertTrue(backupFiles.length == 0);
79   }
80
81   // save keeping all backup files
82   @Test(groups = { "Functional" })
83   public void backupsEnabledNoRollMaxTest() throws Exception
84   {
85     // Enable BackupFiles and set noMax so all backupfiles get kept
86     setBackupFilesOptions(true, false, true);
87
88     // init the newFile and backups (i.e. make sure newFile exists on its own
89     // and has no backups)
90     initNewFileForTesting();
91
92     // now save a few times again. No rollMax so should have more than two
93     // backup files
94     int numSaves = 10;
95     for (int i = 0; i < numSaves; i++)
96     {
97       save();
98     }
99
100     // check 10 backup files
101     int[] indexes1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
102     int[] indexes2 = { 3, 4, 5, 6, 7, 8, 9, 10 };
103     int[] indexes3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
104     Assert.assertTrue(checkBackupFiles(indexes1));
105     Assert.assertFalse(checkBackupFiles(indexes2));
106     Assert.assertFalse(checkBackupFiles(indexes3));
107   }
108
109   // save keeping only the last rollMax (2) backup files
110   @Test(groups = { "Functional" })
111   public void backupsEnabledRollMaxTest() throws Exception
112   {
113     // Enable BackupFiles and set noMax so all backupfiles get kept
114     setBackupFilesOptions(true, false, false);
115
116     // init the newFile and backups (i.e. make sure newFile exists on its own
117     // and has no backups)
118     initNewFileForTesting();
119
120     // now save a few times again. No rollMax so should have more than two
121     // backup files
122     int numSaves = 10;
123     for (int i = 0; i < numSaves; i++)
124     {
125       save();
126     }
127
128     // check there are "rollMax" backup files and they are all saved correctly
129     // check 10 backup files
130     int[] indexes1 = { 9, 10 };
131     int[] indexes2 = { 10 };
132     int[] indexes3 = { 8, 9, 10 };
133     Assert.assertTrue(checkBackupFiles(indexes1));
134     Assert.assertFalse(checkBackupFiles(indexes2));
135     Assert.assertFalse(checkBackupFiles(indexes3));
136   }
137
138   // save keeping only the last rollMax (2) backup files
139   @Test(groups = { "Functional" })
140   public void backupsEnabledReverseRollMaxTest() throws Exception
141   {
142     // Enable BackupFiles and set noMax so all backupfiles get kept
143     setBackupFilesOptions(true, true, false);
144
145     // init the newFile and backups (i.e. make sure newFile exists on its own
146     // and has no backups)
147     initNewFileForTesting();
148
149     // now save a few times again. No rollMax so should have more than two
150     // backup files
151     int numSaves = 10;
152     for (int i = 0; i < numSaves; i++)
153     {
154       save();
155     }
156
157     // check there are "rollMax" backup files and they are all saved correctly
158     // check 10 backup files
159     int[] indexes1 = { 1, 2 };
160     int[] indexes2 = { 1 };
161     int[] indexes3 = { 1, 2, 3 };
162     Assert.assertTrue(checkBackupFiles(indexes1));
163     Assert.assertFalse(checkBackupFiles(indexes2));
164     Assert.assertFalse(checkBackupFiles(indexes3));
165   }
166
167   private void setBackupFilesOptions()
168   {
169     setBackupFilesOptions(true, false, false);
170   }
171
172   private void setBackupFilesOptions(boolean enabled, boolean reverse,
173           boolean noMax)
174   {
175     Cache.loadProperties("test/jalview/io/testProps.jvprops");
176
177     Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
178             Boolean.toString(enabled));
179     Cache.applicationProperties.setProperty(BackupFiles.SUFFIX, suffix);
180     Cache.applicationProperties.setProperty(BackupFiles.SUFFIX_DIGITS,
181             Integer.toString(digits));
182     Cache.applicationProperties.setProperty(BackupFiles.REVERSE_ORDER,
183             Boolean.toString(reverse));
184     Cache.applicationProperties.setProperty(BackupFiles.NO_MAX,
185             Boolean.toString(noMax));
186     Cache.applicationProperties.setProperty(BackupFiles.ROLL_MAX,
187             Integer.toString(rollMax));
188     Cache.applicationProperties.setProperty(BackupFiles.CONFIRM_DELETE_OLD,
189             "false");
190   }
191
192   private void save()
193   {
194     if (af != null)
195     {
196     af.saveAlignment(newFile, jalview.io.FileFormat.Fasta);
197     }
198   }
199
200   // this runs cleanTmpFiles and then writes the newFile once as a starting
201   // point for all tests
202   private void initNewFileForTesting() throws Exception
203   {
204     cleanupTmpFiles();
205
206     AppletFormatAdapter afa = new AppletFormatAdapter();
207     AlignmentI al = afa.readFile(testFile, DataSourceType.FILE,
208             jalview.io.FileFormat.Fasta);
209     List<SequenceI> l = al.getSequences();
210
211     // check this is right
212     if (l.size() != 1)
213     {
214       throw new Exception("single sequence from '" + testFile
215               + "' not read in correctly (should be a single short sequence). List<SequenceI> size is wrong.");
216     }
217     SequenceI s = l.get(0);
218     Sequence ref = new Sequence(sequenceName, sequenceData);
219     ref.setDescription(sequenceDescription);
220     if (!sequencesEqual(s, ref))
221     {
222       throw new Exception("single sequence from '" + testFile
223               + "' not read in correctly (should be a single short sequence). SequenceI name, description or data is wrong.");
224     }
225     // save alignment file to new filename -- this doesn't test backups disabled
226     // yet as this file shouldn't already exist
227     af = new AlignFrame(al, 0, 0);
228     af.saveAlignment(newFile, jalview.io.FileFormat.Fasta);
229   }
230
231   // this deletes the newFile (if it exists) and any saved backup file for it
232   @AfterClass(alwaysRun = true)
233   private void cleanupTmpFiles()
234   {
235     File newfile = new File(newFile);
236     if (newfile.exists())
237     {
238       newfile.delete();
239     }
240     File[] tmpFiles = BackupFiles.lsBackupFiles(newFile, suffix, digits);
241     for (int i = 0; i < tmpFiles.length; i++)
242     {
243       if (actuallyDeleteTmpFiles)
244       {
245         tmpFiles[i].delete();
246       }
247       else
248       {
249         System.out.println("Pretending to delete " + tmpFiles[i].getPath());
250       }
251     }
252   }
253
254   private static File[] getBackupFiles()
255   {
256     return BackupFiles.lsBackupFiles(newFile, suffix, digits);
257   }
258
259   private static boolean checkBackupFiles(int[] indexes) throws IOException
260   {
261     TreeMap<Integer, File> map = BackupFiles.lsBackupFilesAsTreeMap(newFile,
262             suffix, digits);
263     for (int m = 0; m < indexes.length; m++)
264     {
265       int i = indexes[m];
266       if (!map.containsKey(i))
267       {
268         return false;
269       }
270       File f = map.get(i);
271       if (!filesContentEqual(newFile, f.getPath()))
272       {
273         return false;
274       }
275       map.remove(i);
276       if (f == null)
277       {
278         return false;
279       }
280     }
281     // should be nothing left in map
282     if (map.size() > 0)
283     {
284       return false;
285     }
286
287     return true;
288   }
289
290   private static String[] getBackupFilesAsStrings()
291   {
292     File[] files = BackupFiles.lsBackupFiles(newFile, suffix, digits);
293     String[] filenames = new String[files.length];
294     for (int i = 0; i < files.length; i++)
295     {
296       filenames[i] = files[i].getPath();
297     }
298     return filenames;
299   }
300
301   public static boolean sequencesEqual(SequenceI s1, SequenceI s2) {
302     if (s1 == null && s2 == null) {
303       return true;
304     } else if (s1 == null || s2 == null) {
305       return false;
306     }
307     return (s1.getName().equals(s2.getName())
308             && s1.getDescription().equals(s2.getDescription())
309             && Arrays.equals(s1.getSequence(), s2.getSequence()));
310   }
311
312   public static boolean filesContentEqual(String fileName1,
313           String fileName2) throws IOException
314   {
315     Path file1 = Paths.get(fileName1);
316     Path file2 = Paths.get(fileName2);
317     byte[] bytes1 = Files.readAllBytes(file1);
318     byte[] bytes2 = Files.readAllBytes(file2);
319     return Arrays.equals(bytes1, bytes2);
320   }
321
322 }