JAL-3141 Tests now available and working, bringing to light a problem with the classI...
authorBen Soares <bsoares@dundee.ac.uk>
Fri, 2 Nov 2018 16:37:33 +0000 (16:37 +0000)
committerBen Soares <bsoares@dundee.ac.uk>
Fri, 2 Nov 2018 16:37:33 +0000 (16:37 +0000)
examples/backupfilestest.fa [new file with mode: 0644]
resources/lang/Messages_es.properties
src/jalview/gui/Preferences.java
src/jalview/io/BackupFilenameFilter.java
src/jalview/io/BackupFiles.java
test/jalview/io/AnnotationFileIOTest.java
test/jalview/io/BackupFilesTest.java [new file with mode: 0644]
test/jalview/io/testProps.jvprops

diff --git a/examples/backupfilestest.fa b/examples/backupfilestest.fa
new file mode 100644 (file)
index 0000000..c536a79
--- /dev/null
@@ -0,0 +1,2 @@
+>BACKUP_FILES/1-6 backupfiles
+AAAARG
index f3be98c..bd7c7b3 100644 (file)
@@ -1369,8 +1369,22 @@ label.backupfiles_confirm_delete = Confirmar borrar
 label.backupfiles_confirm_delete_old_files = ¿Borrar los siguientes archivos?
 label.backupfiles_confirm_save_file = Confirmar guardar archivo
 label.backupfiles_confirm_save_file_backupfiles_roll_wrong = Posiblemente algo está mal con los archivos de copia de seguridad. ¿Guardar el nuevo archivo?
-label.backups = Backups
-label.backup_files = Backup Files
-label.enable_backupfiles = Enable use of backup files
-label.suffix_format = Suffix format
-
+label.backups = Copias
+label.backup_files = Copias de seguridad
+label.enable_backupfiles = Habilitar copias de seguridad
+label.suffix_format = Formato de sufijo
+label.suffix_template = Plantilla de sufijo (usa %n para representar el índice)
+label.suffix_template_tooltip = Esto será reemplazado por el número de índice. El sufijo aparecerá antes de la extensión.
+label.index_digits = Número de dígitos a utilizar para el índice.
+default.suffix_index_digits_min = 1
+default.suffix_index_digits_max = 6
+label.example_filenames = Ejemplos de nombres de archivos
+label.suffix_example_filenames = Algunos nombres de archivos de ejemplo usando estas configuraciones:
+label.increment_index = El archivo más nuevo tiene el índice más grande
+label.reverse_roll = El archivo más nuevo tiene índice 1
+label.keep_files = Manten los archivos
+label.keep_all_backup_files = Mantener todos los archivos de copia de seguridad
+label.keep_only_this_number_of_backup_files = Mantenga solo este número de archivos de copia de seguridad más recientes
+label.old_backup_files = Viejos archivos de copia de seguridad:
+label.confirm_delete = Confirmar eliminaciones
+label.auto_delete = Eliminar automáticamente
index 99e1cc8..e1c6089 100755 (executable)
@@ -554,8 +554,10 @@ public class Preferences extends GPreferences
      */
     enableBackupFiles
             .setSelected(Cache.getDefault(BackupFiles.ENABLED, true));
-    suffixTemplate.setText(Cache.getDefault(BackupFiles.SUFFIX, "-v"+BackupFiles.getNumPlaceHolder()));
-    suffixDigitsSpinner.setValue(Cache.getDefault(BackupFiles.SUFFIX_DIGITS, 3));
+    suffixTemplate.setText(Cache.getDefault(BackupFiles.SUFFIX,
+            "-v" + BackupFiles.getNumPlaceHolder()));
+    suffixDigitsSpinner
+            .setValue(Cache.getDefault(BackupFiles.SUFFIX_DIGITS, 3));
     suffixReverse.setSelected(
             Cache.getDefault(BackupFiles.REVERSE_ORDER, false));
     backupfilesKeepAll
index bb2af1c..1fed65c 100644 (file)
@@ -106,7 +106,8 @@ class BackupFilenameParts
     if (numcharstart > -1)
     {
       templateStart = template.substring(0, numcharstart);
-      templateEnd = template.substring(numcharstart + BackupFiles.NUM_PLACEHOLDER.length());
+      templateEnd = template.substring(
+              numcharstart + BackupFiles.NUM_PLACEHOLDER.length());
     }
     
     int startLength = base.length() + templateStart.length();
index 784d8a1..0b6b090 100644 (file)
@@ -58,8 +58,6 @@ public class BackupFiles
   // deleting old backup/version files
   private static boolean confirmDelete;
 
-  private static boolean classInit = false;
-
   // defaultSuffix - default template to use to append to basename of file
   private String suffix;
 
