/* + Copyright 2019 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "WorkArea.cpp" #include #define BOOST_TEST_MODULE Test EclIO #include using namespace Opm::EclIO; template bool range_equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { while(first1 != last1 && first2 != last2) { if(*first1 != *first2) return false; ++first1; ++first2; } return (first1 == last1) && (first2 == last2); } bool compare_files(const std::string& filename1, const std::string& filename2) { std::ifstream file1(filename1); std::ifstream file2(filename2); std::istreambuf_iterator begin1(file1); std::istreambuf_iterator begin2(file2); std::istreambuf_iterator end; return range_equal(begin1, end, begin2, end); } template bool operator==(const std::vector & t1, const std::vector & t2) { return std::equal(t1.begin(), t1.end(), t2.begin(), t2.end()); } void write_header(std::ofstream& ofileH, std::string& arrName, int size, std::string arrtype){ int bhead = flipEndianInt(16); int fsize = flipEndianInt(size); ofileH.write(reinterpret_cast(&bhead), sizeof(bhead)); ofileH.write(arrName.c_str(), 8); ofileH.write(reinterpret_cast(&fsize), sizeof(fsize)); ofileH.write(arrtype.c_str(), 4); ofileH.write(reinterpret_cast(&bhead), sizeof(bhead)); } BOOST_AUTO_TEST_CASE(TestEclFile_X231) { std::string filename = "TEST.DAT"; std::string arrName = "TESTX231"; std::vector ivect(10); std::iota(ivect.begin(), ivect.end(), -4); { std::ofstream ofileH; ofileH.open(filename, std::ios_base::binary); int size = static_cast((-1) * std::pow(2,31) + 10); write_header(ofileH, arrName, -1, std::string("X231")); write_header(ofileH, arrName, size, std::string("INTE")); int sizeData = ivect.size()*sizeof(int); sizeData = flipEndianInt(sizeData); ofileH.write(reinterpret_cast(&sizeData), sizeof(sizeData)); for (auto v : ivect){ int fval = flipEndianInt(v); ofileH.write(reinterpret_cast(&fval), sizeof(fval)); } ofileH.write(reinterpret_cast(&sizeData), sizeof(sizeData)); ofileH.close(); } EclFile test1(filename); auto array = test1.get(arrName); for (size_t n = 0; n < 10; n++){ BOOST_CHECK_EQUAL(array[n], ivect[n]); } } BOOST_AUTO_TEST_CASE(TestEclFile_BINARY) { std::string testFile="ECLFILE.INIT"; // check that exception is thrown when input file doesn't exist BOOST_CHECK_THROW(EclFile file1("DUMMY.DAT") , std::invalid_argument ); EclFile file1(testFile); // check that exeption is thrown when member function get is used with wrong type BOOST_CHECK_THROW(std::vector vect1=file1.get(2) , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get("PORV") , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get(0) , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get("ICON") , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get(0) , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get("KEYWORDS") , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get(0) , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get("XCON") , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get(0) , std::runtime_error ); BOOST_CHECK_THROW(std::vector vect1=file1.get("XCON") , std::runtime_error ); // check member function hasKey BOOST_CHECK_EQUAL(file1.hasKey("PORV"), true); BOOST_CHECK_EQUAL(file1.hasKey("XPORV"), false); // test member functon get, use size of vector to confirm that vectror is ok std::vector vect1a=file1.get(0); std::vector vect1b=file1.get("ICON"); BOOST_CHECK_EQUAL(vect1a.size(), 1875U); BOOST_CHECK_EQUAL(vect1b.size(), 1875U); std::vector vect2a=file1.get(1); std::vector vect2b=file1.get("LOGIHEAD"); BOOST_CHECK_EQUAL(vect2a.size(), 121U); BOOST_CHECK_EQUAL(vect2b.size(), 121U); std::vector vect3a=file1.get(2); std::vector vect3b=file1.get("PORV"); BOOST_CHECK_EQUAL(vect3a.size(), 3146U); BOOST_CHECK_EQUAL(vect3b.size(), 3146U); std::vector vect4a=file1.get(3); std::vector vect4b=file1.get("XCON"); BOOST_CHECK_EQUAL(vect4a.size(), 1740U); BOOST_CHECK_EQUAL(vect4b.size(), 1740U); std::vector vect5a=file1.get(4); std::vector vect5b=file1.get("KEYWORDS"); BOOST_CHECK_EQUAL(vect5a.size(), 312U); BOOST_CHECK_EQUAL(vect5b.size(), 312U); } BOOST_AUTO_TEST_CASE(TestEclFile_FORMATTED) { std::string testFile1="ECLFILE.INIT"; std::string testFile2="ECLFILE.FINIT"; // loading data both from binary and formatted file. Check that // date vectors are identical EclFile file1(testFile1); file1.loadData(); EclFile file2(testFile2); file2.loadData(); std::vector vect1a=file1.get("ICON"); std::vector vect1b=file2.get("ICON"); BOOST_CHECK_EQUAL(vect1a.size(), vect1b.size()); BOOST_CHECK(vect1a == vect1b); std::vector vect2a=file1.get("PORV"); std::vector vect2b=file2.get("PORV"); BOOST_CHECK_EQUAL(vect2a.size(), vect2b.size()); BOOST_CHECK(vect2a == vect2b); std::vector vect3a=file1.get("XCON"); std::vector vect3b=file2.get("XCON"); BOOST_CHECK(vect3a == vect3b); std::vector vect4a=file1.get("LOGIHEAD"); std::vector vect4b=file2.get("LOGIHEAD"); BOOST_CHECK_EQUAL(vect4a.size(), vect4b.size()); BOOST_CHECK(vect4a == vect4b); std::vector vect5a=file1.get("KEYWORDS"); std::vector vect5b=file2.get("KEYWORDS"); BOOST_CHECK_EQUAL(vect5a.size(), vect5b.size()); BOOST_CHECK(vect5a == vect5b); } BOOST_AUTO_TEST_CASE(TestEcl_Write_binary) { std::string inputFile="ECLFILE.INIT"; std::string testFile="TEST.DAT"; // loading vectors from binary file and write these back to a binary file1 // compare input and output file and delete file. EclFile file1(inputFile); file1.loadData(); std::vector icon=file1.get("ICON"); std::vector porv=file1.get("PORV"); std::vector xcon=file1.get("XCON"); std::vector logihead=file1.get("LOGIHEAD"); std::vector keywords=file1.get("KEYWORDS"); // writing vectors to test file (TEST.DAT) using class EclOutput { EclOutput eclTest(testFile, false); eclTest.write("ICON",icon); eclTest.write("LOGIHEAD",logihead); eclTest.write("PORV",porv); eclTest.write("XCON",xcon); eclTest.write("KEYWORDS",keywords); eclTest.write("ENDSOL",std::vector()); } BOOST_CHECK_EQUAL(compare_files(inputFile, testFile), true); if (remove(testFile.c_str())==-1) { std::cout << " > Warning! temporary file was not deleted" << std::endl; }; } BOOST_AUTO_TEST_CASE(TestEcl_Write_formatted) { std::string inputFile="ECLFILE.FINIT"; std::string testFile="TEST.FDAT"; // loading vectors from formatted input file and write data back to a formatted file1 // compare input and output file, and delete file. EclFile file1(inputFile, true); std::vector icon = file1.get("ICON"); std::vector porv = file1.get("PORV"); std::vector xcon = file1.get("XCON"); std::vector logihead = file1.get("LOGIHEAD"); std::vector keywords = file1.get("KEYWORDS"); // writing vectors to test file (TEST.FDAT) using class EclOutput EclOutput eclTest(testFile, true); eclTest.write("ICON",icon); eclTest.write("LOGIHEAD",logihead); eclTest.write("PORV",porv); eclTest.write("XCON",xcon); eclTest.write("KEYWORDS",keywords); eclTest.write("ENDSOL",std::vector()); BOOST_CHECK_EQUAL(compare_files(inputFile, testFile), true); if (remove(testFile.c_str())==-1) { std::cout << " > Warning! temporary file was not deleted" << std::endl; }; } BOOST_AUTO_TEST_CASE(TestEcl_Write_formatted_not_finite) { WorkArea wa; std::vector float_vector{std::numeric_limits::infinity() , std::numeric_limits::quiet_NaN()}; std::vector double_vector{std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()}; { EclOutput testfile("TEST.FINIT", true); testfile.write("FLOAT", float_vector); testfile.write("DOUBLE", double_vector); } EclFile file1("TEST.FINIT"); file1.loadData(); auto f = file1.get("FLOAT"); auto d = file1.get("DOUBLE"); BOOST_CHECK(std::isinf(f[0])); BOOST_CHECK(std::isinf(d[0])); BOOST_CHECK(std::isnan(f[1])); BOOST_CHECK(std::isnan(d[1])); BOOST_CHECK_EQUAL(file1.size(), 2U); } BOOST_AUTO_TEST_CASE(TestEcl_getList) { std::string inputFile="ECLFILE.INIT"; std::string testFile="TEST.DAT"; // use EclFile to read/open a binary file // Use API for class EclFile together with class EclOutput to write an // identical eclfile // EclFile::getList(), EclFile::get(int) EclFile file1(inputFile); file1.loadData(); { EclOutput eclTest(testFile, false); auto arrayList = file1.getList(); int n=0; for (auto array : arrayList) { std::string name = std::get<0>(array); eclArrType arrType = std::get<1>(array); if (arrType == INTE) { std::vector vect = file1.get(n); eclTest.write(name, vect); } else if (arrType == REAL) { std::vector vect = file1.get(n); eclTest.write(name, vect); } else if (arrType == DOUB) { std::vector vect = file1.get(n); eclTest.write(name, vect); } else if (arrType == LOGI) { std::vector vect = file1.get(n); eclTest.write(name, vect); } else if (arrType == CHAR) { std::vector vect = file1.get(n); eclTest.write(name, vect); } else if (arrType == MESS) { eclTest.write(name, std::vector()); } else { std::cout << "unknown type " << std::endl; exit(1); } n++; } } BOOST_CHECK_EQUAL(compare_files(inputFile, testFile), true); if (remove(testFile.c_str())==-1) { std::cout << " > Warning! temporary file was not deleted" << std::endl; }; } BOOST_AUTO_TEST_CASE(TestEcl_Write_CHAR) { std::string testFile="TEST.FDAT"; std::vector refStrList = {"This", "is", "a test.", "", "charact", "er >'<", "can be", "part of", "a string"}; { EclOutput eclTest(testFile, true); eclTest.write("TEST",refStrList); } { EclFile file1(testFile); std::vector strList=file1.get("TEST"); for (size_t n = 0; n < refStrList.size(); n++) { BOOST_CHECK(refStrList[n] == strList[n]); } } if (remove(testFile.c_str())==-1) { std::cout << " > Warning! temporary file was not deleted" << std::endl; }; }