1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2024-10-18 00:16:11 -04:00

fromYAML tests

cleanup test logic

don't ignore whole classes of tests
This commit is contained in:
Philipp Otterbein 2024-09-17 14:47:14 +02:00
parent 4e2c061983
commit 2cd714432f
3 changed files with 469 additions and 385 deletions

View file

@ -20,6 +20,24 @@ for f in "$1"/src/*.yaml; do
testname="$(basename ${f} .yaml)" testname="$(basename ${f} .yaml)"
echo "static constexpr std::string_view T_${testname} = R\"RAW(" echo "static constexpr std::string_view T_${testname} = R\"RAW("
cat ${f} cat ${f}
case $testname in
4ABK)
cat << EOL
json: |
{
"unquoted": "separate",
"http://foo.com": null,
"omitted value": null
}
EOL
;;
SM9W)
# not JSON compatible due to null key
echo " fail: true"
;;
*)
;;
esac
echo ")RAW\";" echo ")RAW\";"
echo echo
done done
@ -29,15 +47,30 @@ echo
echo "namespace nix {" echo "namespace nix {"
for f in "$1"/src/*.yaml; do for f in "$1"/src/*.yaml; do
testname="$(basename ${f} .yaml)" testname="$(basename ${f} .yaml)"
[[ "${testname}" = "2SXE" ]] && echo " /** This test case is ignored because the YAML string is parsed incorrectly by ryml, but it's a rather artificial case, which isn't valid YAML 1.3 either." ignore="false"
skip="false"
case $testname in
H7TQ | MUS6 | ZYU8)
echo " /** This test is ignored because these tests are not required to fail and rapidyaml ignores the YAML version string."
ignore="true"
;;
3HFZ | 4EJS | 5TRB | 5U3A | 7LBH | 9C9N | 9MQT | CVW2 | CXX2 | D49Q | DK4H | DK95 | G5U8 | JKF3 | N782 | QB6E | QLJ7 | RXY3 | S4GJ | S98Z | SY6V | VJP3 | X4QW | Y79Y | YJV2 | ZCZ6 | ZL4Z | ZXT5 | 3HFZ | 4EJS | 5TRB | 5U3A | 7LBH | 9C9N | 9MQT | CVW2 | CXX2 | D49Q | DK4H | DK95 | G5U8 | JKF3 | N782 | QB6E | QLJ7 | RXY3 | S4GJ | S98Z | SY6V | VJP3 | X4QW | Y79Y | YJV2 | ZCZ6 | ZL4Z | ZXT5)
skip="true"
;;
*)
;;
esac
echo " TEST_F(${testclass}, T_${testname}) {" echo " TEST_F(${testclass}, T_${testname}) {"
if [ "${testname}" = "565N" ]; then if [ "${testname}" = "565N" ]; then
echo " ASSERT_THROW(${testmethod}(T_${testname}),EvalError); // nix has no binary data type" echo " ASSERT_THROW(${testmethod}(T_${testname}),EvalError); // nix has no binary data type"
else else
echo " ASSERT_EQ(${testmethod}(T_${testname}),\"OK\");" if [ "${skip}" = "true" ]; then
echo " GTEST_SKIP() << \"Reason: Invalid yaml is parsed successfully\";"
fi
echo " ${testmethod}(T_${testname});"
fi fi
echo " }" echo " }"
[[ "${testname}" = "2SXE" ]] && echo " */" [[ "${ignore}" = "true" ]] && echo " */"
echo echo
done done
echo "} /* namespace nix */" echo "} /* namespace nix */"

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
#ifdef HAVE_RYML #ifdef HAVE_RYML
#include "libexpr.hh" #include "libexpr.hh"
#include "primops.hh"
// Ugly, however direct access to the SAX parser is required in order to parse multiple JSON objects from a stream // Ugly, however direct access to the SAX parser is required in order to parse multiple JSON objects from a stream
#include "json-to-value.cc" #include "json-to-value.cc"
@ -9,6 +10,7 @@
namespace nix { namespace nix {
// Testing the conversion from YAML // Testing the conversion from YAML
/* replacement of non-ascii unicode characters, which indicate the presence of certain characters that would be otherwise hard to read */
static std::string replaceUnicodePlaceholders(std::string_view str) { static std::string replaceUnicodePlaceholders(std::string_view str) {
constexpr std::string_view eop("\xe2\x88\x8e"); constexpr std::string_view eop("\xe2\x88\x8e");
constexpr std::string_view filler{"\xe2\x80\x94"}; constexpr std::string_view filler{"\xe2\x80\x94"};
@ -91,17 +93,24 @@ namespace nix {
class FromYAMLTest : public LibExprTest { class FromYAMLTest : public LibExprTest {
protected: protected:
std::string execYAMLTest(std::string_view test) { void execYAMLTest(std::string_view test) {
const PrimOpFun fromYAML = state.getBuiltin("fromYAML").primOp->fun; //const PrimOpFun fromYAML = state.getBuiltin("fromYAML").primOp->fun;
PrimOpFun fromYAML = nullptr;
for (const auto & primOp : *RegisterPrimOp::primOps) {
if (primOp.name == "__fromYAML") {
fromYAML = primOp.fun;
}
}
EXPECT_FALSE(fromYAML == nullptr) << "The experimental feature \"fromYAML\" is not available";
Value testCases, testVal; Value testCases, testVal;
Value *pTestVal = &testVal; Value *pTestVal = &testVal;
testVal.mkString(test); testVal.mkString(test);
fromYAML(state, noPos, &pTestVal, testCases); fromYAML(state, noPos, &pTestVal, testCases);
int ctr = -1; size_t ctr = 0;
std::string_view testName;
Value *json = nullptr;
for (auto testCase : testCases.listItems()) { for (auto testCase : testCases.listItems()) {
Value *json = nullptr;
bool fail = false; bool fail = false;
ctr++;
std::string_view yamlRaw; std::string_view yamlRaw;
for (auto attr = testCase->attrs->begin(); attr != testCase->attrs->end(); attr++) { for (auto attr = testCase->attrs->begin(); attr != testCase->attrs->end(); attr++) {
auto name = state.symbols[attr->name]; auto name = state.symbols[attr->name];
@ -111,44 +120,47 @@ namespace nix {
yamlRaw = state.forceStringNoCtx(*attr->value, noPos, "while interpreting the \"yaml\" field as string"); yamlRaw = state.forceStringNoCtx(*attr->value, noPos, "while interpreting the \"yaml\" field as string");
} else if (name == "fail") { } else if (name == "fail") {
fail = state.forceBool(*attr->value, noPos, "while interpreting the \"fail\" field as bool"); fail = state.forceBool(*attr->value, noPos, "while interpreting the \"fail\" field as bool");
} else if (name == "name") {
testName = state.forceStringNoCtx(*attr->value, noPos, "while interpreting the \"name\" field as string");
} }
} }
fail |= !json; // extract expected result
bool emptyJSON = false;
std::string_view jsonStr;
Value jsonVal; Value jsonVal;
bool nullJSON = json && json->type() == nNull;
bool emptyJSON = !nullJSON;
if (json && !nullJSON) {
std::string_view jsonStr = state.forceStringNoCtx(*json, noPos, "while interpreting the \"json\" field as string");
emptyJSON = jsonStr.empty();
if (!emptyJSON) {
jsonVal = parseJSONStream(state, jsonStr, fromYAML);
jsonStr = printValue(state, jsonVal);
}
}
// extract the YAML to be parsed
std::string yamlStr = replaceUnicodePlaceholders(yamlRaw); std::string yamlStr = replaceUnicodePlaceholders(yamlRaw);
Value yaml, yamlVal; Value yaml, yamlVal;
Value *pYaml = &yaml; Value *pYaml = &yaml;
yaml.mkString(yamlStr); yaml.mkString(yamlStr);
if (!fail) { if (!fail) {
if (json->type() == nNull) { if (emptyJSON) {
jsonStr = "null"; EXPECT_THROW(
jsonVal.mkNull(); fromYAML(state, noPos, &pYaml, yamlVal),
EvalError) << "Testcase #" << ctr << ": Expected empty YAML, which should throw an exception, parsed \"" << printValue(state, yamlVal) << "\":\n" << yamlRaw;
} else { } else {
jsonStr = state.forceStringNoCtx(*json, noPos, "while interpreting the \"json\" field as string");
}
if (!(emptyJSON = jsonStr.empty())) {
if (json->type() != nNull) {
jsonVal = parseJSONStream(state, jsonStr, fromYAML);
jsonStr = printValue(state, jsonVal);
}
fromYAML(state, noPos, &pYaml, yamlVal); fromYAML(state, noPos, &pYaml, yamlVal);
EXPECT_EQ(printValue(state, yamlVal), printValue(state, jsonVal)) << "Testcase[" + std::to_string(ctr) + "]: Parsed YAML does not match expected JSON result"; if (nullJSON) {
EXPECT_TRUE(yamlVal.type() == nNull) << "Testcase #" << ctr << ": Expected null YAML:\n" << yamlStr;
} else {
EXPECT_EQ(printValue(state, yamlVal), printValue(state, jsonVal)) << "Testcase #" << ctr << ": Parsed YAML does not match expected JSON result:\n" << yamlRaw;
}
} }
} else {
EXPECT_THROW(
fromYAML(state, noPos, &pYaml, yamlVal),
EvalError) << "Testcase #" << ctr << " (" << testName << "): Parsing YAML has to throw an exception, but \"" << printValue(state, yamlVal) << "\" was parsed:\n" << yamlRaw;
} }
if (fail || emptyJSON) { ctr++;
try {
fromYAML(state, noPos, &pYaml, yamlVal); // should throw exception, if fail is asserted, and has to throw, if emptyJSON is asserted
} catch (const EvalError &e) {
continue;
}
}
EXPECT_FALSE(emptyJSON) << "Testcase[" + std::to_string(ctr) + "]: Parsing empty YAML has to fail";
// ryml parses some invalid YAML successfully
// EXPECT_FALSE(fail) << "Testcase[" << ctr << "]: Invalid YAML was parsed successfully";
} }
return "OK";
} }
}; };