Fix mbrtoc32 test for musl and glibc.

glibc and musl both interpreted the spec differently than we did
(better, imo) for the return value of a zero-length conversion. Fix
the test to handle that.

Also converted the test from ASSERT to EXPECT to reduce the number of
builds needed to find failures.

Bug: None
Test: ./tests/run-on-host.sh glibc --gtest_filter="uchar.*"
Change-Id: Id74364040ce3b0e21bacd78f70467053cc8a6058
This commit is contained in:
Dan Albert 2023-07-18 22:21:36 +00:00
parent b88a23ec58
commit 0b8fbdf4b3

View file

@ -304,46 +304,86 @@ TEST(uchar, mbrtoc32_out_of_range) {
TEST(uchar, mbrtoc32) {
char32_t out[8];
// C23 says:
//
// Returns:
//
// 0 if the next n or fewer bytes complete the multibyte character that
// corresponds to the null wide character (which is the value stored).
//
// (size_t)(-2) if the next n bytes contribute to an incomplete (but
// potentially valid) multibyte character, and all n bytes have been
// processed (no value is stored).
//
// Bionic historically interpreted the behavior when n is 0 to be the next 0
// bytes decoding to the null. That's a pretty bad interpretation, and both
// glibc and musl return -2 for that case.
//
// The test currently checks the incorrect behavior for bionic because gtest
// doesn't support explicit xfail annotations. The behavior difference here
// should be fixed, but danalbert wants to add more tests before tackling the
// bugs.
#ifdef __ANDROID__
const size_t expected_result_for_zero_length = 0U;
#else
const size_t expected_result_for_zero_length = static_cast<size_t>(-2);
#endif
out[0] = L'x';
ASSERT_EQ(0U, mbrtoc32(out, "hello", 0, nullptr));
ASSERT_EQ(static_cast<char32_t>(L'x'), out[0]);
EXPECT_EQ(expected_result_for_zero_length, mbrtoc32(out, "hello", 0, nullptr));
EXPECT_EQ(static_cast<char32_t>(L'x'), out[0]);
ASSERT_EQ(0U, mbrtoc32(out, "hello", 0, nullptr));
ASSERT_EQ(0U, mbrtoc32(out, "", 0, nullptr));
ASSERT_EQ(1U, mbrtoc32(out, "hello", 1, nullptr));
ASSERT_EQ(static_cast<char32_t>(L'h'), out[0]);
EXPECT_EQ(expected_result_for_zero_length, mbrtoc32(out, "hello", 0, nullptr));
EXPECT_EQ(expected_result_for_zero_length, mbrtoc32(out, "", 0, nullptr));
EXPECT_EQ(1U, mbrtoc32(out, "hello", 1, nullptr));
EXPECT_EQ(static_cast<char32_t>(L'h'), out[0]);
ASSERT_EQ(0U, mbrtoc32(nullptr, "hello", 0, nullptr));
ASSERT_EQ(0U, mbrtoc32(nullptr, "", 0, nullptr));
ASSERT_EQ(1U, mbrtoc32(nullptr, "hello", 1, nullptr));
EXPECT_EQ(expected_result_for_zero_length, mbrtoc32(nullptr, "hello", 0, nullptr));
EXPECT_EQ(expected_result_for_zero_length, mbrtoc32(nullptr, "", 0, nullptr));
EXPECT_EQ(1U, mbrtoc32(nullptr, "hello", 1, nullptr));
ASSERT_EQ(0U, mbrtoc32(nullptr, nullptr, 0, nullptr));
EXPECT_EQ(0U, mbrtoc32(nullptr, nullptr, 0, nullptr));
ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
uselocale(LC_GLOBAL_LOCALE);
// 1-byte UTF-8.
ASSERT_EQ(1U, mbrtoc32(out, "abcdef", 6, nullptr));
ASSERT_EQ(static_cast<char32_t>(L'a'), out[0]);
EXPECT_EQ(1U, mbrtoc32(out, "abcdef", 6, nullptr));
EXPECT_EQ(static_cast<char32_t>(L'a'), out[0]);
// 2-byte UTF-8.
ASSERT_EQ(2U, mbrtoc32(out, "\xc2\xa2" "cdef", 6, nullptr));
ASSERT_EQ(static_cast<char32_t>(0x00a2), out[0]);
EXPECT_EQ(2U, mbrtoc32(out,
"\xc2\xa2"
"cdef",
6, nullptr));
EXPECT_EQ(static_cast<char32_t>(0x00a2), out[0]);
// 3-byte UTF-8.
ASSERT_EQ(3U, mbrtoc32(out, "\xe2\x82\xac" "def", 6, nullptr));
ASSERT_EQ(static_cast<char32_t>(0x20ac), out[0]);
EXPECT_EQ(3U, mbrtoc32(out,
"\xe2\x82\xac"
"def",
6, nullptr));
EXPECT_EQ(static_cast<char32_t>(0x20ac), out[0]);
// 4-byte UTF-8.
ASSERT_EQ(4U, mbrtoc32(out, "\xf0\xa4\xad\xa2" "ef", 6, nullptr));
ASSERT_EQ(static_cast<char32_t>(0x24b62), out[0]);
EXPECT_EQ(4U, mbrtoc32(out,
"\xf0\xa4\xad\xa2"
"ef",
6, nullptr));
EXPECT_EQ(static_cast<char32_t>(0x24b62), out[0]);
#if defined(__BIONIC__) // glibc allows this.
// Illegal 5-byte UTF-8.
errno = 0;
ASSERT_EQ(static_cast<size_t>(-1), mbrtoc32(out, "\xf8\xa1\xa2\xa3\xa4" "f", 6, nullptr));
ASSERT_EQ(EILSEQ, errno);
EXPECT_EQ(static_cast<size_t>(-1), mbrtoc32(out,
"\xf8\xa1\xa2\xa3\xa4"
"f",
6, nullptr));
EXPECT_EQ(EILSEQ, errno);
#endif
// Illegal over-long sequence.
errno = 0;
ASSERT_EQ(static_cast<size_t>(-1), mbrtoc32(out, "\xf0\x82\x82\xac" "ef", 6, nullptr));
ASSERT_EQ(EILSEQ, errno);
EXPECT_EQ(static_cast<size_t>(-1), mbrtoc32(out,
"\xf0\x82\x82\xac"
"ef",
6, nullptr));
EXPECT_EQ(EILSEQ, errno);
}
void test_mbrtoc32_incomplete(mbstate_t* ps) {