diff options
| author | Yong He <yonghe@outlook.com> | 2021-09-24 11:33:44 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-09-24 11:33:44 -0700 |
| commit | bec8e6aec85b6e3f875c58bdd59eb15613978358 (patch) | |
| tree | 0791fb2ce1be786c17e5a6ee489ed3065fc07332 /tools/slang-unit-test/unit-test-string.cpp | |
| parent | f2a3c933bc11a498c622fa18694c84beca8ca031 (diff) | |
Move existing unit tests to a standalone dll. (#1945)
Diffstat (limited to 'tools/slang-unit-test/unit-test-string.cpp')
| -rw-r--r-- | tools/slang-unit-test/unit-test-string.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/tools/slang-unit-test/unit-test-string.cpp b/tools/slang-unit-test/unit-test-string.cpp new file mode 100644 index 000000000..629ed2373 --- /dev/null +++ b/tools/slang-unit-test/unit-test-string.cpp @@ -0,0 +1,262 @@ +// unit-test-path.cpp + +#include "../../source/core/slang-string-util.h" + +#include "tools/unit-test/slang-unit-test.h" + +//#include <math.h> + +#include <sstream> + +using namespace Slang; + +static bool _areEqual(const List<UnownedStringSlice>& lines, const UnownedStringSlice* checkLines, Int checkLinesCount) +{ + if (checkLinesCount != lines.getCount()) + { + return false; + } + + for (Int i = 0; i < checkLinesCount; ++i) + { + if (lines[i] != checkLines[i]) + { + return false; + } + } + return true; +} + +static bool _checkLines(const UnownedStringSlice& input, const UnownedStringSlice* checkLines, Int checkLinesCount) +{ + List<UnownedStringSlice> lines; + StringUtil::calcLines(input, lines); + return _areEqual(lines, checkLines, checkLinesCount); +} + +static bool _checkLineParser(const UnownedStringSlice& input) +{ + UnownedStringSlice remaining(input), line; + for (const auto parserLine : LineParser(input)) + { + if (!StringUtil::extractLine(remaining, line) || line != parserLine) + { + return false; + } + } + return StringUtil::extractLine(remaining, line) == false; +} + +static void _append(double v, StringBuilder& buf) +{ + std::ostringstream stream; + stream.imbue(std::locale::classic()); + stream.setf(std::ios::fixed, std::ios::floatfield); + stream.precision(20); + + stream << std::scientific << v; + + buf << stream.str().c_str(); +} + +// Unit of least precision +static int64_t _calcULPDistance(double a, double b) +{ + // Save work if the floats are equal. + // Also handles +0 == -0 + if (a == b) + { + return 0; + } + + const int64_t max = int64_t((~uint64_t(0)) >> 1); + +#if 0 + // Max distance for NaN + if (isnan(a) || isnan(b)) + { + return max; + } + + // If one's infinite and they're not equal, max distance. + if (isinf(a) || isinf(b)) + { + return max; + } +#endif + + int64_t ia, ib; + memcpy(&ia, &a, sizeof(a)); + memcpy(&ib, &b, sizeof(b)); + + // Don't compare differently-signed floats. + if ((ia < 0) != (ib < 0)) + { + return max; + } + + // Return the absolute value of the distance in ULPs. + int64_t distance = ia - ib; + return distance < 0 ? -distance : distance; +} + +static bool _areApproximatelyEqual(double a, double b, double fixedEpsilon = 1e-10, int ulpsEpsilon = 100) +{ + // Handle the near-zero case. + const double difference = abs(a - b); + if (difference <= fixedEpsilon) + { + return true; + } + + return _calcULPDistance(a, b) <= ulpsEpsilon; +} + +SLANG_UNIT_TEST(string) +{ + { + UnownedStringSlice checkLines[] = { UnownedStringSlice::fromLiteral("") }; + SLANG_CHECK(_checkLines(UnownedStringSlice::fromLiteral(""), checkLines, SLANG_COUNT_OF(checkLines))); + } + { + // Will emit no lines + SLANG_CHECK(_checkLines(UnownedStringSlice(nullptr, nullptr), nullptr, 0)); + } + { + // Two lines - both empty + UnownedStringSlice checkLines[] = { UnownedStringSlice(), UnownedStringSlice()}; + SLANG_CHECK(_checkLines(UnownedStringSlice::fromLiteral("\n"), checkLines, SLANG_COUNT_OF(checkLines))); + } + { + UnownedStringSlice checkLines[] = { UnownedStringSlice::fromLiteral("Hello"), UnownedStringSlice::fromLiteral("World!") }; + SLANG_CHECK(_checkLines(UnownedStringSlice::fromLiteral("Hello\nWorld!"), checkLines, SLANG_COUNT_OF(checkLines))); + } + { + UnownedStringSlice checkLines[] = { UnownedStringSlice::fromLiteral("Hello"), UnownedStringSlice::fromLiteral("World!"), UnownedStringSlice() }; + SLANG_CHECK(_checkLines(UnownedStringSlice::fromLiteral("Hello\n\rWorld!\n"), checkLines, SLANG_COUNT_OF(checkLines))); + } + + { + SLANG_CHECK(_checkLineParser(UnownedStringSlice::fromLiteral("Hello\n\rWorld!\n"))); + SLANG_CHECK(_checkLineParser(UnownedStringSlice::fromLiteral("\n"))); + SLANG_CHECK(_checkLineParser(UnownedStringSlice::fromLiteral(""))); + } + { + Int value; + SLANG_CHECK(SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("-10"), value)) && value == -10); + SLANG_CHECK(SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("0"), value)) && value == 0); + SLANG_CHECK(SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("-0"), value)) && value == 0); + + SLANG_CHECK(SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("13824"), value)) && value == 13824); + SLANG_CHECK(SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("-13824"), value)) && value == -13824); + } + + { + UnownedStringSlice values[] = { UnownedStringSlice("hello"), UnownedStringSlice("world"), UnownedStringSlice("!") }; + ArrayView<UnownedStringSlice> valuesView(values, SLANG_COUNT_OF(values)); + + List<UnownedStringSlice> checkValues; + StringBuilder builder; + + { + builder.Clear(); + StringUtil::join(values, 0, ',', builder); + SLANG_CHECK(builder == ""); + } + + { + builder.Clear(); + StringUtil::join(values, 1, ',', builder); + SLANG_CHECK(builder == "hello"); + + StringUtil::split(builder.getUnownedSlice(), ',', checkValues); + SLANG_CHECK(checkValues.getArrayView() == ArrayView<UnownedStringSlice>(values, 1)); + } + + { + builder.Clear(); + StringUtil::join(values, 2, ',', builder); + SLANG_CHECK(builder == "hello,world"); + + StringUtil::split(builder.getUnownedSlice(), ',', checkValues); + SLANG_CHECK(checkValues.getArrayView() == ArrayView<UnownedStringSlice>(values, 2)); + } + + { + builder.Clear(); + StringUtil::join(values, 3, UnownedStringSlice("ab"), builder); + SLANG_CHECK(builder == "helloabworldab!"); + + StringUtil::split(builder.getUnownedSlice(), UnownedStringSlice("ab"), checkValues); + SLANG_CHECK(checkValues.getArrayView() == ArrayView<UnownedStringSlice>(values, 3)); + } + } + { + + List<double> values; + values.add(0.0); + values.add(-0.0); + + for (Index i = -300; i < 300; ++i) + { + double value = pow(10, i); + + values.add(value); + values.add(-value); + + values.addRange(value / 3); + values.addRange(-value / 3); + } + + StringBuilder buf; + + for (auto value : values) + { + buf.Clear(); + _append(value, buf); + + UnownedStringSlice slice = buf.getUnownedSlice(); + + double parsedValue; + SlangResult res = StringUtil::parseDouble(slice, parsedValue); + + auto ulpsParsed = _calcULPDistance(value, parsedValue); + + SLANG_CHECK(SLANG_SUCCEEDED(res)); + + // Check that they are equal + SLANG_CHECK(_areApproximatelyEqual(value, parsedValue)); + } + } + { + List<int64_t> values; + values.add(0); + + for (Index i = 0; i < 63; ++i) + { + auto value = int64_t(1) << i; + + values.add(value); + values.add(-value); + } + + StringBuilder buf; + + for (auto value : values) + { + buf.Clear(); + buf << value; + + + int64_t parsedValue; + + UnownedStringSlice slice = buf.getUnownedSlice(); + SlangResult res = StringUtil::parseInt64(slice, parsedValue); + + SLANG_CHECK(SLANG_SUCCEEDED(res)); + + // Check that they are equal + SLANG_CHECK(value == parsedValue); + } + } +} |
