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
42#include <MetricFile.h>
43#include <sha1.h>
44
45namespace Nektar
46{
47std::string MetricFile::type =
49
50MetricFile::MetricFile(TiXmlElement *metric, bool generate)
51 : Metric(metric, generate)
52{
53 TiXmlElement *file = metric->FirstChildElement("file");
54 ASSERTL0(file, "Missing file tag for file metric!");
55
56 while (file)
57 {
58 std::string filename, sha1hash;
59
60 if (file->Attribute("filename"))
61 {
62 filename = file->Attribute("filename");
63 }
64 else
65 {
66 ASSERTL0(false, "Missing filename for file tag!");
67 }
68
69 if (!m_generate)
70 {
71 TiXmlElement *sha1 = file->FirstChildElement("sha1");
72 ASSERTL0(sha1, "Missing SHA1 hash for file " + filename);
73 sha1hash = sha1->GetText();
74 ASSERTL0(sha1hash.size() == 40, "Incorrect length for SHA1 hash");
75 }
76
77 m_filehash[filename] = sha1hash;
78
79 file = file->NextSiblingElement("file");
80 }
81}
82
83std::string MetricFile::CalculateHash(std::string pfilename)
84{
85 int fdot = pfilename.find_last_of('.');
86 string ending = pfilename.substr(fdot);
87 string filename;
88
89 if (ending == ".fld" || ending == ".chk" || ending == ".rst")
90 {
91 TiXmlDocument *xmlFldFile;
92 fs::path pathfilename(pfilename);
93
94 if (fs::is_directory(pathfilename))
95 {
96 std::vector<fs::path> dirfiles;
97
98 // make list of all files in directoryj
99 copy(fs::directory_iterator(pathfilename), fs::directory_iterator(),
100 back_inserter(dirfiles));
101
102 xmlFldFile = new TiXmlDocument;
103
104 // load all them into the
105 for (int i = 0; i < dirfiles.size(); ++i)
106 {
107 std::string infile = PortablePath(dirfiles[i]);
108 std::ifstream file(infile.c_str());
109 ASSERTL0(file.good(), "Unable to open file: " + infile);
110 file >> (*xmlFldFile);
111 }
112 }
113 else
114 {
115 xmlFldFile = new TiXmlDocument(pfilename);
116 xmlFldFile->LoadFile(pfilename);
117 }
118
119 // strip out meta data before check
120 TiXmlElement *vNektar = xmlFldFile->FirstChildElement("NEKTAR");
121 while (vNektar)
122 {
123
124 TiXmlNode *vMetaData = vNektar->FirstChild("Metadata");
125
126 // delete MetaData section
127 if (vMetaData)
128 {
129 vNektar->RemoveChild(vMetaData);
130 }
131 vNektar = vNektar->NextSiblingElement("NEKTAR");
132 }
133
134 filename = pfilename + ".tmp";
135 xmlFldFile->SaveFile(filename);
136 }
137 else
138 {
139 filename = pfilename;
140 }
141
142 // Open file.
143 std::ifstream testFile(filename.c_str(), std::ios::binary);
144 ASSERTL0(testFile.is_open(), "Error opening file " + filename);
145
146 // Read in file contents.
147 std::vector<char> fileContents((std::istreambuf_iterator<char>(testFile)),
148 std::istreambuf_iterator<char>());
149
150 // Calculate SHA1 hash.
151 unsigned char hash[20];
152 char strhash[41];
153
154 sha1::calc((void *)&fileContents[0], fileContents.size(), hash);
155 sha1::toHexString(hash, strhash);
156
157 // Close file and return string containing SHA1 hash.
158 testFile.close();
159
160 return std::string(strhash);
161}
162
163bool MetricFile::v_Test(std::istream &pStdout, std::istream &pStderr)
164{
165 boost::ignore_unused(pStdout, pStderr);
166
167 std::map<std::string, std::string>::iterator it;
168 bool success = true;
169
170 for (it = m_filehash.begin(); it != m_filehash.end(); ++it)
171 {
172 std::string filehash = CalculateHash(it->first);
173 if (!boost::iequals(filehash, it->second))
174 {
175 std::cerr << "Failed SHA1 hash test." << std::endl;
176 std::cerr << " Expected: " << it->second << std::endl;
177 std::cerr << " Result: " << filehash << std::endl;
178 success = false;
179 }
180 }
181
182 return success;
183}
184
185void MetricFile::v_Generate(std::istream &pStdout, std::istream &pStderr)
186{
187 boost::ignore_unused(pStdout, pStderr);
188
189 std::map<std::string, std::string>::iterator it;
190
191 // Update SHA1 hashes.
192 for (it = m_filehash.begin(); it != m_filehash.end(); ++it)
193 {
194 std::string filehash = CalculateHash(it->first);
195 m_filehash[it->first] = filehash;
196 }
197
198 // Write new XML structure.
199 TiXmlElement *file = m_metric->FirstChildElement("file");
200 while (file)
201 {
202 std::string filename = file->Attribute("filename");
203 file->Clear();
204
205 TiXmlElement *sha1 = new TiXmlElement("sha1");
206
207 ASSERTL0(m_filehash.count(filename) != 0, "Couldn't find file " +
208 filename +
209 " in list of calculated"
210 "hashes");
211
212 sha1->LinkEndChild(new TiXmlText(m_filehash[filename]));
213 file->LinkEndChild(sha1);
214 file = file->NextSiblingElement("file");
215 }
216}
217} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
std::string RegisterCreatorFunction(std::string key, CreatorFunction func)
Definition: Metric.h:138
std::string CalculateHash(std::string filename)
Definition: MetricFile.cpp:83
virtual bool v_Test(std::istream &pStdout, std::istream &pStderr)
Virtual function to test the metric. Should be redefined in derived classes.
Definition: MetricFile.cpp:163
static std::string type
Definition: MetricFile.h:55
MetricFile(TiXmlElement *metric, bool generate)
Definition: MetricFile.cpp:50
std::map< std::string, std::string > m_filehash
Stores filenames to perform hash on.
Definition: MetricFile.h:66
static MetricSharedPtr create(TiXmlElement *metric, bool generate)
Definition: MetricFile.h:50
virtual void v_Generate(std::istream &pStdout, std::istream &pStderr)
Virtual function to generate the metric. Should be redefined in derived classes.
Definition: MetricFile.cpp:185
Base class for all metrics. Metric represents a test metric that can be used to evaluate the function...
Definition: Metric.h:70
TiXmlElement * m_metric
Pointer to XML structure containing metric definition.
Definition: Metric.h:106
bool m_generate
Determines whether to generate this metric or not.
Definition: Metric.h:101
def copy(self)
Definition: pycml.py:2663
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:45
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
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