OpenVDB: util.h Source File

OpenVDB 8.0.0

util.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
9
10 #ifndef OPENVDB_AX_UNITTEST_UTIL_HAS_BEEN_INCLUDED
11 #define OPENVDB_AX_UNITTEST_UTIL_HAS_BEEN_INCLUDED
12
13 #include <openvdb_ax/ast/AST.h>
14 #include <openvdb_ax/ast/Parse.h>
15 #include <openvdb_ax/ast/Tokens.h>
16 #include <openvdb_ax/compiler/Logger.h>
17
18 #include <openvdb/Types.h>
19
20 #include <memory>
21 #include <vector>
22 #include <utility>
23 #include <string>
24 #include <type_traits>
25
26 #define ERROR_MSG(Msg, Code) Msg + std::string(": \"") + Code + std::string("\"")
27
28 #define TEST_SYNTAX_PASSES(Tests) \
29 { \
30 openvdb::ax::Logger logger;\
31 for (const auto& test : Tests) { \
32 logger.clear();\
33 const std::string& code = test.first; \
34 openvdb::ax::ast::Tree::ConstPtr tree = openvdb::ax::ast::parse(code.c_str(), logger);\
35 std::stringstream str; \
36 CPPUNIT_ASSERT_MESSAGE(ERROR_MSG("Unexpected parsing error(s)\n", str.str()), tree); \
37 } \
38 } \
39
40 #define TEST_SYNTAX_FAILS(Tests) \
41 { \
42 openvdb::ax::Logger logger([](const std::string&) {});\
43 for (const auto& test : Tests) { \
44 logger.clear();\
45 const std::string& code = test.first; \
46 openvdb::ax::ast::Tree::ConstPtr tree = openvdb::ax::ast::parse(code.c_str(), logger);\
47 CPPUNIT_ASSERT_MESSAGE(ERROR_MSG("Expected parsing error", code), logger.hasError()); \
48 } \
49 } \
50
51 namespace unittest_util
52 {
53 // Use shared pointers rather than unique pointers so initializer lists can easily
54 // be used. Could easily introduce some move semantics to work around this if
55 // necessary.
56 using CodeTests = std::vector<std::pair<std::string, openvdb::ax::ast::Node::Ptr>>;
57
58 //
59
60 // Find + Replace all string helper
61 inline void replace(std::string& str, const std::string& oldStr, const std::string& newStr)
62 {
63 std::string::size_type pos = 0u;
64 while ((pos = str.find(oldStr, pos)) != std::string::npos) {
65 str.replace(pos, oldStr.length(), newStr);
66 pos += newStr.length();
67 }
68 }
69
70 //
71
72 inline bool compareLinearTrees(const std::vector<const openvdb::ax::ast::Node*>& a,
73 const std::vector<const openvdb::ax::ast::Node*>& b, const bool allowEmpty = false)
74 {
75 if (!allowEmpty && (a.empty() || b.empty())) return false;
76 if (a.size() != b.size()) return false;
77 const size_t size = a.size();
78 for (size_t i = 0; i < size; ++i) {
79 if ((a[i] == nullptr) ^ (b[i] == nullptr)) return false;
80 if (a[i] == nullptr) continue;
81 if (a[i]->nodetype() != b[i]->nodetype()) return false;
82
83 // Specific handling of various node types to compare child data
84 // @todo generalize this
85 // @note Value methods does not compare child text data
86
87 if (a[i]->nodetype() == openvdb::ax::ast::Node::AssignExpressionNode) {
88 if (static_cast<const openvdb::ax::ast::AssignExpression*>(a[i])->operation() !=
89 static_cast<const openvdb::ax::ast::AssignExpression*>(b[i])->operation()) {
90 return false;
91 }
92 }
93 else if (a[i]->nodetype() == openvdb::ax::ast::Node::BinaryOperatorNode) {
94 if (static_cast<const openvdb::ax::ast::BinaryOperator*>(a[i])->operation() !=
95 static_cast<const openvdb::ax::ast::BinaryOperator*>(b[i])->operation()) {
96 return false;
97 }
98 }
99 else if (a[i]->nodetype() == openvdb::ax::ast::Node::CrementNode) {
100 if (static_cast<const openvdb::ax::ast::Crement*>(a[i])->operation() !=
101 static_cast<const openvdb::ax::ast::Crement*>(b[i])->operation()) {
102 return false;
103 }
104 if (static_cast<const openvdb::ax::ast::Crement*>(a[i])->post() !=
105 static_cast<const openvdb::ax::ast::Crement*>(b[i])->post()) {
106 return false;
107 }
108 }
109 else if (a[i]->nodetype() == openvdb::ax::ast::Node::CastNode) {
110 if (static_cast<const openvdb::ax::ast::Cast*>(a[i])->type() !=
111 static_cast<const openvdb::ax::ast::Cast*>(b[i])->type()) {
112 return false;
113 }
114 }
115 else if (a[i]->nodetype() == openvdb::ax::ast::Node::FunctionCallNode) {
116 if (static_cast<const openvdb::ax::ast::FunctionCall*>(a[i])->name() !=
117 static_cast<const openvdb::ax::ast::FunctionCall*>(b[i])->name()) {
118 return false;
119 }
120 }
121 else if (a[i]->nodetype() == openvdb::ax::ast::Node::LoopNode) {
122 if (static_cast<const openvdb::ax::ast::Loop*>(a[i])->loopType() !=
123 static_cast<const openvdb::ax::ast::Loop*>(b[i])->loopType()) {
124 return false;
125 }
126 }
127 else if (a[i]->nodetype() == openvdb::ax::ast::Node::KeywordNode) {
128 if (static_cast<const openvdb::ax::ast::Keyword*>(a[i])->keyword() !=
129 static_cast<const openvdb::ax::ast::Keyword*>(b[i])->keyword()) {
130 return false;
131 }
132 }
133 else if (a[i]->nodetype() == openvdb::ax::ast::Node::AttributeNode) {
134 if (static_cast<const openvdb::ax::ast::Attribute*>(a[i])->type() !=
135 static_cast<const openvdb::ax::ast::Attribute*>(b[i])->type()) {
136 return false;
137 }
138 if (static_cast<const openvdb::ax::ast::Attribute*>(a[i])->name() !=
139 static_cast<const openvdb::ax::ast::Attribute*>(b[i])->name()) {
140 return false;
141 }
142 if (static_cast<const openvdb::ax::ast::Attribute*>(a[i])->inferred() !=
143 static_cast<const openvdb::ax::ast::Attribute*>(b[i])->inferred()) {
144 return false;
145 }
146 }
147 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ExternalVariableNode) {
148 if (static_cast<const openvdb::ax::ast::ExternalVariable*>(a[i])->type() !=
149 static_cast<const openvdb::ax::ast::ExternalVariable*>(b[i])->type()) {
150 return false;
151 }
152 if (static_cast<const openvdb::ax::ast::ExternalVariable*>(a[i])->name() !=
153 static_cast<const openvdb::ax::ast::ExternalVariable*>(b[i])->name()) {
154 return false;
155 }
156 }
157 else if (a[i]->nodetype() == openvdb::ax::ast::Node::DeclareLocalNode) {
158 if (static_cast<const openvdb::ax::ast::DeclareLocal*>(a[i])->type() !=
159 static_cast<const openvdb::ax::ast::DeclareLocal*>(b[i])->type()) {
160 return false;
161 }
162 }
163 else if (a[i]->nodetype() == openvdb::ax::ast::Node::LocalNode) {
164 if (static_cast<const openvdb::ax::ast::Local*>(a[i])->name() !=
165 static_cast<const openvdb::ax::ast::Local*>(b[i])->name()) {
166 return false;
167 }
168 }
169 // @note Value methods does not compare child text data
170 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ValueBoolNode) {
171 if (static_cast<const openvdb::ax::ast::Value<bool>*>(a[i])->value() !=
172 static_cast<const openvdb::ax::ast::Value<bool>*>(b[i])->value()) {
173 return false;
174 }
175 }
176 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ValueInt16Node) {
177 if (static_cast<const openvdb::ax::ast::Value<int16_t>*>(a[i])->value() !=
178 static_cast<const openvdb::ax::ast::Value<int16_t>*>(b[i])->value()) {
179 return false;
180 }
181 }
182 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ValueInt32Node) {
183 if (static_cast<const openvdb::ax::ast::Value<int32_t>*>(a[i])->value() !=
184 static_cast<const openvdb::ax::ast::Value<int32_t>*>(b[i])->value()) {
185 return false;
186 }
187 }
188 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ValueInt64Node) {
189 if (static_cast<const openvdb::ax::ast::Value<int64_t>*>(a[i])->value() !=
190 static_cast<const openvdb::ax::ast::Value<int64_t>*>(b[i])->value()) {
191 return false;
192 }
193 }
194 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ValueFloatNode) {
195 if (static_cast<const openvdb::ax::ast::Value<float>*>(a[i])->value() !=
196 static_cast<const openvdb::ax::ast::Value<float>*>(b[i])->value()) {
197 return false;
198 }
199 }
200 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ValueDoubleNode) {
201 if (static_cast<const openvdb::ax::ast::Value<double>*>(a[i])->value() !=
202 static_cast<const openvdb::ax::ast::Value<double>*>(b[i])->value()) {
203 return false;
204 }
205 }
206 else if (a[i]->nodetype() == openvdb::ax::ast::Node::ValueStrNode) {
207 if (static_cast<const openvdb::ax::ast::Value<std::string>*>(a[i])->value() !=
208 static_cast<const openvdb::ax::ast::Value<std::string>*>(b[i])->value()) {
209 return false;
210 }
211 }
212 }
213 return true;
214 }
215
216 inline std::vector<std::string>
217 nameSequence(const std::string& base, const size_t number)
218 {
219 std::vector<std::string> names;
220 if (number <= 0) return names;
221 names.reserve(number);
222
223 for (size_t i = 1; i <= number; i++) {
224 names.emplace_back(base + std::to_string(i));
225 }
226
227 return names;
228 }
229 }
230
231 #endif // OPENVDB_AX_UNITTEST_UTIL_HAS_BEEN_INCLUDED
232
Types.h
unittest_util::compareLinearTrees
bool compareLinearTrees(const std::vector< const openvdb::ax::ast::Node * > &a, const std::vector< const openvdb::ax::ast::Node * > &b, const bool allowEmpty=false)
Definition: util.h:72
Parse.h
Parsing methods for creating abstract syntax trees out of AX code.
unittest_util::replace
void replace(std::string &str, const std::string &oldStr, const std::string &newStr)
Definition: util.h:61
Logger.h
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
Tokens.h
Various function and operator tokens used throughout the AST and code generation.
unittest_util::CodeTests
std::vector< std::pair< std::string, openvdb::ax::ast::Node::Ptr > > CodeTests
Definition: util.h:56
unittest_util
Definition: util.h:52
unittest_util::nameSequence
std::vector< std::string > nameSequence(const std::string &base, const size_t number)
Definition: util.h:217
AST.h
Provides the definition for every abstract and concrete derived class which represent a particular ab...