Merge branch 'develop' into features/mchmmer
[jalview.git] / test / jalview / io / FormatAdapterTest.java
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 static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertNotNull;
25 import static org.testng.AssertJUnit.fail;
26
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.SequenceI;
29 import jalview.gui.JvOptionPane;
30
31 import java.io.IOException;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.DataProvider;
37 import org.testng.annotations.Test;
38
39 public class FormatAdapterTest
40 {
41
42   @BeforeClass(alwaysRun = true)
43   public void setUpJvOptionPane()
44   {
45     JvOptionPane.setInteractiveMode(false);
46     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
47   }
48
49   /**
50    * Test saving and re-reading in a specified format
51    * 
52    * @throws IOException
53    */
54   @Test(groups = { "Functional" }, dataProvider = "formats")
55   public void testRoundTrip(FileFormatI format) throws IOException
56   {
57     try
58     {
59       AlignmentI al;
60       if (format == FileFormat.HMMER3)
61       {
62         al = new FormatAdapter().readFile("examples/uniref50.hmm",
63                 DataSourceType.FILE, FileFormat.HMMER3);
64       }
65       else
66       {
67         al = new FormatAdapter().readFile("examples/uniref50.fa",
68               DataSourceType.FILE, FileFormat.Fasta);
69       }
70
71       /*
72        * 'gap' is the gap character used in the alignment data file here,
73        * not the user preferred gap character
74        */
75       char gap = al.getGapCharacter();
76       assertNotNull(al);
77
78       SequenceI[] seqs = al.getSequencesArray();
79       String formatted = new FormatAdapter().formatSequences(format, al,
80               false);
81
82       AlignmentI reloaded = new FormatAdapter().readFile(formatted,
83               DataSourceType.PASTE, format);
84       List<SequenceI> reread = reloaded.getSequences();
85         assertEquals("Wrong number of reloaded sequences", seqs.length,
86                 reread.size());
87
88
89       int i = 0;
90       for (SequenceI seq : reread)
91       {
92         String sequenceString = seq.getSequenceAsString();
93
94         /*
95          * special case: MSF always uses '.' as gap character
96          */
97         sequenceString = adjustForGapTreatment(sequenceString, gap, format);
98         assertEquals(
99                 String.format("Sequence %d: %s", i, seqs[i].getName()),
100                 seqs[i].getSequenceAsString(), sequenceString);
101         i++;
102       }
103     } catch (IOException e)
104     {
105       fail(String
106               .format("Format %s failed with %s", format, e.getMessage()));
107     }
108   }
109
110   /**
111    * Optionally change the gap character in the string to the given character,
112    * depending on the sequence file format
113    * 
114    * @param sequenceString
115    *          a sequence (as written in 'format' format)
116    * @param gap
117    *          the sequence's original gap character
118    * @param format
119    * @return
120    */
121   String adjustForGapTreatment(String sequenceString, char gap,
122           FileFormatI format)
123   {
124     if (FileFormat.MSF.equals(format))
125     {
126       /*
127        * MSF forces gap character to '.', so change it back
128        * for comparison purposes
129        */
130       sequenceString = sequenceString.replace('.', gap);
131     }
132     return sequenceString;
133   }
134
135   /**
136    * Data provider that serves alignment formats that are both readable and
137    * (text) writable
138    * 
139    * @return
140    */
141   @DataProvider(name = "formats")
142   static Object[][] getFormats()
143   {
144     List<FileFormatI> both = new ArrayList<>();
145     for (FileFormatI format : FileFormats.getInstance().getFormats())
146     {
147       if (format.isReadable() && format.isWritable()
148               && format.isTextFormat())
149       {
150         both.add(format);
151       }
152     }
153
154     Object[][] formats = new Object[both.size()][];
155     int i = 0;
156     for (FileFormatI format : both)
157     {
158       formats[i] = new Object[] { format };
159       i++;
160     }
161     return formats;
162   }
163
164   /**
165    * Enable this to isolate testing to a single file format
166    * 
167    * @throws IOException
168    */
169   @Test(groups = { "Functional" }, enabled = false)
170   public void testOneFormatRoundTrip() throws IOException
171   {
172     testRoundTrip(FileFormat.Json);
173   }
174 }