Skip to content

Commit

Permalink
unsupported int128 tests (#452)
Browse files Browse the repository at this point in the history
* int128 tests added

* fix utils_tests

* fixed template specialization UB, improved randomness
  • Loading branch information
belous-dp committed Apr 2, 2024
1 parent d2bcc20 commit e2e08a0
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 7 deletions.
44 changes: 43 additions & 1 deletion server/src/utils/StringUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ namespace StringUtils {
}

template<>
int stot<>(const std::string& s) {
int stot(const std::string& s) {
return std::stoi(s);
}
template<>
Expand Down Expand Up @@ -203,6 +203,48 @@ namespace StringUtils {
LOG_S(ERROR) << "Wrong bool value: " + s;
throw std::invalid_argument("Wrong bool value: " + s);
}
template<>
__int128 stot(const std::string& s) {
if (s.empty()) {
throw std::invalid_argument("Empty int128");
}
bool neg = s[0] == '-';
size_t pos = (s[0] == '+' || s[0] == '-') ? 1 : 0;
__int128 res = 0;
for (; pos < s.size(); ++pos) {
char d = s[pos];
if (d < '0' || d > '9') {
throw std::invalid_argument("Not an int128: " + s);
}
res *= 10;
if (neg) {
res -= d - '0';
} else {
res += d - '0';
}
}
return res;
}
template<>
unsigned __int128 stot(const std::string& s) {
if (s.empty()) {
throw std::invalid_argument("Empty unsigned int128");
}
if (s[0] == '-') {
throw std::invalid_argument("Signed unsigned int128: " + s);
}
size_t pos = s[0] == '+' ? 1 : 0;
unsigned __int128 res = 0;
for (; pos < s.size(); ++pos) {
char d = s[pos];
if (d < '0' || d > '9') {
throw std::invalid_argument("Not an int128: " + s);
}
res *= 10;
res += d - '0';
}
return res;
}

std::string wrapQuotations(const std::string &s) {
return "\"" + s + "\"";
Expand Down
12 changes: 12 additions & 0 deletions server/src/utils/StringUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ namespace StringUtils {
T stot(const std::string&) {
return T();
}
template<> int stot(const std::string& s);
template<> long stot(const std::string& s);
template<> long long stot(const std::string& s);
template<> unsigned int stot(const std::string& s);
template<> unsigned long stot(const std::string& s);
template<> unsigned long long stot(const std::string& s);
template<> float stot(const std::string& s);
template<> double stot(const std::string& s);
template<> long double stot(const std::string& s);
template<> bool stot(const std::string& s);
template<> __int128 stot(const std::string& s);
template<> unsigned __int128 stot(const std::string& s);

std::string wrapQuotations(const std::string &s);
}
Expand Down
35 changes: 34 additions & 1 deletion server/test/framework/Syntax_Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3658,7 +3658,7 @@ namespace {
checkBitfieldFit<unsigned>(subViews[2], 15) &&
testCase.returnValue.view->getEntryValue(nullptr) == "13";
}
})
})
);
}

Expand Down Expand Up @@ -3703,4 +3703,37 @@ namespace {
return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 42;
}}));
}

TEST_F(Syntax_Test, DISABLED_int128_mult) {
auto [testGen, status] = createTestForFunction(types_c, 120);

ASSERT_TRUE(status.ok()) << status.error_message();

for (const auto &testCase: testGen.tests.at(types_c).methods.begin().value().testCases) {
auto res = StringUtils::stot<unsigned __int128>(
testCase.returnValue.view->getEntryValue(nullptr));
auto a = StringUtils::stot<unsigned long long>(
testCase.paramValues[0].view->getEntryValue(nullptr));
auto b = StringUtils::stot<unsigned long long>(
testCase.paramValues[1].view->getEntryValue(nullptr));
ASSERT_TRUE(res == ~((unsigned __int128) 0) || res == static_cast<unsigned __int128>(a) * b);
}

checkTestCasePredicates(
testGen.tests.at(bitfields_c).methods.begin().value().testCases,
std::vector<TestCasePredicate>(
{
[](const tests::Tests::MethodTestCase &testCase) {
return StringUtils::stot<unsigned __int128>(
testCase.returnValue.view->getEntryValue(nullptr)) ==
~((unsigned __int128) 0);
},
[](const tests::Tests::MethodTestCase &testCase) {
return StringUtils::stot<unsigned __int128>(
testCase.returnValue.view->getEntryValue(nullptr)) !=
~((unsigned __int128) 0);
}
})
);
}
}
29 changes: 24 additions & 5 deletions server/test/framework/Utils_Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@
namespace {
auto projectPath = fs::current_path().parent_path() / testUtils::getRelativeTestSuitePath("server");

TEST(StringUtils_stotInt128, simple) {
__int128 val = 42;
auto res = StringUtils::stot<__int128>("42");
EXPECT_EQ(val, res);
}

TEST(StringUtils_stotInt128, simple_unsigned) {
unsigned __int128 val = 42;
auto res = StringUtils::stot<unsigned __int128>("42");
EXPECT_EQ(val, res);
}

TEST(StringUtils_stotInt128, INT128_MIN) {
__int128 val = 1;
val <<= 127;
auto res = StringUtils::stot<__int128>("-170141183460469231731687303715884105728");
EXPECT_EQ(val, res);
}

TEST(ReadBytesAsValueTest, Unsigned1) {
size_t const LEN = 4;
std::vector<char> bytes(LEN);
Expand Down Expand Up @@ -307,12 +326,12 @@ namespace {

template<typename T>
void readBytesAsValueTestTemplate(T val) {
srand(42);
size_t const len = sizeof(T);
std::default_random_engine gen(42);
for (size_t tcount = 0; tcount < 5; ++tcount) {
auto add = static_cast<size_t>(rand() % 10);
auto start = static_cast<size_t>(rand() % add);
size_t const len = sizeof(T);
std::vector<char> bytes(len + add);
auto extra = static_cast<size_t>(std::uniform_int_distribution<unsigned>(1, 10)(gen));
auto start = static_cast<size_t>(std::uniform_int_distribution<unsigned>(0, extra)(gen));
std::vector<char> bytes(len + extra);
for (size_t i = 1; i <= len; ++i) {
bytes[start + i - 1] = (val >> (CHAR_BIT * (i - 1))) & ((1 << CHAR_BIT) - 1);
}
Expand Down
10 changes: 10 additions & 0 deletions server/test/suites/syntax/types.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "types.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

char a_or_b(char a, char b) {
if (a == 'a') {
Expand Down Expand Up @@ -114,3 +115,12 @@ int structWithConstPointerParam(struct SupportedStruct4 st) {
struct IncompleteType {
char c[100];
};

unsigned __int128 int128_mult(unsigned long long a, unsigned long long b) {
unsigned __int128 mult = a;
mult *= b;
if (mult > (unsigned __int128) LLONG_MAX) {
return ~((unsigned __int128)0);
}
return mult;
}
2 changes: 2 additions & 0 deletions server/test/suites/syntax/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ int void_pointer(void * a);
// This function should be skipped, as structs with unions are not supported.
struct UnsupportedStruct3 structWithUnion(int a);

unsigned __int128 int128_mult(unsigned long long a, unsigned long long b);

#endif //SIMPLE_TEST_PROJECT_OTHER_TYPES_h

0 comments on commit e2e08a0

Please sign in to comment.