Skip to content

Commit 43f806d

Browse files
committed
Additional Strutil tests (AcademySoftwareFoundation#3655)
Better coverage of edge cases for escape_chars/unescape_chars, stoi hex conversion, strtod, stod, freestanding c_str(), parse_nested failure cases, base64_encode, debug.
1 parent 30571a0 commit 43f806d

File tree

5 files changed

+62
-15
lines changed

5 files changed

+62
-15
lines changed

.github/workflows/analysis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ on:
1515
branches:
1616
- master
1717
- '*analysis*'
18+
- '*sonar*'
1819
# Allow manual kicking off of the workflow from github.com
1920
workflow_dispatch:
2021
# Uncomment the following line if we want to run analysis on all PRs:

src/libutil/strutil.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ Strutil::escape_chars(string_view unescaped)
352352
case '\r': c = 'r'; break;
353353
case '\f': c = 'f'; break;
354354
case '\a': c = 'a'; break;
355+
default: break;
355356
}
356357
s.insert(i, 1, c);
357358
}
@@ -379,10 +380,8 @@ Strutil::unescape_chars(string_view escaped)
379380
case 'b': s[i] = '\b'; break;
380381
case 'r': s[i] = '\r'; break;
381382
case 'f': s[i] = '\f'; break;
382-
case 'a':
383-
s[i] = '\a';
384-
break;
385-
// default case: the deletion is enough (backslash and quote)
383+
case 'a': s[i] = '\a'; break;
384+
default: break; // the deletion is enough (backslash and quote)
386385
}
387386
} else if (c >= '0' && c < '8') {
388387
// up to 3 octal digits
@@ -1615,7 +1614,6 @@ Strutil::strtod(const char* nptr, char** endptr) noexcept
16151614
// Can use strtod_l on platforms that support it
16161615
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) \
16171616
|| defined(__FreeBSD_kernel__) || defined(__GLIBC__)
1618-
// static initialization inside function is thread-safe by C++11 rules!
16191617
return strtod_l(nptr, endptr, c_loc);
16201618
#elif defined(_WIN32)
16211619
// Windows has _strtod_l
@@ -1695,7 +1693,7 @@ Strutil::stof(string_view s, size_t* pos)
16951693
// will use the "short string optimization", meaning that this string
16961694
// creation will NOT need an allocation/free for most strings we expect
16971695
// to hold a text representation of a float.
1698-
return Strutil::stof(std::string(s).c_str(), pos);
1696+
return Strutil::stof(std::string(s), pos);
16991697
}
17001698

17011699

src/libutil/strutil_test.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,9 @@ test_escape(string_view raw, string_view escaped)
305305
void
306306
test_escape_sequences()
307307
{
308-
test_escape ("\\ \n \r \t", "\\\\ \\n \\r \\t");
308+
test_escape ("\\ \n \r \t \v \b \f \a", "\\\\ \\n \\r \\t \\v \\b \\f \\a");
309309
test_escape (" \"quoted\" ", " \\\"quoted\\\" ");
310+
OIIO_CHECK_EQUAL(Strutil::unescape_chars("A\\023B"), "A\023B");
310311
}
311312

312313

@@ -852,6 +853,7 @@ test_numeric_conversion()
852853
std::numeric_limits<int>::max());
853854
OIIO_CHECK_EQUAL(Strutil::stoi("-12345678901234567890"),
854855
std::numeric_limits<int>::min());
856+
OIIO_CHECK_EQUAL(Strutil::stoi("0x100", nullptr, 16), 256); // hex
855857

856858
OIIO_CHECK_EQUAL(Strutil::stoui("hi"), 0);
857859
OIIO_CHECK_EQUAL(Strutil::stoui(" "), 0);
@@ -921,6 +923,22 @@ test_numeric_conversion()
921923
OIIO_CHECK_EQUAL (Strutil::stof("100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E-200"), 1.0f);
922924
OIIO_CHECK_EQUAL (Strutil::stof("0.00000000000000000001"), 1.0e-20f);
923925

926+
OIIO_CHECK_EQUAL(Strutil::strtod("314.25"), 314.25);
927+
OIIO_CHECK_EQUAL(Strutil::strtod("hi"), 0.0);
928+
929+
pos = 100;
930+
OIIO_CHECK_EQUAL(Strutil::stod(string_view("314.25"), &pos), 314.25);
931+
OIIO_CHECK_EQUAL(pos, 6);
932+
pos = 100;
933+
OIIO_CHECK_EQUAL(Strutil::stod("hi", &pos), 0.0);
934+
OIIO_CHECK_EQUAL(pos, 0);
935+
pos = 100;
936+
OIIO_CHECK_EQUAL(Strutil::stod("", &pos), 0.0);
937+
OIIO_CHECK_EQUAL(pos, 0);
938+
pos = 100;
939+
OIIO_CHECK_EQUAL(Strutil::stod(nullptr, &pos), 0.0);
940+
OIIO_CHECK_EQUAL(pos, 0);
941+
924942
// Note: we don't test from_strings<> separately because it's just
925943
// implemented directly as calls to stoi, stoui, stof.
926944

