DUNE PDELab (2.8)

checkvtkfile.hh
1#ifndef DUNE_GRID_IO_FILE_TEST_CHECKVTKFILE_HH
2#define DUNE_GRID_IO_FILE_TEST_CHECKVTKFILE_HH
3
4#include <cstddef>
5#include <cstdlib>
6#include <iostream>
7#include <iomanip>
8#include <ios>
9#include <iostream>
10#include <ostream>
11#include <set>
12#include <sstream>
13#include <string>
14
15#include <sys/wait.h>
16
18#include <dune/common/test/testsuite.hh>
19
20namespace Dune {
21
22namespace Impl {
23
24// quote so the result can be used inside '...' in python
25// quotes not included in the result
26inline std::string pyq(const std::string &s)
27{
28 std::ostringstream result;
29 for(std::size_t i = 0; i < s.size(); ++i)
30 {
31 char c = s[i];
32 switch(c) {
33 case '\'': result << "\\'"; break;
34 case '\\': result << "\\\\"; break;
35 case '\n': result << "\\n"; break;
36 default:
37 if(c < 32 || c >= 127)
38 result << "\\x" << std::hex << std::setfill('0') << std::setw(2)
39 << static_cast<int>(c);
40 else
41 result << c;
42 }
43 }
44 return result.str();
45}
46
47// quote so the result can be used inside '...' in the bourne shell
48// quotes not included in the result
49inline std::string shq(const std::string &s)
50{
51 std::ostringstream result;
52 bool pend = false;
53 for(std::size_t i = 0; i < s.size(); ++i)
54 {
55 char c = s[i];
56 switch(c) {
58 "Can't pass \\0 through the shell");
59 case '\'': result << (pend ? "" : "'") << "\\'"; pend = true; break;
60 default: result << (pend ? "'" : "") << c; pend = false; break;
61 }
62 }
63 if(pend) result << "'";
64 return result.str();
65}
66
67inline int runShell(const std::string &code)
68{
69 int result = std::system(code.c_str());
70 // Avoid returning anything that is a multiple of 256, unless the return
71 // value was 0. This way the return value can be directly used as an
72 // argument to exit(), which usually interprets its argument modulo 256.
73 if(WIFEXITED(result))
74 return WEXITSTATUS(result);
75 if(WIFSIGNALED(result))
76 return WTERMSIG(result) + 256;
77 else
78 return 513;
79}
80
81inline int runPython(const std::string &code)
82{
83 return runShell("python3 -c '"+shq(code)+"'");
84}
85
86inline bool is_suffix(const std::string &s, const std::string &suffix)
87{
88 return s.size() >= suffix.size() &&
89 s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
90}
91
92inline bool havePythonVTK()
93{
94 static const bool result = [] {
95 // This check is invoked only once, even in a multithreading environment,
96 // since it is invoked in the initializer of a static variable.
97 if(runPython("from vtk import *") == 0)
98 return true;
99 std::cerr << "warning: python or python vtk module not available. This "
100 << "will result in skipped tests, since we cannot check that "
101 << "vtk can read the files we wrote." << std::endl;
102 return false;
103 } ();
104
105 return result;
106}
107
108inline std::string pythonVTKReader(const std::string& filename)
109{
110 if (is_suffix(filename, ".vtu")) return "vtkXMLUnstructuredGridReader";
111 else if(is_suffix(filename, ".pvtu")) return "vtkXMLPUnstructuredGridReader";
112 else if(is_suffix(filename, ".vtp")) return "vtkXMLPolyDataReader";
113 else if(is_suffix(filename, ".pvtp")) return "vtkXMLPPolyDataReader";
115 "Unknown vtk file extension: " << filename);
116}
117
118} /* namespace Impl */
119
120class VTKChecker
121{
122public:
123 void push(const std::string& file)
124 {
125 auto res = files_.insert(file);
126 if (not res.second) {
127 testSuite_.check(false, "VTKChecker")
128 << "'" << file << "' was added multiple times";
129 }
130 }
131
132 int check()
133 {
134 if (not Impl::havePythonVTK()) {
135 return 77;
136 }
137 else if (not files_.empty()) {
138 const int result = Impl::runPython(generatePythonCode());
139 testSuite_.check(result == 0);
140 }
141 return testSuite_.exit();
142 }
143
144 const TestSuite& testSuite() const
145 {
146 return testSuite_;
147 }
148
149private:
150 std::string generatePythonCode() const
151 {
152 std::stringstream code;
153
154 code << "from vtk import *\n"
155 << "import sys\n"
156 << "passed = True\n";
157
158 for (const auto& file : files_) {
159 code << "reader = " << Impl::pythonVTKReader(file) << "()\n"
160 << "reader.SetFileName('" << Impl::pyq(file) << "')\n"
161 << "reader.Update()\n"
162 << "if (not (reader.GetOutput().GetNumberOfCells() > 0)):\n"
163 << " print('ERROR in {}'.format('" << Impl::pyq(file) << "'))\n"
164 << " passed = False\n";
165 }
166
167 code << "sys.exit(0 if passed else 1)\n";
168
169 return code.str();
170 }
171
172 std::set< std::string > files_;
173 TestSuite testSuite_;
174};
175
176} /* namespace Dune */
177
178#endif // DUNE_GRID_IO_FILE_TEST_CHECKVTKFILE_HH
Default exception for dummy implementations.
Definition: exceptions.hh:261
A few common exception classes.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
Dune namespace.
Definition: alignedallocator.hh:11
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 22, 23:30, 2024)