Commit 183ad875 authored by Mikaël Salson's avatar Mikaël Salson

Fasta: Throw rather than exit on error.

An exception can be caught while an exit can't. Thus we can test it.
Moreover some consistency is introduced: Fasta and OnlineFasta will
throw a invalid_argument in case of problem with the input file
(either in opening or parsing it).
parent 17d9c7b1
......@@ -43,7 +43,7 @@ Fasta::Fasta(const string &input,
{
init(extract_field, extract_separator);
if (!input.size()) // Do not open empty files (D germline if not segmentD)
if (!input.size()) // Do not open empty filenames (D germline if not segmentD)
return ;
add(input);
......@@ -59,8 +59,7 @@ void Fasta::add(const string &filename) {
ifstream is(filename.c_str());
if (is.fail())
{
cerr << " !! Error in opening file: " << filename << endl ;
exit(1);
throw invalid_argument(" !! Error in opening file: "+ filename);
}
cout << " <== " << filename ;
......@@ -95,7 +94,7 @@ OnlineFasta::OnlineFasta(const string &input,
extract_separator(extract_separator)
{
if (this->input->fail()) {
throw ios_base::failure("!! Error in opening file "+input);
throw invalid_argument("!! Error in opening file "+input);
}
cout << " <== " << input << endl ;
......@@ -154,7 +153,7 @@ void OnlineFasta::next() {
case '>': state=FASTX_FASTA; break;
case '@': state=FASTX_FASTQ_ID; break;
default:
throw runtime_error("The file seems to be malformed!");
throw invalid_argument("The file seems to be malformed!");
}
// Identifier line
......@@ -173,14 +172,17 @@ void OnlineFasta::next() {
break;
case FASTX_FASTQ_SEQ:
// FASTQ separator between sequence and quality
assert(line[0] == '+');
if (line[0] != '+')
throw invalid_argument("Expected line starting with + in FASTQ file");
break;
case FASTX_FASTQ_SEP:
// Reading quality
current.quality = line;
if (current.quality.length() != current.sequence.length())
throw invalid_argument("Quality and sequence don't have the same length ");
break;
default:
throw runtime_error("Unexpected state after reading identifiers line");
throw invalid_argument("Unexpected state after reading identifiers line");
}
if (state >= FASTX_FASTQ_ID && state <= FASTX_FASTQ_SEP)
state = (fasta_state)(((int)state) + 1);
......@@ -217,7 +219,7 @@ string OnlineFasta::getInterestingLine() {
}
void OnlineFasta::unexpectedEOF() {
throw runtime_error("Unexpected EOF while reading FASTA/FASTQ file");
throw invalid_argument("Unexpected EOF while reading FASTA/FASTQ file");
}
// Operators
......@@ -247,4 +249,3 @@ ostream &operator<<(ostream &out, const Sequence &seq) {
out << seq.sequence << endl;
return out;
}
......@@ -43,7 +43,9 @@ public:
/**
* Read all the sequences in the input filename and record them in the object.
*
*/
* @throws invalid_argument if filename or file content is not
* valid
*/
Fasta(const string &input,
int extract_field=0, string extract_separator="|");
......@@ -58,7 +60,15 @@ public:
const Sequence &read(int index) const;
const string& sequence(int index) const;
/**
* Add the content of the stream to the current object
*/
void add(istream &in);
/**
* Add the content of the file to the current object
* @throws invalid_argument if the file cannot be opened or
* if the content is not valid
*/
void add(const string &filename);
friend istream& operator>>(istream&, Fasta&);
......@@ -90,6 +100,8 @@ class OnlineFasta {
* Open the file and read the first sequence.
* @post getSequence() does not return the first sequence yet.
* next() must be called first.
* @throws invalid_argument if file cannot be opened or is not
* well-formed
*/
OnlineFasta(const string &input,
int extract_field=0, string extract_separator="|");
......@@ -118,6 +130,7 @@ class OnlineFasta {
/**
* Go to the next sequence in the file.
* @post hasNext() ==> getSequence() returns the following sequence in the file.
* @throws invalid_argument if the file is not well formated
*/
void next();
......
#include <core/tools.h>
#include <core/fasta.h>
#include "tests.h"
#include <stdexcept>
void testOnlineFasta1() {
OnlineFasta fa("../../data/test1.fa");
......@@ -59,6 +60,43 @@ void testFastaAdd() {
}
}
void testFastaAddThrows() {
bool caught = false;
try {
Fasta fa1("mlkdkklflskjfskldfj.fa");
} catch (invalid_argument e) {
caught = true;
}
TAP_TEST(caught == true, TEST_FASTA_INVALID_FILE, "");
Fasta fa1("../../data/test1.fa");
caught = false;
try {
fa1.add("ljk:lkjsdfsdlfjsdlfkjs.fa");
} catch (invalid_argument e) {
caught = true;
}
TAP_TEST(caught == true, TEST_FASTA_INVALID_FILE, "");
caught = false;
try {
fa1.add("testTools.cpp");
} catch (invalid_argument e) {
caught = true;
}
TAP_TEST(caught == true, TEST_FASTA_INVALID_FILE, "");
caught = false;
try {
OnlineFasta fa("lkjdflkdfjglkdfjg.fa");
} catch (invalid_argument e) {
caught = true;
}
TAP_TEST(caught == true, TEST_FASTA_INVALID_FILE, "");
}
void testRevcomp() {
TAP_TEST(complement("AATCAGactgactagATCGAn") == "TTAGTCTGACTGATCTAGCTN", TEST_REVCOMP, "");
TAP_TEST(revcomp("AATCAGactgactagATCGAn") == "NTCGATCTAGTCAGTCTGATT", TEST_REVCOMP, "");
......
......@@ -12,6 +12,7 @@ enum {
TEST_FASTA_LABEL_FULL,
TEST_FASTA_SEQUENCE,
TEST_FASTA_ADD,
TEST_FASTA_INVALID_FILE,
TEST_CREATE_SEQUENCE_LABEL_FULL,
TEST_CREATE_SEQUENCE_LABEL,
TEST_CREATE_SEQUENCE_SEQUENCE,
......@@ -112,6 +113,7 @@ inline void declare_tests() {
RECORD_TAP_TEST(TEST_FASTA_LABEL_FULL, "Fasta/Fastq full label");
RECORD_TAP_TEST(TEST_FASTA_SEQUENCE, "Fasta/Fastq sequence");
RECORD_TAP_TEST(TEST_FASTA_ADD, "Fasta add() method");
RECORD_TAP_TEST(TEST_FASTA_INVALID_FILE, "Fasta with invalid file");
RECORD_TAP_TEST(TEST_CREATE_SEQUENCE_LABEL_FULL, "create_sequence: label_full field");
RECORD_TAP_TEST(TEST_CREATE_SEQUENCE_LABEL, "create_sequence: label field");
RECORD_TAP_TEST(TEST_CREATE_SEQUENCE_SEQUENCE, "create_sequence: sequence field");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment