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