126TEST_CASE(
"Reading space delimited numeric data",
"[ioutils::readColumns]" )
128 SECTION(
"a single column of floating point numbers" )
130 std::string fname =
"/tmp/readcol_test_single_col_float.dat";
133 fout <<
"#a commment\n";
136 fout <<
"4.96 #with comment\n";
141 SECTION(
"reading as int" )
143 std::vector<int> data0;
146 REQUIRE( data0.size() == 5 );
147 REQUIRE( data0[0] == 1 );
148 REQUIRE( data0[1] == 2 );
149 REQUIRE( data0[2] == 4 );
150 REQUIRE( data0[3] == 5 );
151 REQUIRE( data0[4] == 1 );
154 SECTION(
"reading as float" )
156 std::vector<float> data0;
159 REQUIRE( data0.size() == 5 );
160 REQUIRE_THAT( data0[0], WithinRel( 1.23, 1e-5 ) );
161 REQUIRE_THAT( data0[1], WithinRel( 2.15, 1e-5 ) );
162 REQUIRE_THAT( data0[2], WithinRel( 4.96, 1e-5 ) );
163 REQUIRE_THAT( data0[3], WithinRel( 5.23, 1e-5 ) );
164 REQUIRE_THAT( data0[4], WithinRel( 1e-9, 1e-5 ) );
168 SECTION(
"a two columns of floating point numbers" )
170 std::string fname =
"/tmp/readcol_test_two_cols_float.dat";
173 fout <<
"#a commment\n";
174 fout <<
"1.23 6.78\n";
175 fout <<
"2.15 8.88\n";
176 fout <<
"4.96 -2.33#with comment\n";
179 fout <<
"5.23 9.9e5\n";
180 fout <<
"1e-9 -5.6e2\n";
181 fout <<
" #comment at end not on first char and no newline";
184 SECTION(
"reading both as int" )
186 std::vector<int> data0, data1;
189 REQUIRE( data0.size() == 5 );
190 REQUIRE( data0[0] == 1 );
191 REQUIRE( data0[1] == 2 );
192 REQUIRE( data0[2] == 4 );
193 REQUIRE( data0[3] == 5 );
194 REQUIRE( data0[4] == 1 );
196 REQUIRE( data1.size() == 5 );
197 REQUIRE( data1[0] == 6 );
198 REQUIRE( data1[1] == 8 );
199 REQUIRE( data1[2] == -2 );
200 REQUIRE( data1[3] == 9 );
201 REQUIRE( data1[4] == -5 );
204 SECTION(
"reading both as float" )
206 std::vector<float> data0, data1;
209 REQUIRE( data0.size() == 5 );
210 REQUIRE_THAT( data0[0], WithinRel( 1.23, 1e-5 ) );
211 REQUIRE_THAT( data0[1], WithinRel( 2.15, 1e-5 ) );
212 REQUIRE_THAT( data0[2], WithinRel( 4.96, 1e-5 ) );
213 REQUIRE_THAT( data0[3], WithinRel( 5.23, 1e-5 ) );
214 REQUIRE_THAT( data0[4], WithinRel( 1e-9, 1e-5 ) );
216 REQUIRE( data1.size() == 5 );
217 REQUIRE_THAT( data1[0], WithinRel( 6.78, 1e-5 ) );
218 REQUIRE_THAT( data1[1], WithinRel( 8.88, 1e-5 ) );
219 REQUIRE_THAT( data1[2], WithinRel( -2.33, 1e-5 ) );
220 REQUIRE_THAT( data1[3], WithinRel( 9.9e5, 1e-5 ) );
221 REQUIRE_THAT( data1[4], WithinRel( -5.6e2, 1e-5 ) );
283TEST_CASE(
"Reading combined type data",
"[ioutils::readColumns]" )
285 SECTION(
"a single column of floating point numbers" )
287 std::string fname =
"/tmp/readcol_test_combos.dat";
290 fout <<
"test1 1.23 2.56\n";
291 fout <<
"test2 2.15 8.93\n";
292 fout <<
"test3 0 0\n";
293 fout <<
"test4 6.7 1\n";
294 fout <<
"test5 0 22.2\n";
295 fout <<
"test6 1e-4 0\n";
298 std::vector<std::string> str0;
299 std::vector<float> data1, data2;
305 REQUIRE( str0[0] ==
"test1" );
306 REQUIRE( str0[1] ==
"test2" );
307 REQUIRE( str0[2] ==
"test3" );
308 REQUIRE( str0[3] ==
"test4" );
309 REQUIRE( str0[4] ==
"test5" );
310 REQUIRE( str0[5] ==
"test6" );
312 REQUIRE_THAT( data1[0], WithinRel( 1.23, 1e-7 ) );
313 REQUIRE_THAT( data1[1], WithinRel( 2.15, 1e-7 ) );
314 REQUIRE( data1[2] == 0 );
315 REQUIRE_THAT( data1[3], WithinRel( 6.7, 1e-7 ) );
316 REQUIRE( data1[4] == 0 );
317 REQUIRE_THAT( data1[5], WithinRel( 1e-4, 1e-7 ) );
319 REQUIRE_THAT( data2[0], WithinRel( 2.56, 1e-7 ) );
320 REQUIRE_THAT( data2[1], WithinRel( 8.93, 1e-7 ) );
321 REQUIRE( data2[2] == 0 );
322 REQUIRE_THAT( data2[3], WithinRel( 1, 1e-7 ) );
323 REQUIRE_THAT( data2[4], WithinRel( 22.2, 1e-7 ) );
324 REQUIRE( data2[5] == 0 );
355TEST_CASE(
"Parsing column edge cases",
"[ioutils::readColumns]" )
357 SECTION(
"empty input" )
359 std::vector<std::string> values;
361 REQUIRE( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
"", 0, column, values ) ==
363 REQUIRE( values.empty() );
366 SECTION(
"whitespace-only final field" )
368 std::vector<std::string> values;
370 REQUIRE( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
" ", 3, column, values ) ==
372 REQUIRE( values == std::vector<std::string>{
"" } );
375 SECTION(
"invalid whitespace-only numeric final field" )
377 std::vector<double> values;
379 REQUIRE( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
" ", 3, column, values ) ==
383 SECTION(
"missing comma-delimited field" )
385 std::vector<int> values;
387 REQUIRE( mx::ioutils::readcol<mx::ioutils::readColCommaDelim, mx::verbose::vv>(
",value", 6, column, values ) ==
389 REQUIRE( values == std::vector<int>{ -99 } );
392 SECTION(
"terminated direct field" )
394 std::vector<std::string> values;
397 mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
"value\n", 6, column, values ) ==
399 REQUIRE( values == std::vector<std::string>{
"value" } );
402 SECTION(
"skipped field" )
404 const std::string filename{
"/tmp/readcol_test_skip.dat" };
405 std::ofstream fout{ filename };
406 fout <<
"first ignored 2.5\n";
409 std::vector<std::string> names;
411 std::vector<double> values;
417 REQUIRE( names == std::vector<std::string>{
"first" } );
418 REQUIRE( values == std::vector<double>{ 2.5 } );
426TEST_CASE(
"Handling column conversion exceptions",
"[ioutils::readColumns]" )
428 throwingColumn values;
431 SECTION(
"always-translated conversion exceptions" )
433 injectedFailure = injectedReadColumnsFailure::invalidArgument;
434 REQUIRE( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
"value", 5, column, values ) ==
437 injectedFailure = injectedReadColumnsFailure::outOfRange;
438 REQUIRE( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
"value", 5, column, values ) ==
442 SECTION(
"allocation failure" )
444 injectedFailure = injectedReadColumnsFailure::badAlloc;
446 ( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
"value", 5, column, values ) ),
448 REQUIRE( mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readcol<
449 mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColSpaceDelim,
453 SECTION(
"standard failure" )
455 injectedFailure = injectedReadColumnsFailure::standard;
457 ( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
"value", 5, column, values ) ),
459 REQUIRE( mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readcol<
460 mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColSpaceDelim,
464 SECTION(
"unknown failure" )
466 injectedFailure = injectedReadColumnsFailure::unknown;
468 ( mx::ioutils::readcol<mx::ioutils::readColSpaceDelim, mx::verbose::vv>(
"value", 5, column, values ) ),
470 REQUIRE( mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readcol<
471 mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColSpaceDelim,
480TEST_CASE(
"Handling line-read exceptions",
"[ioutils::readColumns]" )
482 const std::string filename{
"/tmp/readcol_test_line_exceptions.dat" };
483 std::ofstream fout{ filename };
484 fout <<
"value 1.5\n";
487 readColumnsHookGuard guard;
488 failingOperation = mx::ioutils::readColumnsDetail::operation::afterReadLine;
489 std::vector<std::string> names;
490 std::vector<double> values;
492 SECTION(
"allocation failure" )
494 injectedFailure = injectedReadColumnsFailure::badAlloc;
498 REQUIRE( mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColumns<
499 mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColSpaceDelim,
503 SECTION(
"standard failure" )
505 injectedFailure = injectedReadColumnsFailure::standard;
509 REQUIRE( mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColumns<
510 mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColSpaceDelim,
514 SECTION(
"unknown failure" )
516 injectedFailure = injectedReadColumnsFailure::unknown;
520 REQUIRE( mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColumns<
521 mx::ioutils::MXLIBTEST_CATCH_ALL_EXCEPTIONS_ns::readColSpaceDelim,
530TEST_CASE(
"Handling column file stream errors",
"[ioutils::readColumns]" )
532 const std::string filename{
"/tmp/readcol_test_stream_errors.dat" };
533 std::ofstream fout{ filename };
534 fout <<
"value 1.5\n";
537 readColumnsHookGuard guard;
538 std::vector<std::string> names;
539 std::vector<double> values;
541 for(
auto operation : { mx::ioutils::readColumnsDetail::operation::afterOpen,
542 mx::ioutils::readColumnsDetail::operation::afterReadLine,
543 mx::ioutils::readColumnsDetail::operation::afterClose } )
545 failingOperation = operation;
547 injectedFailure = injectedReadColumnsFailure::streamErrno;
551 injectedFailure = injectedReadColumnsFailure::streamFallback;