Dune Core Modules (unstable)

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
18#include <dune/common/test/testsuite.hh>
19
20#include <Python.h>
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
49inline int runPython(const std::string &code)
50{
51#if (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION >= 8)
52 PyConfig config;
53 PyConfig_InitPythonConfig(&config);
54 PyConfig_SetString(&config, &config.program_name, PYTHON_INTERPRETER);
55 PyStatus status = Py_InitializeFromConfig(&config);
56 PyConfig_Clear(&config);
57 if (PyStatus_Exception(status)) {
58 Py_ExitStatusException(status);
59 return PyStatus_IsExit(status) ? status.exitcode : EXIT_FAILURE;
60 }
61#else
62 Py_SetProgramName(PYTHON_INTERPRETER);
63 Py_Initialize();
64#endif
65
66 int exitcode = PyRun_SimpleString(code.c_str());
67 int finalizecode = Py_FinalizeEx();
68 return (exitcode + finalizecode) ? EXIT_FAILURE : EXIT_SUCCESS;
69}
70
71inline bool is_suffix(const std::string &s, const std::string &suffix)
72{
73 return s.size() >= suffix.size() &&
74 s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
75}
76
77inline bool havePythonVTK()
78{
79 static const bool result = [] {
80 // This check is invoked only once, even in a multithreading environment,
81 // since it is invoked in the initializer of a static variable.
82 if(runPython("from vtk import *") == EXIT_SUCCESS)
83 return true;
84 std::cerr << "warning: python or python vtk module not available. This "
85 << "will result in skipped tests, since we cannot check that "
86 << "vtk can read the files we wrote." << std::endl;
87 return false;
88 } ();
89
90 return result;
91}
92
93inline std::string pythonVTKReader(const std::string& filename)
94{
95 if (is_suffix(filename, ".vtu")) return "vtkXMLUnstructuredGridReader";
96 else if(is_suffix(filename, ".pvtu")) return "vtkXMLPUnstructuredGridReader";
97 else if(is_suffix(filename, ".vtp")) return "vtkXMLPolyDataReader";
98 else if(is_suffix(filename, ".pvtp")) return "vtkXMLPPolyDataReader";
100 "Unknown vtk file extension: " << filename);
101}
102
103} /* namespace Impl */
104
105class VTKChecker
106{
107public:
108 void push(const std::string& file)
109 {
110 auto res = files_.insert(file);
111 if (not res.second) {
112 testSuite_.check(false, "VTKChecker")
113 << "'" << file << "' was added multiple times";
114 }
115 }
116
117 int check()
118 {
119 if (not Impl::havePythonVTK()) {
120 return 77;
121 }
122 else if (not files_.empty()) {
123 const int result = Impl::runPython(generatePythonCode());
124 testSuite_.check(result == EXIT_SUCCESS);
125 }
126 return testSuite_.exit();
127 }
128
129 const TestSuite& testSuite() const
130 {
131 return testSuite_;
132 }
133
134private:
135 std::string generatePythonCode() const
136 {
137 std::stringstream code;
138
139 code << "from vtk import *\n"
140 << "import sys\n"
141 << "passed = True\n";
142
143 for (const auto& file : files_) {
144 code << "reader = " << Impl::pythonVTKReader(file) << "()\n"
145 << "reader.SetFileName('" << Impl::pyq(file) << "')\n"
146 << "reader.Update()\n"
147 << "if (not (reader.GetOutput().GetNumberOfCells() > 0)):\n"
148 << " print('ERROR in {}'.format('" << Impl::pyq(file) << "'))\n"
149 << " passed = False\n";
150 }
151
152 code << "sys.exit(0 if passed else 1)\n";
153
154 return code.str();
155 }
156
157 std::set< std::string > files_;
158 TestSuite testSuite_;
159};
160
161} /* namespace Dune */
162
163#endif // DUNE_GRID_IO_FILE_TEST_CHECKVTKFILE_HH
Default exception for dummy implementations.
Definition: exceptions.hh:355
A few common exception classes.
#define DUNE_THROW(E,...)
Definition: exceptions.hh:312
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 22, 23:30, 2024)