OpenVDB 9.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
4/// @file test/util.h
5///
6/// @author Nick Avramoussis
7///
8/// @brief Test utilities
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>
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
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.
56using CodeTests = std::vector<std::pair<std::string, openvdb::ax::ast::Node::Ptr>>;
57
58//
59
60// Find + Replace all string helper
61inline 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
72inline 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
216inline std::vector<std::string>
217nameSequence(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
Provides the definition for every abstract and concrete derived class which represent a particular ab...
ValueT value
Definition: GridBuilder.h:1287
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
Parsing methods for creating abstract syntax trees out of AX code.
Various function and operator tokens used throughout the AST and code generation.
Definition: util.h:52
void replace(std::string &str, const std::string &oldStr, const std::string &newStr)
Definition: util.h:61
std::vector< std::string > nameSequence(const std::string &base, const size_t number)
Definition: util.h:217
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
std::vector< std::pair< std::string, openvdb::ax::ast::Node::Ptr > > CodeTests
Definition: util.h:56