Nektar++
MetricFile.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: MetricFile.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Implementation of the File metric.
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include <fstream>
36#include <iterator>
37#include <vector>
38
39#include <boost/algorithm/string.hpp>
40#include <boost/core/ignore_unused.hpp>
41
43
44#include <MetricFile.h>
45#include <sha1.h>
46
47namespace Nektar
48{
49std::string MetricFile::type =
51
52MetricFile::MetricFile(TiXmlElement *metric, bool generate)
53 : Metric(metric, generate)
54{
55 TiXmlElement *file = metric->FirstChildElement("file");
56 ASSERTL0(file, "Missing file tag for file metric!");
57
58 while (file)
59 {
60 std::string filename, sha1hash;
61
62 if (file->Attribute("filename"))
63 {
64 filename = file->Attribute("filename");
65 }
66 else
67 {
68 ASSERTL0(false, "Missing filename for file tag!");
69 }
70
71 if (!m_generate)
72 {
73 TiXmlElement *sha1 = file->FirstChildElement("sha1");
74 ASSERTL0(sha1, "Missing SHA1 hash for file " + filename);
75 sha1hash = sha1->GetText();
76 ASSERTL0(sha1hash.size() == 40, "Incorrect length for SHA1 hash");
77 }
78
79 m_filehash[filename] = sha1hash;
80
81 file = file->NextSiblingElement("file");
82 }
83}
84
85std::string MetricFile::CalculateHash(std::string pfilename)
86{
87 int fdot = pfilename.find_last_of('.');
88 string ending = pfilename.substr(fdot);
89 string filename;
90
91 if (ending == ".fld" || ending == ".chk" || ending == ".rst")
92 {
93 TiXmlDocument *xmlFldFile;
94 fs::path pathfilename(pfilename);
95
96 if (fs::is_directory(pathfilename))
97 {
98 std::vector<fs::path> dirfiles;
99
100 // make list of all files in directoryj
101 copy(fs::directory_iterator(pathfilename), fs::directory_iterator(),
102 back_inserter(dirfiles));
103
104 xmlFldFile = new TiXmlDocument;
105
106 // load all them into the
107 for (int i = 0; i < dirfiles.size(); ++i)
108 {
109 std::string infile = LibUtilities::PortablePath(dirfiles[i]);
110 std::ifstream file(infile.c_str());
111 ASSERTL0(file.good(), "Unable to open file: " + infile);
112 file >> (*xmlFldFile);
113 }
114 }
115 else
116 {
117 xmlFldFile = new TiXmlDocument(pfilename);
118 xmlFldFile->LoadFile(pfilename);
119 }
120
121 // strip out meta data before check
122 TiXmlElement *vNektar = xmlFldFile->FirstChildElement("NEKTAR");
123 while (vNektar)
124 {
125
126 TiXmlNode *vMetaData = vNektar->FirstChild("Metadata");
127
128 // delete MetaData section
129 if (vMetaData)
130 {
131 vNektar->RemoveChild(vMetaData);
132 }
133 vNektar = vNektar->NextSiblingElement("NEKTAR");
134 }
135
136 filename = pfilename + ".tmp";
137 xmlFldFile->SaveFile(filename);
138 }
139 else
140 {
141 filename = pfilename;
142 }
143
144 // Open file.
145 std::ifstream testFile(filename.c_str(), std::ios::binary);
146 ASSERTL0(testFile.is_open(), "Error opening file " + filename);
147
148 // Read in file contents.
149 std::vector<char> fileContents((std::istreambuf_iterator<char>(testFile)),
150 std::istreambuf_iterator<char>());
151
152 // Calculate SHA1 hash.
153 unsigned char hash[20];
154 char strhash[41];
155
156 sha1::calc((void *)&fileContents[0], fileContents.size(), hash);
157 sha1::toHexString(hash, strhash);
158
159 // Close file and return string containing SHA1 hash.
160 testFile.close();
161
162 return std::string(strhash);
163}
164
165bool MetricFile::v_Test(std::istream &pStdout, std::istream &pStderr)
166{
167 boost::ignore_unused(pStdout, pStderr);
168
169 std::map<std::string, std::string>::iterator it;
170 bool success = true;
171
172 for (it = m_filehash.begin(); it != m_filehash.end(); ++it)
173 {
174 std::string filehash = CalculateHash(it->first);
175 if (!boost::iequals(filehash, it->second))
176 {
177 std::cerr << "Failed SHA1 hash test." << std::endl;
178 std::cerr << " Expected: " << it->second << std::endl;
179 std::cerr << " Result: " << filehash << std::endl;
180 success = false;
181 }
182 }
183
184 return success;
185}
186
187void MetricFile::v_Generate(std::istream &pStdout, std::istream &pStderr)
188{
189 boost::ignore_unused(pStdout, pStderr);
190
191 std::map<std::string, std::string>::iterator it;
192
193 // Update SHA1 hashes.
194 for (it = m_filehash.begin(); it != m_filehash.end(); ++it)
195 {
196 std::string filehash = CalculateHash(it->first);
197 m_filehash[it->first] = filehash;
198 }
199
200 // Write new XML structure.
201 TiXmlElement *file = m_metric->FirstChildElement("file");
202 while (file)
203 {
204 std::string filename = file->Attribute("filename");
205 file->Clear();
206
207 TiXmlElement *sha1 = new TiXmlElement("sha1");
208
209 ASSERTL0(m_filehash.count(filename) != 0, "Couldn't find file " +
210 filename +
211 " in list of calculated"
212 "hashes");
213
214 sha1->LinkEndChild(new TiXmlText(m_filehash[filename]));
215 file->LinkEndChild(sha1);
216 file = file->NextSiblingElement("file");
217 }
218}
219} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
std::string RegisterCreatorFunction(std::string key, CreatorFunction func)
Definition: Metric.h:133
std::string CalculateHash(std::string filename)
Definition: MetricFile.cpp:85
static std::string type
Definition: MetricFile.h:55
MetricFile(TiXmlElement *metric, bool generate)
Definition: MetricFile.cpp:52
std::map< std::string, std::string > m_filehash
Stores filenames to perform hash on.
Definition: MetricFile.h:66
bool v_Test(std::istream &pStdout, std::istream &pStderr) override
Virtual function to test the metric. Should be redefined in derived classes.
Definition: MetricFile.cpp:165
static MetricSharedPtr create(TiXmlElement *metric, bool generate)
Definition: MetricFile.h:50
void v_Generate(std::istream &pStdout, std::istream &pStderr) override
Virtual function to generate the metric. Should be redefined in derived classes.
Definition: MetricFile.cpp:187
Base class for all metrics. Metric represents a test metric that can be used to evaluate the function...
Definition: Metric.h:65
TiXmlElement * m_metric
Pointer to XML structure containing metric definition.
Definition: Metric.h:101
bool m_generate
Determines whether to generate this metric or not.
Definition: Metric.h:96
def copy(self)
Definition: pycml.py:2663
static std::string PortablePath(const fs::path &path)
create portable path on different platforms for std::filesystem path.
Definition: Filesystem.hpp:56
MetricFactory & GetMetricFactory()
Definition: Metric.cpp:42
Definition: sha1.cpp:72
void toHexString(const unsigned char *hash, char *hexstring)
Calculate a string which represents the SHA1 hash as a hexadecimal number.
Definition: sha1.cpp:213
void calc(const void *src, const int bytelength, unsigned char *hash)
Calculate the SHA1 hash of some data set.
Definition: sha1.cpp:150