OpenVDB 12.1.0

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