@@ -135,12 +133,8 @@ public class BackupFiles
 
   public static void classInit()
   {
-    if (!classInit)
-    {
-      setEnabled(Cache.getDefault(ENABLED, true));
-      setConfirmDelete(Cache.getDefault(CONFIRM_DELETE_OLD, true));
-      classInit = true;
-    }
+    setEnabled(Cache.getDefault(ENABLED, true));
+    setConfirmDelete(Cache.getDefault(CONFIRM_DELETE_OLD, true));
   }
 
   public static void setEnabled(boolean flag)
@@ -476,5 +470,68 @@ public class BackupFiles
     return rename;
   }
 
+  public static TreeMap<Integer, File> lsBackupFilesAsTreeMap(
+          String fileName,
+          String suffix, int digits)
+  {
+    File[] backupFiles = null;
+
+    File file = new File(fileName);
+
+    String dir = "";
+    File dirFile;
+    try
+    {
+      dirFile = file.getParentFile();
+      dir = dirFile.getCanonicalPath();
+    } catch (Exception e)
+    {
+      System.out.println(
+              "Could not get canonical path for file '" + file + "'");
+      return new TreeMap<>();
+    }
+
+    String filename = file.getName();
+    String basename = filename;
+    String extension = "";
+    int dotcharpos = filename.lastIndexOf('.');
+    // don't split of filenames with the last '.' at the very beginning or
+    // very end of the filename
+    if ((dotcharpos > 0) && (dotcharpos < filename.length() - 1))
+    {
+      basename = filename.substring(0, dotcharpos);
+      extension = filename.substring(dotcharpos); // NOTE this includes the '.'
+    }
+    
+    // find existing backup files
+    BackupFilenameFilter bff = new BackupFilenameFilter(basename, suffix, digits, extension);
+    backupFiles = dirFile.listFiles(bff); // is clone needed?
+    
+    // sort the backup files (based on integer found in the suffix) using a
+    // precomputed Hashmap for speed
+    HashMap<Integer, File> bfHashMap = new HashMap<>();
+    for (int i = 0; i < backupFiles.length; i++)
+    {
+      File f = backupFiles[i];
+      BackupFilenameParts bfp = new BackupFilenameParts(f, basename, suffix,
+              digits, extension);
+      bfHashMap.put(bfp.indexNum(), f);
+    }
+    TreeMap<Integer, File> bfTreeMap = new TreeMap<>();
+    bfTreeMap.putAll(bfHashMap);
+
+    return bfTreeMap;
+  }
+
+  public static File[] lsBackupFiles(String fileName, String suffix,
+          int digits)
+  {
+    TreeMap<Integer, File> bfTreeMap = lsBackupFilesAsTreeMap(fileName,
+            suffix, digits);
+    File[] backupFiles = new File[bfTreeMap.size()];
+    bfTreeMap.values().toArray(backupFiles);
+    return backupFiles;
+  }
+
 }
 
index 6a00cde..05ce22d 100644 (file)
@@ -70,7 +70,7 @@ public class AnnotationFileIOTest
     }
   }
 
