OpenVDB  10.0.1
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>
15 #include <openvdb_ax/ast/Parse.h>
16 #include <openvdb_ax/ast/Tokens.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  CPPUNIT_ASSERT_MESSAGE(ERROR_MSG("Unexpected parsing error(s)\n", str.str()), tree && !logger.hasError()); \
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  CPPUNIT_ASSERT_MESSAGE(ERROR_MSG("Expected parsing error", code), !tree && logger.hasError()); \
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 
Provides the definition for every abstract and concrete derived class which represent a particular ab...
Parsing methods for creating abstract syntax trees out of AX code.
std::vector< std::pair< std::string, openvdb::ax::ast::Node::Ptr > > CodeTests
Definition: util.h:58
void replace(std::string &str, const std::string &oldStr, const std::string &newStr)
Definition: util.h:65
ValueT value
Definition: GridBuilder.h:1290
Definition: util.h:53
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
Various function and operator tokens used throughout the AST and code generation. ...
std::map< std::string, std::map< std::string, std::string > > ConfigMap
Definition: util.h:60
Various tools which traverse an AX AST and report information back to a std::ostream.
std::vector< std::string > nameSequence(const std::string &base, const size_t number)
Definition: util.h:221
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