DUNE PDELab (git)

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