@@ -1249,6 +1267,17 @@ test_string_view()
12491267
// not horribly broken.
12501268
wstring_view wsv;
12511269
OIIO_CHECK_ASSERT(wsv == wsv);
1270+
1271+
// Test the freestanding OIIO::c_str() function
1272+
OIIO_CHECK_EQUAL(OIIO::c_str(""), std::string());
1273+
OIIO_CHECK_EQUAL(OIIO::c_str(cstr), cstr);
1274+
OIIO_CHECK_EQUAL(OIIO::c_str(s), s);
1275+
OIIO_CHECK_EQUAL(OIIO::c_str(ustring(cstr)), ustring(cstr));
1276+
OIIO_CHECK_EQUAL(OIIO::c_str(sr), sr);
1277+
OIIO_CHECK_EQUAL(OIIO::c_str(string_view(sr.data(), 2)), std::string("01"));
1278+
Strutil::print("addr cstr={:p}, s={:p}, ustring={:p}, sr={:p}, c_str(sr)={:p}\n",
1279+
(void*)cstr, (void*)s.c_str(), (void*)ustring(cstr).c_str(), (void*)sr.data(),
1280+
(void*)c_str(sr));
12521281
}
12531282

12541283

@@ -1412,8 +1441,16 @@ void test_parse ()
14121441

14131442
s = "[a([b]c)]x]"; ss = parse_nested (s);
14141443
OIIO_CHECK_EQUAL (ss, "[a([b]c)]"); OIIO_CHECK_EQUAL (s, "x]");
1415-
s = "[a([b]c)]x]"; ss = parse_nested (s, false);
1444+
s = "[a([b]c)]x]"; ss = parse_nested (s, false); // no eating
14161445
OIIO_CHECK_EQUAL (ss, "[a([b]c)]"); OIIO_CHECK_EQUAL (s, "[a([b]c)]x]");
1446+
s = "([a([b]c)])x]"; ss = parse_nested (s);
1447+
OIIO_CHECK_EQUAL (ss, "([a([b]c)])"); OIIO_CHECK_EQUAL (s, "x]");
1448+
s = "blah[a([b]c)]x]"; ss = parse_nested (s);
1449+
OIIO_CHECK_EQUAL (ss, ""); OIIO_CHECK_EQUAL (s, "blah[a([b]c)]x]");
1450+
s = ""; ss = parse_nested (s);
1451+
OIIO_CHECK_EQUAL (ss, ""); OIIO_CHECK_EQUAL (s, "");
1452+
s = "(blah"; ss = parse_nested (s);
1453+
OIIO_CHECK_EQUAL (ss, ""); OIIO_CHECK_EQUAL (s, "(blah");
14171454
}
14181455

14191456

@@ -1581,6 +1618,14 @@ test_edit_distance()
15811618

15821619

15831620

1621+
void
1622+
test_base64_encode()
1623+
{
1624+
OIIO_CHECK_EQUAL(Strutil::base64_encode("foo123,()"), "Zm9vMTIzLCgp");
1625+
}
1626+
1627+
1628+
15841629
int
15851630
main(int /*argc*/, char* /*argv*/[])
15861631
{
@@ -1615,6 +1660,9 @@ main(int /*argc*/, char* /*argv*/[])
16151660
test_string_compare_function();
16161661
test_datetime();
16171662
test_edit_distance();
1663+
test_base64_encode();
1664+
1665+
Strutil::debug("debug message\n");
16181666

16191667
return unit_test_failures;
16201668
}

src/libutil/ustring.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -600,15 +600,15 @@ ustring::concat(string_view s, string_view t)
600600
std::string
601601
ustring::getstats(bool verbose)
602602
{
603-
UstringTable& table(ustring_table());
604603
std::ostringstream out;
605604
out.imbue(std::locale::classic()); // Force "C" locale with '.' decimal
606-
size_t n_e = table.get_num_entries();
607-
size_t mem = table.get_memory_usage();
605+
size_t n_e = total_ustrings();
606+
size_t mem = memory();
608607
if (verbose) {
609608
out << "ustring statistics:\n";
610609
#ifdef USTRING_TRACK_NUM_LOOKUPS
611-
out << " ustring requests: " << table.get_num_lookups() << "\n";
610+
out << " ustring requests: " << ustring_table().get_num_lookups()
611+
<< "\n";
612612
#endif
613613
out << " unique strings: " << n_e << "\n";
614614
out << " ustring memory: " << Strutil::memformat(mem) << "\n";
@@ -623,7 +623,7 @@ ustring::getstats(bool verbose)
623623
#endif
624624
} else {
625625
#ifdef USTRING_TRACK_NUM_LOOKUPS
626-
out << "requests: " << table.get_num_lookups() << ", ";
626+
out << "requests: " << ustring_table().get_num_lookups() << ", ";
627627
#endif
628628
out << "unique " << n_e << ", " << Strutil::memformat(mem);
629629
}

src/libutil/ustring_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ test_ustring()
143143
// make_unique, is_unique, from_unique
144144
const char* foostr = foo.c_str();
145145
OIIO_CHECK_EQUAL(ustring::make_unique("foo"), foostr);
146+
OIIO_CHECK_EQUAL(ustring::make_unique(string_view()), ustring());
146147
OIIO_CHECK_EQUAL(ustring::is_unique(foostr), true);
147148
OIIO_CHECK_EQUAL(ustring::is_unique("foo"), false);
148149
OIIO_CHECK_EQUAL(ustring::from_unique(foostr), foo);
@@ -292,8 +293,7 @@ main(int argc, char* argv[])
292293
benchmark_threaded_ustring_creation();
293294
verify_no_collisions();
294295

295-
if (verbose)
296-
std::cout << "\n" << ustring::getstats() << "\n";
296+
std::cout << "\n" << ustring::getstats(true) << "\n";
297297

298298
return unit_test_failures;
299299
}

0 commit comments

Comments
 (0)