From 85c8a687e7bdb5f2edf5baf8d90d47628fa8d66e Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Fri, 2 Nov 2018 16:37:33 +0000 Subject: [PATCH] JAL-3141 Tests now available and working, bringing to light a problem with the classInit flag (now removed). Added some more dodgy Spanish translations. --- examples/backupfilestest.fa | 2 + resources/lang/Messages_es.properties | 24 ++- src/jalview/gui/Preferences.java | 6 +- src/jalview/io/BackupFilenameFilter.java | 3 +- src/jalview/io/BackupFiles.java | 73 ++++++- test/jalview/io/AnnotationFileIOTest.java | 2 +- test/jalview/io/BackupFilesTest.java | 322 +++++++++++++++++++++++++++++ test/jalview/io/testProps.jvprops | 8 + 8 files changed, 423 insertions(+), 17 deletions(-) create mode 100644 examples/backupfilestest.fa create mode 100644 test/jalview/io/BackupFilesTest.java diff --git a/examples/backupfilestest.fa b/examples/backupfilestest.fa new file mode 100644 index 0000000..c536a79 --- /dev/null +++ b/examples/backupfilestest.fa @@ -0,0 +1,2 @@ +>BACKUP_FILES/1-6 backupfiles +AAAARG diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index f3be98c..bd7c7b3 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -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 diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index 99e1cc8..e1c6089 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -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 diff --git a/src/jalview/io/BackupFilenameFilter.java b/src/jalview/io/BackupFilenameFilter.java index bb2af1c..1fed65c 100644 --- a/src/jalview/io/BackupFilenameFilter.java +++ b/src/jalview/io/BackupFilenameFilter.java @@ -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(); diff --git a/src/jalview/io/BackupFiles.java b/src/jalview/io/BackupFiles.java index 784d8a1..0b6b090 100644 --- a/src/jalview/io/BackupFiles.java +++ b/src/jalview/io/BackupFiles.java @@ -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 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 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 bfTreeMap = new TreeMap<>(); + bfTreeMap.putAll(bfHashMap); + + return bfTreeMap; + } + + public static File[] lsBackupFiles(String fileName, String suffix, + int digits) + { + TreeMap bfTreeMap = lsBackupFilesAsTreeMap(fileName, + suffix, digits); + File[] backupFiles = new File[bfTreeMap.size()]; + bfTreeMap.values().toArray(backupFiles); + return backupFiles; + } + } diff --git a/test/jalview/io/AnnotationFileIOTest.java b/test/jalview/io/AnnotationFileIOTest.java index 6a00cde..05ce22d 100644 --- a/test/jalview/io/AnnotationFileIOTest.java +++ b/test/jalview/io/AnnotationFileIOTest.java @@ -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 index 0000000..c1a8d4c --- /dev/null +++ b/test/jalview/io/BackupFilesTest.java @@ -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 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 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 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); + } + +} diff --git a/test/jalview/io/testProps.jvprops b/test/jalview/io/testProps.jvprops index 96364e4..f180395 100644 --- a/test/jalview/io/testProps.jvprops +++ b/test/jalview/io/testProps.jvprops @@ -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 -- 1.7.10.2