Skip to content

Commit 4e4758e

Browse files
committed
Adds the WhenSerialized matcher which replaces SerializesTo and accepts matchers such as Eq and StrContains.
Also added EqSuashingWhitespace to compare strings ignoring differences in whitespace.
1 parent 84bae28 commit 4e4758e

File tree

3 files changed

+135
-54
lines changed

3 files changed

+135
-54
lines changed

src/substrait/textplan/converter/tests/BinaryToTextPlanConversionTest.cpp

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include "substrait/textplan/tests/ParseResultMatchers.h"
99

1010
namespace io::substrait::textplan {
11+
12+
using ::testing::Eq;
13+
1114
namespace {
1215

1316
class TestCase {
@@ -31,15 +34,15 @@ std::vector<TestCase> GetTestCases() {
3134
{
3235
"empty plan",
3336
"",
34-
SerializesTo(""),
37+
WhenSerialized(Eq("")),
3538
},
3639
{
3740
"empty extension space",
3841
R"(extension_uris: {
3942
extension_uri_anchor: 42;
4043
uri: "http://life@everything",
4144
})",
42-
SerializesTo(""),
45+
WhenSerialized(Eq("")),
4346
},
4447
{
4548
"used extension space",
@@ -54,9 +57,10 @@ std::vector<TestCase> GetTestCases() {
5457
name: "sum:fp64_fp64"
5558
}
5659
})",
57-
SerializesTo("extension_space http://life@everything {\n"
58-
" function sum:fp64_fp64 as sum;\n"
59-
"}\n"),
60+
WhenSerialized(EqSquashingWhitespace(
61+
R"(extension_space http://life@everything {
62+
function sum:fp64_fp64 as sum;
63+
})")),
6064
},
6165
{
6266
"seven extensions, no uris",
@@ -109,15 +113,16 @@ std::vector<TestCase> GetTestCases() {
109113
name: "multiply:opt_fp64_fp64"
110114
}
111115
})",
112-
SerializesTo("extension_space {\n"
113-
" function lte:fp64_fp64 as lte;\n"
114-
" function sum:fp64_fp64 as sum;\n"
115-
" function lt:fp64_fp64 as lt;\n"
116-
" function is_not_null:fp64 as is_not_null;\n"
117-
" function and:bool_bool as and;\n"
118-
" function gte:fp64_fp64 as gte;\n"
119-
" function multiply:opt_fp64_fp64 as multiply;\n"
120-
"}\n"),
116+
WhenSerialized(EqSquashingWhitespace(
117+
R"(extension_space {
118+
function lte:fp64_fp64 as lte;
119+
function sum:fp64_fp64 as sum;
120+
function lt:fp64_fp64 as lt;
121+
function is_not_null:fp64 as is_not_null;
122+
function and:bool_bool as and;
123+
function gte:fp64_fp64 as gte;
124+
function multiply:opt_fp64_fp64 as multiply;
125+
})")),
121126
},
122127
{
123128
"read local files",
@@ -140,32 +145,33 @@ std::vector<TestCase> GetTestCases() {
140145
})",
141146
AllOf(
142147
HasSymbols({"local", "read", "root"}),
143-
SerializesTo(
144-
"read relation read {\n"
145-
"}\n"
146-
"\n"
147-
"source local_files local {\n"
148-
" items = [\n"
149-
" {uri_file: \"/mock_lineitem.orc\" start: 0 length: 3719 orc: {}}\n"
150-
" ]\n"
151-
"}\n")),
148+
WhenSerialized(EqSquashingWhitespace(
149+
R"(read relation read {
150+
}
151+
152+
source local_files local {
153+
items = [
154+
{uri_file: "/mock_lineitem.orc" start: 0 length: 3719 orc: {}}
155+
]
156+
})"))),
152157
},
153158
{
154159
"read named table",
155160
"relations: { root: { input: { read: { base_schema {} named_table { names: \"#2\" } } } } }",
156161
AllOf(
157162
HasSymbols({"schema", "named", "read", "root"}),
158-
SerializesTo("read relation read {\n"
159-
"}\n"
160-
"\n"
161-
"schema schema {\n"
162-
"}\n"
163-
"\n"
164-
"source named_table named {\n"
165-
" names = [\n"
166-
" \"#2\",\n"
167-
" ]\n"
168-
"}\n")),
163+
WhenSerialized(EqSquashingWhitespace(
164+
R"(read relation read {
165+
}
166+
167+
schema schema {
168+
}
169+
170+
source named_table named {
171+
names = [
172+
"#2",
173+
]
174+
})"))),
169175
},
170176
{
171177
"single three node pipeline",

src/substrait/textplan/tests/ParseResultMatchers.cpp

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,45 @@ std::vector<std::string> symbolNames(
2525
return names;
2626
}
2727

28+
bool StringEqSquashingWhitespace(
29+
const std::string& have,
30+
const std::string& expected) {
31+
auto atHave = have.begin();
32+
auto atExpected = expected.begin();
33+
while (atHave != have.end() && atExpected != expected.end()) {
34+
if (isspace(*atExpected)) {
35+
if (!isspace(*atHave)) {
36+
return false;
37+
}
38+
// Have a match, consume all remaining space.
39+
do {
40+
atExpected++;
41+
} while (atExpected != expected.end() && isspace(*atExpected));
42+
do {
43+
atHave++;
44+
} while (atHave != have.end() && isspace(*atHave));
45+
continue;
46+
}
47+
if (*atHave != *atExpected) {
48+
return false;
49+
}
50+
atHave++;
51+
atExpected++;
52+
}
53+
// For convenience consume any trailing whitespace on both sides.
54+
if (atExpected != expected.end()) {
55+
do {
56+
atExpected++;
57+
} while (atExpected != expected.end() && isspace(*atExpected));
58+
}
59+
if (atHave != have.end()) {
60+
do {
61+
atHave++;
62+
} while (atHave != have.end() && isspace(*atHave));
63+
}
64+
return atHave == have.end() && atExpected == expected.end();
65+
}
66+
2867
} // namespace
2968

