Skip to content

Commit e2e08a0

Browse files
authored
unsupported int128 tests (#452)
* int128 tests added * fix utils_tests * fixed template specialization UB, improved randomness
1 parent d2bcc20 commit e2e08a0

File tree

6 files changed

+125
-7
lines changed

6 files changed

+125
-7
lines changed

server/src/utils/StringUtils.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ namespace StringUtils {
158158
}
159159

160160
template<>
161-
int stot<>(const std::string& s) {
161+
int stot(const std::string& s) {
162162
return std::stoi(s);
163163
}
164164
template<>
@@ -203,6 +203,48 @@ namespace StringUtils {
203203
LOG_S(ERROR) << "Wrong bool value: " + s;
204204
throw std::invalid_argument("Wrong bool value: " + s);
205205
}
206+
template<>
207+
__int128 stot(const std::string& s) {
208+
if (s.empty()) {
209+
throw std::invalid_argument("Empty int128");
210+
}
211+
bool neg = s[0] == '-';
212+
size_t pos = (s[0] == '+' || s[0] == '-') ? 1 : 0;
213+
__int128 res = 0;
214+
for (; pos < s.size(); ++pos) {
215+
char d = s[pos];
216+
if (d < '0' || d > '9') {
217+
throw std::invalid_argument("Not an int128: " + s);
218+
}
219+
res *= 10;
220+
if (neg) {
221+
res -= d - '0';
222+
} else {
223+
res += d - '0';
224+
}
225+
}
226+
return res;
227+
}
228+
template<>
229+
unsigned __int128 stot(const std::string& s) {
230+
if (s.empty()) {
231+
throw std::invalid_argument("Empty unsigned int128");
232+
}
233+
if (s[0] == '-') {
234+
throw std::invalid_argument("Signed unsigned int128: " + s);
235+
}
236+
size_t pos = s[0] == '+' ? 1 : 0;
237+
unsigned __int128 res = 0;
238+
for (; pos < s.size(); ++pos) {
239+
char d = s[pos];
240+
if (d < '0' || d > '9') {
241+
throw std::invalid_argument("Not an int128: " + s);
242+
}
243+
res *= 10;
244+
res += d - '0';
245+
}
246+
return res;
247+
}
206248

207249
std::string wrapQuotations(const std::string &s) {
208250
return "\"" + s + "\"";

server/src/utils/StringUtils.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ namespace StringUtils {
8787
T stot(const std::string&) {
8888
return T();
8989
}
90+
template<> int stot(const std::string& s);
91+
template<> long stot(const std::string& s);
92+
template<> long long stot(const std::string& s);
93+
template<> unsigned int stot(const std::string& s);
94+
template<> unsigned long stot(const std::string& s);
95+
template<> unsigned long long stot(const std::string& s);
96+
template<> float stot(const std::string& s);
97+
template<> double stot(const std::string& s);
98+
template<> long double stot(const std::string& s);
99+
template<> bool stot(const std::string& s);
100+
template<> __int128 stot(const std::string& s);
101+
template<> unsigned __int128 stot(const std::string& s);
90102

91103
std::string wrapQuotations(const std::string &s);
92104
}

server/test/framework/Syntax_Tests.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3658,7 +3658,7 @@ namespace {
36583658
checkBitfieldFit<unsigned>(subViews[2], 15) &&
36593659
testCase.returnValue.view->getEntryValue(nullptr) == "13";
36603660
}
3661-
})
3661+
})
36623662
);
36633663
}
36643664