-  AlignmentI readAlignmentFile(File f)
+  protected AlignmentI readAlignmentFile(File f)
   {
     System.out.println("Reading file: " + f);
     String ff = f.getPath();
diff --git a/test/jalview/io/BackupFilesTest.java b/test/jalview/io/BackupFilesTest.java
new file mode 100644 (file)
index 0000000..c1a8d4c
--- /dev/null
@@ -0,0 +1,322 @@
+package jalview.io;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.JvOptionPane;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.TreeMap;
+
+import org.junit.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class BackupFilesTest
+{
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
+  private static boolean actuallyDeleteTmpFiles = true;
+  private static String testDir = "examples";
+
+  private static String testFilename = "backupfilestest.fa";
+
+
+  private static String testFile = testDir + File.separatorChar
+          + testFilename;
+
+  private static String newFilename = "backupfilestestTemp.fa";
+
+  private static String newFile = testDir + File.separatorChar
+          + newFilename;
+
+  private static String sequenceName = "BACKUP_FILES";
+
+  private static String sequenceDescription = "backupfiles";
+
+  private static String sequenceData = "AAAARG";
+
+  private static String suffix = "_BACKUPTEST-%n";
+
+  private static int digits = 8;
+
+  private static int rollMax = 2;
+
+  private AlignFrame af;
+
+  // read and save with backupfiles disabled
+  @Test(groups = { "Functional" })
+  public void noBackupsEnabledTest() throws Exception
+  {
+    // set BACKUPFILES_ENABLED to false (i.e. turn off BackupFiles feature -- no
+    // backup files to be made when saving)
+    setBackupFilesOptions(false, true, true);
+
+    // init the newFile and backups (i.e. make sure newFile exists on its own
+    // and has no backups)
+    initNewFileForTesting();
+
+    // now save again
+    save();
+
+    // check no backup files
+    File[] backupFiles = getBackupFiles();
+    Assert.assertTrue(backupFiles.length == 0);
+  }
+
+  // save keeping all backup files
+  @Test(groups = { "Functional" })
+  public void backupsEnabledNoRollMaxTest() throws Exception
+  {
+    // Enable BackupFiles and set noMax so all backupfiles get kept
+    setBackupFilesOptions(true, false, true);
+
+    // init the newFile and backups (i.e. make sure newFile exists on its own
+    // and has no backups)
+    initNewFileForTesting();
+
+    // now save a few times again. No rollMax so should have more than two
+    // backup files
+    int numSaves = 10;
+    for (int i = 0; i < numSaves; i++)
+    {
+      save();
+    }
+
+    // check 10 backup files
+    int[] indexes1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    int[] indexes2 = { 3, 4, 5, 6, 7, 8, 9, 10 };
+    int[] indexes3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+    Assert.assertTrue(checkBackupFiles(indexes1));
+    Assert.assertFalse(checkBackupFiles(indexes2));
+    Assert.assertFalse(checkBackupFiles(indexes3));
+  }
+
+  // save keeping only the last rollMax (2) backup files
+  @Test(groups = { "Functional" })
+  public void backupsEnabledRollMaxTest() throws Exception
+  {
+    // Enable BackupFiles and set noMax so all backupfiles get kept
+    setBackupFilesOptions(true, false, false);
+
+    // init the newFile and backups (i.e. make sure newFile exists on its own
+    // and has no backups)
+    initNewFileForTesting();
+
+    // now save a few times again. No rollMax so should have more than two
+    // backup files
+    int numSaves = 10;
+    for (int i = 0; i < numSaves; i++)
+    {
+      save();
+    }
+
+    // check there are "rollMax" backup files and they are all saved correctly
+    // check 10 backup files
+    int[] indexes1 = { 9, 10 };
+    int[] indexes2 = { 10 };
+    int[] indexes3 = { 8, 9, 10 };
+    Assert.assertTrue(checkBackupFiles(indexes1));
+    Assert.assertFalse(checkBackupFiles(indexes2));
+    Assert.assertFalse(checkBackupFiles(indexes3));
+  }
+
+  // save keeping only the last rollMax (2) backup files
+  @Test(groups = { "Functional" })
+  public void backupsEnabledReverseRollMaxTest() throws Exception
+  {
+    // Enable BackupFiles and set noMax so all backupfiles get kept
+    setBackupFilesOptions(true, true, false);
+
+    // init the newFile and backups (i.e. make sure newFile exists on its own
+    // and has no backups)
+    initNewFileForTesting();
+
+    // now save a few times again. No rollMax so should have more than two
+    // backup files
+    int numSaves = 10;
+    for (int i = 0; i < numSaves; i++)
+    {
+      save();
+    }
+
+    // check there are "rollMax" backup files and they are all saved correctly
+    // check 10 backup files
+    int[] indexes1 = { 1, 2 };
+    int[] indexes2 = { 1 };
+    int[] indexes3 = { 1, 2, 3 };
+    Assert.assertTrue(checkBackupFiles(indexes1));
+    Assert.assertFalse(checkBackupFiles(indexes2));
+    Assert.assertFalse(checkBackupFiles(indexes3));
+  }
+
+  private void setBackupFilesOptions()
+  {
+    setBackupFilesOptions(true, false, false);
+  }
+
+  private void setBackupFilesOptions(boolean enabled, boolean reverse,
+          boolean noMax)
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+
+    Cache.applicationProperties.setProperty(BackupFiles.ENABLED,
+            Boolean.toString(enabled));
+    Cache.applicationProperties.setProperty(BackupFiles.SUFFIX, suffix);
+    Cache.applicationProperties.setProperty(BackupFiles.SUFFIX_DIGITS,
+            Integer.toString(digits));
+    Cache.applicationProperties.setProperty(BackupFiles.REVERSE_ORDER,
+            Boolean.toString(reverse));
+    Cache.applicationProperties.setProperty(BackupFiles.NO_MAX,
+            Boolean.toString(noMax));
+    Cache.applicationProperties.setProperty(BackupFiles.ROLL_MAX,
+            Integer.toString(rollMax));
+    Cache.applicationProperties.setProperty(BackupFiles.CONFIRM_DELETE_OLD,
+            "false");
+  }
+
+  private void save()
+  {
+    if (af != null)
+    {
+    af.saveAlignment(newFile, jalview.io.FileFormat.Fasta);
+    }
+  }
+
+  // this runs cleanTmpFiles and then writes the newFile once as a starting
+  // point for all tests
+  private void initNewFileForTesting() throws Exception
+  {
+    cleanupTmpFiles();
+
+    AppletFormatAdapter afa = new AppletFormatAdapter();
+    AlignmentI al = afa.readFile(testFile, DataSourceType.FILE,
+            jalview.io.FileFormat.Fasta);
+    List<SequenceI> l = al.getSequences();
+
+    // check this is right
+    if (l.size() != 1)
+    {
+      throw new Exception("single sequence from '" + testFile
+              + "' not read in correctly (should be a single short sequence). List<SequenceI> size is wrong.");
+    }
+    SequenceI s = l.get(0);
+    Sequence ref = new Sequence(sequenceName, sequenceData);
+    ref.setDescription(sequenceDescription);
+    if (!sequencesEqual(s, ref))
+    {
+      throw new Exception("single sequence from '" + testFile
+              + "' not read in correctly (should be a single short sequence). SequenceI name, description or data is wrong.");
+    }
+    // save alignment file to new filename -- this doesn't test backups disabled
+    // yet as this file shouldn't already exist
+    af = new AlignFrame(al, 0, 0);
+    af.saveAlignment(newFile, jalview.io.FileFormat.Fasta);
+  }
+
+  // this deletes the newFile (if it exists) and any saved backup file for it
+  @AfterClass(alwaysRun = true)
+  private void cleanupTmpFiles()
+  {
+    File newfile = new File(newFile);
+    if (newfile.exists())
+    {
+      newfile.delete();
+    }
+    File[] tmpFiles = BackupFiles.lsBackupFiles(newFile, suffix, digits);
+    for (int i = 0; i < tmpFiles.length; i++)
+    {
+      if (actuallyDeleteTmpFiles)
+      {
+        tmpFiles[i].delete();
+      }
+      else
+      {
+        System.out.println("Pretending to delete " + tmpFiles[i].getPath());
+      }
+    }
+  }
+
+  private static File[] getBackupFiles()
+  {
+    return BackupFiles.lsBackupFiles(newFile, suffix, digits);
+  }
+
+  private static boolean checkBackupFiles(int[] indexes) throws IOException
+  {
+    TreeMap<Integer, File> map = BackupFiles.lsBackupFilesAsTreeMap(newFile,
+            suffix, digits);
+    for (int m = 0; m < indexes.length; m++)
+    {
+      int i = indexes[m];
+      if (!map.containsKey(i))
+      {
+        return false;
+      }
+      File f = map.get(i);
+      if (!filesContentEqual(newFile, f.getPath()))
+      {
+        return false;
+      }
+      map.remove(i);
+      if (f == null)
+      {
+        return false;
+      }
+    }
+    // should be nothing left in map
+    if (map.size() > 0)
+    {
+      return false;
+    }
+
+    return true;
+  }
+
+  private static String[] getBackupFilesAsStrings()
+  {
+    File[] files = BackupFiles.lsBackupFiles(newFile, suffix, digits);
+    String[] filenames = new String[files.length];
+    for (int i = 0; i < files.length; i++)
+    {
+      filenames[i] = files[i].getPath();
+    }
+    return filenames;
+  }
+
+  public static boolean sequencesEqual(SequenceI s1, SequenceI s2) {
+    if (s1 == null && s2 == null) {
+      return true;
+    } else if (s1 == null || s2 == null) {
+      return false;
+    }
+    return (s1.getName().equals(s2.getName())
+            && s1.getDescription().equals(s2.getDescription())
+            && Arrays.equals(s1.getSequence(), s2.getSequence()));
+  }
+
+  public static boolean filesContentEqual(String fileName1,
+          String fileName2) throws IOException
+  {
+    Path file1 = Paths.get(fileName1);
+    Path file2 = Paths.get(fileName2);
+    byte[] bytes1 = Files.readAllBytes(file1);
+    byte[] bytes2 = Files.readAllBytes(file2);
+    return Arrays.equals(bytes1, bytes2);
+  }
+
+}
index 96364e4..f180395 100644 (file)
@@ -1,5 +1,13 @@
 #---JalviewX Properties File---
 #Fri Apr 25 09:54:25 BST 2014
+#
+BACKUPFILES_ROLL_MAX=2
+BACKUPFILES_REVERSE_ORDER=false
+BACKUPFILES_SUFFIX=_BACKUPFILESTESTTMP%n
+BACKUPFILES_CONFIRM_DELETE_OLD=false
+BACKUPFILES_NO_MAX=false
+BACKUPFILES_ENABLED=true
+BACKUPFILES_SUFFIX_DIGITS=8
 SCREEN_Y=768
 SCREEN_X=936
 SHOW_WSDISCOVERY_ERRORS=true