3069
class ParsesOkMatcher {
@@ -117,39 +156,39 @@ ::testing::Matcher<const ParseResult&> HasSymbols(
117156
return HasSymbolsMatcher(std::move(expected_symbols));
118157
}
119158

120-
class SerializesToMatcher {
159+
class WhenSerializedMatcher {
121160
public:
122161
using is_gtest_matcher = void;
123162

124-
explicit SerializesToMatcher(std::string expected_result)
125-
: expected_result_(std::move(expected_result)) {}
163+
explicit WhenSerializedMatcher(
164+
::testing::Matcher<const std::string&> string_matcher)
165+
: string_matcher_(std::move(string_matcher)) {}
126166

127-
bool MatchAndExplain(const ParseResult& result, std::ostream* listener)
128-
const {
167+
bool MatchAndExplain(
168+
const ParseResult& result,
169+
::testing::MatchResultListener* listener) const {
129170
std::string outputText =
130171
SymbolTablePrinter::outputToText(result.getSymbolTable());
131-
if (listener) {
132-
*listener << "has output text \"" << outputText << "\"";
133-
}
134-
return outputText == expected_result_;
172+
return MatchPrintAndExplain(outputText, string_matcher_, listener);
135173
}
136174

137-
void DescribeTo(std::ostream* os) const {
138-
*os << "serializes to: " << ::testing::PrintToString(expected_result_);
175+
void DescribeTo(::std::ostream* os) const {
176+
*os << "matches after serializing ";
177+
string_matcher_.DescribeTo(os);
139178
}
140179

141-
void DescribeNegationTo(std::ostream* os) const {
142-
*os << "does not serialize to: "
143-
<< ::testing::PrintToString(expected_result_);
180+
void DescribeNegationTo(::std::ostream* os) const {
181+
*os << "does not match after serializing ";
182+
string_matcher_.DescribeTo(os);
144183
}
145184

146185
private:
147-
const std::string expected_result_;
186+
::testing::Matcher<const std::string&> string_matcher_;
148187
};
149188

150-
::testing::Matcher<const ParseResult&> SerializesTo(
151-
std::string expected_symbols) {
152-
return SerializesToMatcher(std::move(expected_symbols));
189+
::testing::Matcher<const ParseResult&> WhenSerialized(
190+
::testing::Matcher<const std::string&> string_matcher) {
191+
return WhenSerializedMatcher(std::move(string_matcher));
153192
}
154193

155194
class HasErrorsMatcher {
@@ -183,4 +222,35 @@ ::testing::Matcher<const ParseResult&> HasErrors(
183222
return HasErrorsMatcher(std::move(expected_errors));
184223
}
185224

225+
class EqSquashingWhitespaceMatcher {
226+
public:
227+
using is_gtest_matcher = void;
228+
229+
explicit EqSquashingWhitespaceMatcher(std::string expected_string)
230+
: expected_string_(std::move(expected_string)) {}
231+
232+
bool MatchAndExplain(const std::string& str, std::ostream* /* listener */)
233+
const {
234+
return StringEqSquashingWhitespace(str, expected_string_);
235+
}
236+
237+
void DescribeTo(std::ostream* os) const {
238+
*os << "equals squashing whitespace "
239+
<< ::testing::PrintToString(expected_string_);
240+
}
241+
242+
void DescribeNegationTo(std::ostream* os) const {
243+
*os << "does not equal squashing whitespace "
244+
<< ::testing::PrintToString(expected_string_);
245+
}
246+
247+
private:
248+
std::string expected_string_;
249+
};
250+
251+
::testing::Matcher<const std::string&> EqSquashingWhitespace(
252+
std::string expected_string) {
253+
return EqSquashingWhitespaceMatcher(std::move(expected_string));
254+
}
255+
186256
} // namespace io::substrait::textplan

src/substrait/textplan/tests/ParseResultMatchers.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@ namespace io::substrait::textplan {
1414
[[maybe_unused]] ::testing::Matcher<const ParseResult&> HasSymbols(
1515
std::vector<std::string> expected_symbols);
1616

17-
[[maybe_unused]] ::testing::Matcher<const ParseResult&> SerializesTo(
18-
std::string expected_result);
17+
[[maybe_unused]] ::testing::Matcher<const ParseResult&> WhenSerialized(
18+
::testing::Matcher<const std::string&> string_matcher);
1919

2020
[[maybe_unused]] ::testing::Matcher<const ParseResult&> HasErrors(
2121
std::vector<std::string> expected_errors);
2222

23+
// Matches strings ignoring differences in kinds of whitespace (as long as they
24+
// are present) and ignoring trailing whitespace as well.
25+
[[maybe_unused]] ::testing::Matcher<const std::string&> EqSquashingWhitespace(
26+
std::string expected_string);
27+
2328
} // namespace io::substrait::textplan

0 commit comments

Comments
 (0)