@@ -3703,4 +3703,37 @@ namespace {
37033703
return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 42;
37043704
}}));
37053705
}
3706+
3707+
TEST_F(Syntax_Test, DISABLED_int128_mult) {
3708+
auto [testGen, status] = createTestForFunction(types_c, 120);
3709+
3710+
ASSERT_TRUE(status.ok()) << status.error_message();
3711+
3712+
for (const auto &testCase: testGen.tests.at(types_c).methods.begin().value().testCases) {
3713+
auto res = StringUtils::stot<unsigned __int128>(
3714+
testCase.returnValue.view->getEntryValue(nullptr));
3715+
auto a = StringUtils::stot<unsigned long long>(
3716+
testCase.paramValues[0].view->getEntryValue(nullptr));
3717+
auto b = StringUtils::stot<unsigned long long>(
3718+
testCase.paramValues[1].view->getEntryValue(nullptr));
3719+
ASSERT_TRUE(res == ~((unsigned __int128) 0) || res == static_cast<unsigned __int128>(a) * b);
3720+
}
3721+
3722+
checkTestCasePredicates(
3723+
testGen.tests.at(bitfields_c).methods.begin().value().testCases,
3724+
std::vector<TestCasePredicate>(
3725+
{
3726+
[](const tests::Tests::MethodTestCase &testCase) {
3727+
return StringUtils::stot<unsigned __int128>(
3728+
testCase.returnValue.view->getEntryValue(nullptr)) ==
3729+
~((unsigned __int128) 0);
3730+
},
3731+
[](const tests::Tests::MethodTestCase &testCase) {
3732+
return StringUtils::stot<unsigned __int128>(
3733+
testCase.returnValue.view->getEntryValue(nullptr)) !=
3734+
~((unsigned __int128) 0);
3735+
}
3736+
})
3737+
);
3738+
}
37063739
}

server/test/framework/Utils_Tests.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@
1515
namespace {
1616
auto projectPath = fs::current_path().parent_path() / testUtils::getRelativeTestSuitePath("server");
1717

18+
TEST(StringUtils_stotInt128, simple) {
19+
__int128 val = 42;
20+
auto res = StringUtils::stot<__int128>("42");
21+
EXPECT_EQ(val, res);
22+
}
23+
24+
TEST(StringUtils_stotInt128, simple_unsigned) {
25+
unsigned __int128 val = 42;
26+
auto res = StringUtils::stot<unsigned __int128>("42");
27+
EXPECT_EQ(val, res);
28+
}
29+
30+
TEST(StringUtils_stotInt128, INT128_MIN) {
31+
__int128 val = 1;
32+
val <<= 127;
33+
auto res = StringUtils::stot<__int128>("-170141183460469231731687303715884105728");
34+
EXPECT_EQ(val, res);
35+
}
36+
1837
TEST(ReadBytesAsValueTest, Unsigned1) {
1938
size_t const LEN = 4;
2039
std::vector<char> bytes(LEN);
@@ -307,12 +326,12 @@ namespace {
307326

308327
template<typename T>
309328
void readBytesAsValueTestTemplate(T val) {
310-
srand(42);
329+
size_t const len = sizeof(T);
330+
std::default_random_engine gen(42);
311331
for (size_t tcount = 0; tcount < 5; ++tcount) {
312-
auto add = static_cast<size_t>(rand() % 10);
313-
auto start = static_cast<size_t>(rand() % add);
314-
size_t const len = sizeof(T);
315-
std::vector<char> bytes(len + add);
332+
auto extra = static_cast<size_t>(std::uniform_int_distribution<unsigned>(1, 10)(gen));
333+
auto start = static_cast<size_t>(std::uniform_int_distribution<unsigned>(0, extra)(gen));
334+
std::vector<char> bytes(len + extra);
316335
for (size_t i = 1; i <= len; ++i) {
317336
bytes[start + i - 1] = (val >> (CHAR_BIT * (i - 1))) & ((1 << CHAR_BIT) - 1);
318337
}

server/test/suites/syntax/types.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "types.h"
22
#include <stdio.h>
33
#include <stdlib.h>
4+
#include <limits.h>
45

56
char a_or_b(char a, char b) {
67
if (a == 'a') {
@@ -114,3 +115,12 @@ int structWithConstPointerParam(struct SupportedStruct4 st) {
114115
struct IncompleteType {
115116
char c[100];
116117
};
118+
119+
unsigned __int128 int128_mult(unsigned long long a, unsigned long long b) {
120+
unsigned __int128 mult = a;
121+
mult *= b;
122+
if (mult > (unsigned __int128) LLONG_MAX) {
123+
return ~((unsigned __int128)0);
124+
}
125+
return mult;
126+
}

server/test/suites/syntax/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ int void_pointer(void * a);
6161
// This function should be skipped, as structs with unions are not supported.
6262
struct UnsupportedStruct3 structWithUnion(int a);
6363

64+
unsigned __int128 int128_mult(unsigned long long a, unsigned long long b);
65+
6466
#endif //SIMPLE_TEST_PROJECT_OTHER_TYPES_h

0 commit comments

Comments
 (0)