Initial import

This commit is contained in:
Justine Tunney 2020-06-15 07:18:57 -07:00
commit c91b3c5006
14915 changed files with 590219 additions and 0 deletions

View file

@ -0,0 +1,50 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dce.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#define FANATICS "Fanatics"
static const char hyperion[] =
FANATICS " have their dreams, wherewith they weave / "
"A paradise for a sect; the savage too / "
"From forth the loftiest fashion of his sleep / "
"...";
TEST(crc32c, test) {
EXPECT_EQ(0, crc32c(0, "", 0));
EXPECT_EQ(crc32c(0, "hello", 5), crc32c(0, "hello", 5));
EXPECT_EQ(0xe3069283, crc32c(0, "123456789", 9));
EXPECT_EQ(0x6d6eefba, crc32c(0, hyperion, strlen(hyperion)));
EXPECT_EQ(0x6d6eefba, crc32c(crc32c(0, FANATICS, strlen(FANATICS)),
hyperion + strlen(FANATICS),
strlen(hyperion) - strlen(FANATICS)));
}
uint32_t crc32c$pure(uint32_t, const char *, size_t) hidden;
uint32_t crc32c$sse42(uint32_t, const char *, size_t) hidden;
FIXTURE(crc32c, pure) { *(void **)(&crc32c) = (void *)crc32c$pure; }
FIXTURE(crc32c, sse42) {
if (X86_HAVE(SSE4_2)) {
*(void **)(&crc32c) = (void *)crc32c$sse42;
}
}

View file

@ -0,0 +1,50 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(getutf16, testNul) {
wint_t wc;
EXPECT_EQ(1, getutf16(u"", &wc));
EXPECT_EQ('\0', wc);
EXPECT_EQ(1, (getutf16)(u"", &wc));
EXPECT_EQ('\0', wc);
}
TEST(getutf16, testBasic) {
wint_t wc;
EXPECT_EQ(1, getutf16(u"h", &wc));
EXPECT_EQ('h', wc);
EXPECT_EQ(1, (getutf16)(u"h", &wc));
EXPECT_EQ('h', wc);
}
TEST(getutf16, testAegeanNumberSupplementaryPlane) {
wint_t wc;
EXPECT_EQ(4, tpdecode("𐄷", &wc));
EXPECT_EQ(4, tpdecode("\xF0\x90\x84\xB7", &wc));
EXPECT_EQ(0x10137, wc);
EXPECT_EQ(2, strlen16(u"𐄷"));
EXPECT_EQ(2, getutf16(u"𐄷", &wc));
EXPECT_EQ(0x10137, wc);
EXPECT_EQ(2, (getutf16)(u"𐄷", &wc));
EXPECT_EQ(0x10137, wc);
}

View file

@ -0,0 +1,43 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/hyperion.h"
#include "libc/testlib/testlib.h"
#if 0
void *isnotplaintext(const void *, size_t)
__attribute__((__pure__, __leaf__, __nothrow__));
#endif
TEST(isnotplaintext, test) {
EXPECT_EQ(NULL, isnotplaintext(kHyperion, kHyperionSize));
EXPECT_STREQ("", isnotplaintext(kHyperion, kHyperionSize + 1));
}
char *doit(char *data, size_t size) {
data = isnotplaintext(data, size);
asm volatile("" : "+r"(data));
return data;
}
BENCH(isnotplaintext, bench) {
EZBENCH(donothing, doit(kHyperion, kHyperionSize));
}

View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(memccpy, testStringCopy) {
char buf[16];
EXPECT_EQ(buf + 3, memccpy(buf, "hi", '\0', sizeof(buf)));
EXPECT_STREQ("hi", buf);
}
TEST(memccpy, testOverflow) {
char buf[1];
EXPECT_EQ(NULL, memccpy(buf, "hi", '\0', sizeof(buf)));
}
TEST(memccpy, testZeroLength_doesNothing) {
char buf[1];
EXPECT_EQ(NULL, memccpy(buf, "hi", '\0', 0));
}

View file

@ -0,0 +1,83 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(memcpy, memcpy) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
ASSERT_EQ(b1, memcpy(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
}
}
TEST(memcpy, memcpyDirect) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
ASSERT_EQ(b1, (memcpy)(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
}
}
TEST(memcpy, mempcpy) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
ASSERT_EQ(b1 + n, mempcpy(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
}
}
TEST(memcpy, mempcpyDirect) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
ASSERT_EQ(b1 + n, (mempcpy)(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
}
}
TEST(memcpy, overlapping_isFineIfCopyingBackwards) {
for (size_t i = 0; i < 32; ++i) {
char *b1 = tmalloc(64 + i);
char *b2 = tmalloc(64 + i);
memcpy(b1, b2, 64);
memcpy(b1, b1 + i, 64 - i);
memmove(b2, b2 + i, 64 - i);
ASSERT_EQ(0, memcmp(b1, b2, 64));
tfree(b2);
tfree(b1);
}
}

View file

@ -0,0 +1,29 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(memfrob, test) {
char buf[6];
EXPECT_STREQ("*****", memfrob(memcpy(buf, "\0\0\0\0\0", 6), 5));
EXPECT_STREQ("BOFFE", memfrob(strcpy(buf, "hello"), 5));
EXPECT_STREQ("hello", memfrob(memfrob(strcpy(buf, "hello"), 5), 5));
}

View file

@ -0,0 +1,56 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#define N 256
#define S 7
TEST(memmove, overlapping) {
for (size_t i = 0; i < N; i += S) {
for (size_t j = 10; j < N; j += S) {
char *b1 = tmalloc(N);
char *b2 = tmalloc(N);
size_t n = min(N - i, N - j);
memcpy(b2, b1 + i, n);
ASSERT_EQ(b1 + j, memmove(b1 + j, b1 + i, n));
ASSERT_EQ(0, memcmp(b1 + j, b2, n));
tfree(b2);
tfree(b1);
}
}
}
TEST(memmove, overlappingDirect) {
for (size_t i = 0; i < N; i += S) {
for (size_t j = 10; j < N; j += S) {
char *b1 = tmalloc(N);
char *b2 = tmalloc(N);
size_t n = min(N - i, N - j);
memcpy(b2, b1 + i, n);
ASSERT_EQ(b1 + j, (memmove)(b1 + j, b1 + i, n));
ASSERT_EQ(0, memcmp(b1 + j, b2, n));
tfree(b2);
tfree(b1);
}
}
}

View file

@ -0,0 +1,76 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#include "libc/unicode/unicode.h"
unsigned n;
size_t size;
wchar_t *str;
char16_t *b, *buf;
TEST(pututf16, testEmpty) {
EXPECT_EQ(0, pututf16(NULL, 0, u'j', false));
EXPECT_EQ(0, (pututf16)(NULL, 0, u'j', false));
}
TEST(pututf16, testNul) {
size = 1;
buf = tmalloc(size * sizeof(char16_t));
EXPECT_EQ(1, pututf16(buf, size, u'\0', false));
EXPECT_EQ(u'\0', buf[0]);
buf[0] = '\7';
EXPECT_EQ(1, (pututf16)(buf, size, u'\0', false));
EXPECT_EQ(u'\0', buf[0]);
tfree(buf);
}
TEST(pututf16, testAscii) {
size = 1;
buf = tmalloc(size * sizeof(char16_t));
EXPECT_EQ(1, pututf16(buf, size, u'j', false));
EXPECT_EQ(u'j', buf[0]);
EXPECT_EQ(1, (pututf16)(buf, size, u't', false));
EXPECT_EQ(u't', buf[0]);
tfree(buf);
}
TEST(pututf16, testGothicSupplementaryPlane) {
size = 2;
buf = tmalloc(size * sizeof(char16_t));
EXPECT_EQ(2, pututf16(buf, size, L'𐌰', false));
EXPECT_STREQN(u"𐌰", buf, 1);
EXPECT_EQ(2, (pututf16)(buf, size, L'𐌱', false));
EXPECT_STREQN(u"𐌱", buf, 1);
tfree(buf);
}
TEST(pututf16, testEmojiAndEmojiPresentationModifier_areBothInAstralPlanes) {
n = 8;
b = tgc(tmalloc(sizeof(char16_t) * n));
str = L"\U0001F466\U0001F3FF";
memset(b, 0, n * sizeof(char16_t));
EXPECT_EQ(2, pututf16(b, n, str[0], false));
EXPECT_BINEQ(u"=╪f▄    ", b);
memset(b, 0, n * sizeof(char16_t));
EXPECT_EQ(2, pututf16(b, n, str[1], false));
EXPECT_BINEQ(u"<╪λ▀    ", b);
}

View file

@ -0,0 +1,39 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/str.h"
#include "libc/testlib/hyperion.h"
#include "libc/testlib/testlib.h"
uint8_t *sha256(const char *s) {
static uint8_t hash[32];
struct Sha256Ctx ctx;
sha256_init(&ctx);
sha256_update(&ctx, (const uint8_t *)s, strlen(s));
sha256_final(&ctx, hash);
return hash;
}
TEST(sha256, test) {
EXPECT_BINEQ(u",≥M║_░ú♫&Φ;*┼╣Γ€←▬▲╲▼ºB^s♦3bôïÿ$", sha256("hello"));
}
TEST(sha256, testNontrivialSize) {
EXPECT_BINEQ(u"╨╒║☺ª↨╨╒ù€»╝∞nfÑ4Æ╒Tn╫╕`eóA¿↑[3╬", sha256(kHyperion));
}

View file

@ -0,0 +1,63 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/str/str.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/calls.h"
#include "libc/testlib/testlib.h"
sigset_t ss;
TEST(sigemptyset, test) {
EXPECT_EQ(0, sigemptyset(&ss));
EXPECT_BINEQ(u"        ", &ss);
}
TEST(sigfillset, test) {
EXPECT_EQ(0, sigfillset(&ss));
EXPECT_BINEQ(u"λλλλλλλλ", &ss);
}
TEST(sigaddset, test) {
sigemptyset(&ss);
EXPECT_EQ(0, sigaddset(&ss, 1));
EXPECT_BINEQ(u"☺       ", &ss);
EXPECT_EQ(0, sigaddset(&ss, 64));
EXPECT_BINEQ(u"☺      Ç", &ss);
}
TEST(sigdelset, test) {
sigfillset(&ss);
EXPECT_EQ(0, sigdelset(&ss, 1));
EXPECT_BINEQ(u"■λλλλλλλ", &ss);
EXPECT_EQ(0, sigdelset(&ss, 64));
EXPECT_BINEQ(u"■λλλλλλ⌂", &ss);
}
TEST(sigismember, test) {
sigfillset(&ss);
EXPECT_TRUE(sigismember(&ss, 1));
sigdelset(&ss, 1);
EXPECT_FALSE(sigismember(&ss, 1));
EXPECT_TRUE(sigismember(&ss, 64));
sigdelset(&ss, 64);
EXPECT_FALSE(sigismember(&ss, 64));
}

42
test/libc/str/str_test.c Normal file
View file

@ -0,0 +1,42 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(strlen16, testEmpty) { EXPECT_EQ(0, strlen(u"")); }
TEST(strlen16, testAscii) { EXPECT_EQ(5, strlen(u"hello")); }
TEST(strlen16, testUnicode) {
EXPECT_EQ(28, strlen(u"αcτµαlly pδrταblε εxεcµταblε"));
}
TEST(strclen, testAegeanNumberSupplementaryPlane) {
EXPECT_EQ(36, strlen("𐄷𐄸𐄹𐄺𐄻𐄼𐄽𐄾𐄿"));
EXPECT_EQ(18, strlen(u"𐄷𐄸𐄹𐄺𐄻𐄼𐄽𐄾𐄿"));
EXPECT_EQ(9, strlen(L"𐄷𐄸𐄹𐄺𐄻𐄼𐄽𐄾𐄿"));
EXPECT_EQ(9, strclen("𐄷𐄸𐄹𐄺𐄻𐄼𐄽𐄾𐄿"));
EXPECT_EQ(9, strclen(u"𐄷𐄸𐄹𐄺𐄻𐄼𐄽𐄾𐄿"));
EXPECT_EQ(9, strclen(L"𐄷𐄸𐄹𐄺𐄻𐄼𐄽𐄾𐄿"));
}
TEST(strlen16, testCoolKidNulTerminator) {
EXPECT_EQ(2, strlen((const char16_t *)"\x00\xd8\x00\xdc\x00"));
}

View file

@ -0,0 +1,64 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(strchr, blank) {
const char *const blank = "";
EXPECT_EQ(NULL, strchr(blank, '#'));
EXPECT_EQ(blank, strchr(blank, '\0'));
}
TEST(strchr, text) {
char buf[] = "hellothere";
EXPECT_STREQ("there", strchr(buf, 't'));
}
TEST(rawmemchr, text) {
char buf[] = "hellothere";
EXPECT_STREQ("there", rawmemchr(buf, 't'));
}
TEST(strchrnul, text) {
char buf[] = "hellothere";
EXPECT_STREQ("there", strchrnul(buf, 't'));
}
TEST(strchr, nulTerminator) {
char buf[] = "hellothere";
EXPECT_STREQ("", strchr(buf, '\0'));
}
TEST(rawmemchr, nulTerminator) {
char buf[] = "hellothere";
EXPECT_STREQ("", rawmemchr(buf, '\0'));
}
TEST(strchrnul, nulTerminator) {
char buf[] = "hellothere";
EXPECT_STREQ("", strchrnul(buf, '\0'));
}
TEST(strchr, notFound_returnsNul) {
char buf[] = "hellothere";
EXPECT_EQ(NULL, strchr(buf, 'z'));
}
TEST(strchrnul, notFound_returnsPointerToNulByte) {
char buf[] = "hi";
EXPECT_STREQ("", strchrnul(buf, 'z'));
EXPECT_EQ(&buf[2], strchrnul(buf, 'z'));
}

587
test/libc/str/strcmp_test.c Normal file
View file

@ -0,0 +1,587 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/nexgen32e/cachesize.h"
#include "libc/nexgen32e/tinystrcmp.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/rand/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
int memcmp$sse2(const void *, const void *, size_t) hidden;
int memcmp$avx2(const void *, const void *, size_t) hidden;
int (*memcmpi)(const void *, const void *, size_t) = memcmp$sse2;
int strcmp$k8(const char *, const char *) hidden;
int strcmp$avx(const char *, const char *) hidden;
int (*strcmpi)(const char *, const char *) = tinystrcmp;
int strncmp$k8(const char *, const char *, size_t) hidden;
int strncmp$avx(const char *, const char *, size_t) hidden;
int (*strncmpi)(const char *, const char *, size_t) = tinystrncmp;
FIXTURE(strcmp, avx) {
if (X86_HAVE(AVX)) {
strcmpi = strcmp$avx;
strncmpi = strncmp$avx;
}
if (X86_HAVE(AVX2)) {
memcmpi = memcmp$avx2;
}
}
/*───────────────────────────────────────────────────────────────────────────│─╗
test/libc/str/strcmp_test.c § emptiness
*/
TEST(strcmp, emptyString) {
EXPECT_EQ(0, strcmpi("", ""));
EXPECT_NE(0, strcmpi("", "a"));
}
TEST(strcasecmp, emptyString) {
EXPECT_EQ(0, strcasecmp("", ""));
EXPECT_NE(0, strcasecmp("", "a"));
}
TEST(strcmp16, emptyString) {
EXPECT_EQ(0, strcmp16(u"", u""));
EXPECT_NE(0, strcmp16(u"", u"a"));
}
TEST(strcasecmp16, emptyString) {
EXPECT_EQ(0, strcasecmp16(u"", u""));
EXPECT_NE(0, strcasecmp16(u"", u"a"));
}
TEST(wcscmp, emptyString) {
EXPECT_EQ(0, wcscmp(L"", L""));
EXPECT_NE(0, wcscmp(L"", L"a"));
}
TEST(wcscasecmp, emptyString) {
EXPECT_EQ(0, wcscasecmp(L"", L""));
EXPECT_NE(0, wcscasecmp(L"", L"a"));
}
TEST(strncmp, emptyString) {
char *s1 = strcpy(tmalloc(1), "");
char *s2 = strcpy(tmalloc(1), "");
ASSERT_EQ(0, strncmpi(s1, s2, 0));
ASSERT_EQ(0, strncmpi(s1, s2, 1));
ASSERT_EQ(0, strncmpi(s1, s2, -1));
ASSERT_EQ(0, strncmpi(s1, s1, -1));
ASSERT_EQ(0, strncmpi(s2, s2, -1));
tfree(s2);
tfree(s1);
}
TEST(strncasecmp, emptyString) {
char *s1 = strcpy(tmalloc(1), "");
char *s2 = strcpy(tmalloc(1), "");
ASSERT_EQ(0, strncasecmp(s1, s2, 0));
ASSERT_EQ(0, strncasecmp(s1, s2, 1));
ASSERT_EQ(0, strncasecmp(s1, s2, -1));
ASSERT_EQ(0, strncasecmp(s1, s1, -1));
ASSERT_EQ(0, strncasecmp(s2, s2, -1));
tfree(s2);
tfree(s1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
test/libc/str/strcmp_test.c § inequality
*/
TEST(strncmp, testInequality) {
char *s1 = strcpy(tmalloc(2), "1");
char *s2 = strcpy(tmalloc(1), "");
ASSERT_EQ(0, strncmpi(s1, s2, 0));
ASSERT_EQ('1', strncmpi(s1, s2, 1));
ASSERT_EQ(-'1', strncmpi(s2, s1, 1));
tfree(s2);
tfree(s1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
test/libc/str/strcmp_test.c § does it work?
*/
TEST(memcmp, test) {
EXPECT_EQ(memcmpi("\200", "\200", 1), 0);
EXPECT_LT(memcmpi("\177", "\200", 1), 0);
EXPECT_GT(memcmpi("\200", "\177", 1), 0);
EXPECT_EQ(memcmpi("", "", 0), 0);
EXPECT_EQ(memcmpi("a", "a", 1), 0);
EXPECT_GT(memcmpi("a", "A", 1), 0);
EXPECT_LT(memcmpi("A", "a", 1), 0);
EXPECT_LT(memcmpi("\001", "\377", 1), 0);
EXPECT_GT(memcmpi("\377", "\001", 1), 0);
EXPECT_EQ(memcmpi("a", "aa", 1), 0);
EXPECT_EQ(memcmpi("aa", "a", 1), 0);
EXPECT_LT(memcmpi("a", "aa", 2), 0);
EXPECT_GT(memcmpi("aa", "a", 2), 0);
EXPECT_LT(memcmpi("aaaaaaaaaaaaaaa\001", "aaaaaaaaaaaaaaa\377", 16), 0);
EXPECT_GT(memcmpi("aaaaaaaaaaaaaaa\377", "aaaaaaaaaaaaaaa\001", 16), 0);
EXPECT_LT(memcmpi("aaaaaaaaaaaaaaaa\001", "aaaaaaaaaaaaaaaa\377", 17), 0);
EXPECT_GT(memcmpi("aaaaaaaaaaaaaaaa\377", "aaaaaaaaaaaaaaaa\001", 17), 0);
EXPECT_LT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377", 32),
0);
EXPECT_GT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001", 32),
0);
EXPECT_LT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377", 33),
0);
EXPECT_GT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001", 33),
0);
EXPECT_LT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377", 34),
0);
EXPECT_GT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001", 34),
0);
}
TEST(strcmp, testItWorks) {
EXPECT_EQ(strcmpi("", ""), 0);
EXPECT_EQ(strcmpi("a", "a"), 0);
EXPECT_GT(strcmpi("a", "A"), 0);
EXPECT_LT(strcmpi("A", "a"), 0);
EXPECT_LT(strcmpi("\001", "\377"), 0);
EXPECT_GT(strcmpi("\377", "\001"), 0);
EXPECT_LT(strcmpi("a", "aa"), 0);
EXPECT_GT(strcmpi("aa", "a"), 0);
EXPECT_LT(strcmpi("a\000", "aa\000"), 0);
EXPECT_GT(strcmpi("aa\000", "a\000"), 0);
EXPECT_LT(strcmpi("aaaaaaaaaaaaaaa\001", "aaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(strcmpi("aaaaaaaaaaaaaaa\377", "aaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(strcmpi("aaaaaaaaaaaaaaaa\001", "aaaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(strcmpi("aaaaaaaaaaaaaaaa\377", "aaaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(strcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(strcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(strcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
}
TEST(strcasecmp, testItWorks) {
EXPECT_EQ(strcasecmp("", ""), 0);
EXPECT_EQ(strcasecmp("a", "a"), 0);
EXPECT_EQ(strcasecmp("a", "A"), 0);
EXPECT_EQ(strcasecmp("A", "a"), 0);
EXPECT_LT(strcasecmp("a", "z"), 0);
EXPECT_GT(strcasecmp("z", "a"), 0);
EXPECT_LT(strcasecmp("\001", "\377"), 0);
EXPECT_GT(strcasecmp("\377", "\001"), 0);
EXPECT_LT(strcasecmp("a", "aa"), 0);
EXPECT_GT(strcasecmp("aa", "a"), 0);
EXPECT_LT(strcasecmp("a\000", "aa\000"), 0);
EXPECT_GT(strcasecmp("aa\000", "a\000"), 0);
EXPECT_LT(strcasecmp("aaaaaaaaaaaaaaa\001", "aaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(strcasecmp("aaaaaaaaaaaaaaa\377", "aaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(strcasecmp("aaaaaaaaaaaaaaaa\001", "aaaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(strcasecmp("aaaaaaaaaaaaaaaa\377", "aaaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(strcasecmp("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcasecmp("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(strcasecmp("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcasecmp("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(strcasecmp("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcasecmp("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
}
TEST(strcmp16, testItWorks) {
EXPECT_EQ(strcmp16(u"", u""), 0);
EXPECT_EQ(strcmp16(u"a", u"a"), 0);
EXPECT_GT(strcmp16(u"a", u"A"), 0);
EXPECT_LT(strcmp16(u"A", u"a"), 0);
EXPECT_LT(strcmp16(u"\001", u"\377"), 0);
EXPECT_GT(strcmp16(u"\377", u"\001"), 0);
EXPECT_LT(strcmp16(u"a", u"aa"), 0);
EXPECT_GT(strcmp16(u"aa", u"a"), 0);
EXPECT_LT(strcmp16(u"a\000", u"aa\000"), 0);
EXPECT_GT(strcmp16(u"aa\000", u"a\000"), 0);
EXPECT_LT(strcmp16(u"aaaaaaaaaaaaaaa\001", u"aaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(strcmp16(u"aaaaaaaaaaaaaaa\377", u"aaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(strcmp16(u"aaaaaaaaaaaaaaaa\001", u"aaaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(strcmp16(u"aaaaaaaaaaaaaaaa\377", u"aaaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(strcmp16(u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001",
u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcmp16(u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377",
u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(strcmp16(u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001",
u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcmp16(u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377",
u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(strcmp16(u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001",
u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(strcmp16(u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377",
u"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
}
TEST(wcscmp, testItWorks) {
EXPECT_EQ(wcscmp(L"", L""), 0);
EXPECT_EQ(wcscmp(L"a", L"a"), 0);
EXPECT_GT(wcscmp(L"a", L"A"), 0);
EXPECT_LT(wcscmp(L"A", L"a"), 0);
EXPECT_LT(wcscmp(L"\001", L"\377"), 0);
EXPECT_GT(wcscmp(L"\377", L"\001"), 0);
EXPECT_LT(wcscmp(L"a", L"aa"), 0);
EXPECT_GT(wcscmp(L"aa", L"a"), 0);
EXPECT_LT(wcscmp(L"a", L"aa"), 0);
EXPECT_GT(wcscmp(L"aa", L"a"), 0);
EXPECT_LT(wcscmp(L"aaaaaaaaaaaaaaa\001", L"aaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(wcscmp(L"aaaaaaaaaaaaaaa\377", L"aaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(wcscmp(L"aaaaaaaaaaaaaaaa\001", L"aaaaaaaaaaaaaaaa\377"), 0);
EXPECT_GT(wcscmp(L"aaaaaaaaaaaaaaaa\377", L"aaaaaaaaaaaaaaaa\001"), 0);
EXPECT_LT(wcscmp(L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001",
L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(wcscmp(L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\377",
L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(wcscmp(L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001",
L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(wcscmp(L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\377",
L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
EXPECT_LT(wcscmp(L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001",
L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377"),
0);
EXPECT_GT(wcscmp(L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\377",
L"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\001"),
0);
}
TEST(strcasecmp, testItWorksCase) {
EXPECT_EQ(0, strcasecmp("hello", "HELLO"));
EXPECT_EQ(0, strcasecmp("hello", "Hello"));
EXPECT_EQ(0, strcasecmp("hello", "hello"));
EXPECT_NE(0, strcasecmp("hello", "yello"));
}
TEST(strcasecmp16, testItWorksCase) {
EXPECT_EQ(0, strcasecmp16(u"hello", u"HELLO"));
EXPECT_EQ(0, strcasecmp16(u"hello", u"Hello"));
EXPECT_EQ(0, strcasecmp16(u"hello", u"hello"));
EXPECT_NE(0, strcasecmp16(u"hello", u"yello"));
}
TEST(wcscasecmp, testItWorksCase) {
EXPECT_EQ(0, wcscasecmp(L"hello", L"HELLO"));
EXPECT_EQ(0, wcscasecmp(L"hello", L"Hello"));
EXPECT_EQ(0, wcscasecmp(L"hello", L"hello"));
EXPECT_NE(0, wcscasecmp(L"hello", L"yello"));
}
TEST(strcasecmp8to16, testItWorksCase) {
EXPECT_EQ(0, strcasecmp8to16("hello", u"HELLO"));
EXPECT_EQ(0, strcasecmp8to16("hello", u"Hello"));
EXPECT_EQ(0, strcasecmp8to16("hello", u"hello"));
EXPECT_NE(0, strcasecmp8to16("hello", u"yello"));
}
/*───────────────────────────────────────────────────────────────────────────│─╗
test/libc/str/strcmp_test.c § nontrivial length
*/
TEST(strncmp, testEqualManyNs) {
char *s1 = tmalloc(PAGESIZE);
char *s2 = tmalloc(PAGESIZE);
memset(s1, 7, PAGESIZE);
memset(s2, 7, PAGESIZE);
s1[PAGESIZE - 1] = '\0';
s2[PAGESIZE - 1] = '\0';
for (unsigned i = 1; i <= 128; ++i) {
ASSERT_EQ(0, strncmpi(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 0));
ASSERT_EQ(0, strncmpi(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 1));
}
tfree(s2);
tfree(s1);
}
TEST(strncmp, testNotEqualManyNs) {
char *s1 = tmalloc(PAGESIZE);
char *s2 = tmalloc(PAGESIZE);
for (unsigned i = 1; i <= 128; ++i) {
memset(s1, 7, PAGESIZE);
memset(s2, 7, PAGESIZE);
s1[PAGESIZE - 1] = (unsigned char)0;
s2[PAGESIZE - 1] = (unsigned char)255;
ASSERT_EQ(-255, strncmpi(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 0));
ASSERT_EQ(-255, strncmpi(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 1));
}
tfree(s2);
tfree(s1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
test/libc/str/strcmp_test.c § nul termination vs. explicit length
*/
TEST(strncmp, testStringNulTerminatesBeforeExplicitLength) {
const char kRdi[] = "";
const char kRsi[] = "TZ=America/Los_Angeles";
char *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
size_t rdx = 3;
EXPECT_EQ(strncmpi(rdi, rdi, rdx), 0);
EXPECT_LT(strncmpi(rdi, rsi, rdx), 0);
EXPECT_GT(strncmpi(rsi, rdi, rdx), 0);
tfree(rsi);
tfree(rdi);
}
TEST(strncasecmp, testStringNulTerminatesBeforeExplicitLength) {
const char kRdi[] = "";
const char kRsi[] = "TZ=America/Los_Angeles";
char *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
size_t rdx = 3;
EXPECT_EQ(strncasecmp(rdi, rdi, rdx), 0);
EXPECT_LT(strncasecmp(rdi, rsi, rdx), 0);
EXPECT_GT(strncasecmp(rsi, rdi, rdx), 0);
tfree(rsi);
tfree(rdi);
}
TEST(strncmp16, testStringNulTerminatesBeforeExplicitLength) {
const char16_t kRdi[] = u"";
const char16_t kRsi[] = u"TZ=America/Los_Angeles";
char16_t *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char16_t *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
size_t rdx = 3;
EXPECT_EQ(strncmp16(rdi, rdi, rdx), 0);
EXPECT_LT(strncmp16(rdi, rsi, rdx), 0);
EXPECT_GT(strncmp16(rsi, rdi, rdx), 0);
tfree(rsi);
tfree(rdi);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
test/libc/str/strcmp_test.c § two's complement bane
*/
TEST(strcmp, testTwosComplementBane_hasUnsignedBehavior) {
EXPECT_EQ(strcmpi("\200", "\200"), 0);
EXPECT_LT(strcmpi("\x7f", "\x80"), 0);
EXPECT_GT(strcmpi("\x80", "\x7f"), 0);
}
TEST(strcasecmp, testTwosComplementBane_hasUnsignedBehavior) {
EXPECT_EQ(strcasecmp("\200", "\200"), 0);
EXPECT_LT(strcasecmp("\x7f", "\x80"), 0);
EXPECT_GT(strcasecmp("\x80", "\x7f"), 0);
}
TEST(memcmp, testTwosComplementBane_unsignedBehavior) {
EXPECT_EQ(memcmpi("\200", "\200", 1), 0);
EXPECT_LT(memcmpi("\177", "\200", 1), 0);
EXPECT_GT(memcmpi("\200", "\177", 1), 0);
EXPECT_EQ(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\200",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\200", 34),
0);
EXPECT_LT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\177",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\200", 34),
0);
EXPECT_GT(memcmpi("aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\200",
"aaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaa\177", 34),
0);
}
TEST(strcmp16, testTwosComplementBane_hasUnsignedBehavior) {
char16_t *B1 = tmalloc(8);
char16_t *B2 = tmalloc(8);
B1[1] = L'\0';
B2[1] = L'\0';
EXPECT_EQ(strcmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\x00\x80", 2)), 0);
EXPECT_LT(strcmp16(memcpy(B1, "\xff\x7f", 2), memcpy(B2, "\x00\x80", 2)), 0);
EXPECT_GT(strcmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\xff\x7f", 2)), 0);
tfree(B2);
tfree(B1);
}
TEST(strncmp16, testTwosComplementBane_hasUnsignedBehavior) {
char16_t *B1 = tmalloc(4);
char16_t *B2 = tmalloc(4);
EXPECT_EQ(strncmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\x00\x80", 2), 1),
0);
EXPECT_LT(strncmp16(memcpy(B1, "\xff\x7f", 2), memcpy(B2, "\x00\x80", 2), 1),
0);
EXPECT_GT(strncmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\xff\x7f", 2), 1),
0);
tfree(B2);
tfree(B1);
}
TEST(wcscmp, testTwosComplementBane_hasSignedBehavior) {
wchar_t *B1 = tmalloc(8);
wchar_t *B2 = tmalloc(8);
B1[1] = L'\0';
B2[1] = L'\0';
EXPECT_EQ(wcscmp(memcpy(B1, "\x00\x00\x00\x80", 4),
memcpy(B2, "\x00\x00\x00\x80", 4)),
0);
EXPECT_GT(wcscmp(memcpy(B1, "\xff\xff\xff\x7f", 4),
memcpy(B2, "\x00\x00\x00\x80", 4)),
0);
EXPECT_LT(wcscmp(memcpy(B1, "\x00\x00\x00\x80", 4),
memcpy(B2, "\xff\xff\xff\x7f", 4)),
0);
tfree(B2);
tfree(B1);
}
TEST(wcsncmp, testTwosComplementBane_hasSignedBehavior) {
wchar_t *B1 = tmalloc(4);
wchar_t *B2 = tmalloc(4);
EXPECT_EQ(wcsncmp(memcpy(B1, "\x00\x00\x00\x80", 4),
memcpy(B2, "\x00\x00\x00\x80", 4), 1),
0);
EXPECT_GT(wcsncmp(memcpy(B1, "\xff\xff\xff\x7f", 4),
memcpy(B2, "\x00\x00\x00\x80", 4), 1),
0);
EXPECT_LT(wcsncmp(memcpy(B1, "\x00\x00\x00\x80", 4),
memcpy(B2, "\xff\xff\xff\x7f", 4), 1),
0);
tfree(B2);
tfree(B1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
test/libc/str/strcmp_test.c § benchmarks
*/
testonly noinline int strcmp$pure(const char *a, const char *b) {
for (; *a == *b; a++, b++) {
if (!*a) break;
}
return (*a & 0xff) - (*b & 0xff);
}
testonly noinline int strcasecmp$pure(const char *a, const char *b) {
for (; *a && *b; a++, b++) {
if (!(*a == *b || tolower(*a & 0xff) == tolower(*b & 0xff))) {
break;
}
}
return tolower(*a & 0xff) - tolower(*b & 0xff);
}
char *randomize_buf2str(size_t size, char data[size]) {
rngset(data, size, rand64, -1);
data[size - 1] = '\0';
return data;
}
char *longstringislong(size_t size, char data[size]) {
unsigned i;
randomize_buf2str(size, data);
for (i = 0; i < size; ++i) {
data[i] |= 1u << (i & 5);
}
data[size - 1] = '\0';
return data;
}
void randomize_buf2str_dupe(size_t size, char data[size], char dupe[size]) {
randomize_buf2str(size, data);
memcpy(dupe, data, size);
}
void longstringislong_dupe(size_t size, char data[size], char dupe[size]) {
longstringislong(size, data);
memcpy(dupe, data, size);
}
BENCH(bench_00_strcmp, bench) {
size_t size;
char *dupe, *data;
size = ROUNDDOWN(getcachesize(kCpuCacheTypeData, 1) / 2, PAGESIZE);
data = tgc(tmalloc(size));
dupe = tgc(tmalloc(size));
EZBENCH2("strcmp [identity]", longstringislong(size, data),
EXPROPRIATE(strcmp(VEIL("r", data), data)));
EZBENCH2("strcmp [short dupe]", randomize_buf2str_dupe(size, data, dupe),
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
EZBENCH2("strcmp$pure [short dupe]", randomize_buf2str_dupe(size, data, dupe),
EXPROPRIATE(strcmp$pure(VEIL("r", data), VEIL("r", dupe))));
EZBENCH2("strcmp [long dupe]", longstringislong_dupe(size, data, dupe),
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
EZBENCH2("strcmp$pure [long dupe]", longstringislong_dupe(size, data, dupe),
EXPROPRIATE(strcmp$pure(VEIL("r", data), VEIL("r", dupe))));
}
BENCH(bench_01_strcasecmp, bench) {
size_t size;
char *dupe, *data;
size = ROUNDDOWN(getcachesize(kCpuCacheTypeData, 1) / 2, PAGESIZE);
data = tgc(tmalloc(size));
dupe = tgc(tmalloc(size));
EZBENCH2("strcasecmp [identity]", longstringislong(size, data),
EXPROPRIATE(strcasecmp(VEIL("r", data), data)));
EZBENCH2("strcasecmp [short dupe]", randomize_buf2str_dupe(size, data, dupe),
EXPROPRIATE(strcasecmp(VEIL("r", data), VEIL("r", dupe))));
EZBENCH2("strcasecmp$pure [short dupe]",
randomize_buf2str_dupe(size, data, dupe),
EXPROPRIATE(strcasecmp$pure(VEIL("r", data), VEIL("r", dupe))));
EZBENCH2("strcasecmp [long dupe]", longstringislong_dupe(size, data, dupe),
EXPROPRIATE(strcasecmp(VEIL("r", data), VEIL("r", dupe))));
EZBENCH2("strcasecmp$pure [long dupe]",
longstringislong_dupe(size, data, dupe),
EXPROPRIATE(strcasecmp$pure(VEIL("r", data), VEIL("r", dupe))));
}

131
test/libc/str/strlen_test.c Normal file
View file

@ -0,0 +1,131 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/macros.h"
#include "libc/nexgen32e/tinystrlen.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
char u8[] = "utf-8 ☻";
char16_t u16[] = u"utf16 ☻";
wchar_t u32[] = L"utf32 ☻";
TEST(strlen, usageExample_c11) {
EXPECT_EQ(6 + 3, strlen(u8));
EXPECT_EQ(7, strlen(u16));
EXPECT_EQ(7, strlen(u32));
}
TEST(strlen, usageExample_c99) {
EXPECT_EQ(6 + 3, strlen(u8));
EXPECT_EQ(7, strlen16(u16));
EXPECT_EQ(7, wcslen(u32));
}
TEST(strlen, whatMemoryLooksLike) {
EXPECT_BINEQ(u"utf-8 Γÿ╗ ", u8); /* ← thompson-pike encoded */
EXPECT_BINEQ(u"u t f 1 6   ;&  ", u16);
EXPECT_BINEQ(u"u   t   f   3   2       ;&      ", u32);
}
TEST(strlen, test_const) {
const char buf[] = "hellothere";
ASSERT_EQ(0, strlen(""));
ASSERT_EQ(0, strnlen("e", 0));
ASSERT_EQ(10, strlen(buf));
}
TEST(strlen, test_nonconst) {
char buf[256];
unsigned i;
for (i = 0; i < 255; ++i) buf[i] = i + 1;
buf[i] = '\0';
ASSERT_EQ(255, strlen(buf));
}
TEST(strnlen, testconst) {
ASSERT_EQ(0, strnlen_s(NULL, 3));
ASSERT_EQ(0, strnlen("", 3));
ASSERT_EQ(0, strnlen("a", 0));
ASSERT_EQ(3, strnlen("123", 3));
ASSERT_EQ(2, strnlen("123", 2));
ASSERT_EQ(3, strnlen("123", 4));
}
TEST(strlen, testnonconst) {
char buf[256];
unsigned i;
for (i = 0; i < 255; ++i) buf[i] = i + 1;
buf[i] = '\0';
ASSERT_EQ(255, strlen(buf));
}
TEST(strnlen_s, null_ReturnsZero) {
ASSERT_EQ(0, strnlen_s(NULL, 3));
}
TEST(strnlen, nulNotFound_ReturnsSize) {
int sizes[] = {1, 2, 7, 8, 15, 16, 31, 32, 33};
for (unsigned i = 0; i < ARRAYLEN(sizes); ++i) {
char *buf = tmalloc(sizes[i]);
memset(buf, ' ', sizes[i]);
ASSERT_EQ(sizes[i], strnlen(buf, sizes[i]));
tfree(buf);
}
}
TEST(strnlen_s, nulNotFound_ReturnsZero) {
char buf[3] = {1, 2, 3};
ASSERT_EQ(0, strnlen_s(buf, 3));
}
TEST(tinystrlen, test) {
ASSERT_EQ(0, tinystrlen(""));
ASSERT_EQ(1, tinystrlen("a"));
ASSERT_EQ(3, tinystrlen("123"));
}
TEST(tinywcslen, test) {
ASSERT_EQ(0, tinywcslen(L""));
ASSERT_EQ(1, tinywcslen(L"a"));
ASSERT_EQ(3, tinywcslen(L"123"));
}
TEST(tinywcsnlen, test) {
EXPECT_EQ(0, tinywcsnlen(L"", 3));
EXPECT_EQ(0, tinywcsnlen(L"a", 0));
EXPECT_EQ(3, tinywcsnlen(L"123", 3));
EXPECT_EQ(2, tinywcsnlen(L"123", 2));
EXPECT_EQ(3, tinywcsnlen(L"123", 4));
}
TEST(tinystrlen16, test) {
ASSERT_EQ(0, tinystrlen16(u""));
ASSERT_EQ(1, tinystrlen16(u"a"));
ASSERT_EQ(3, tinystrlen16(u"123"));
}
TEST(tinystrnlen16, test) {
EXPECT_EQ(0, tinystrnlen16(u"", 3));
EXPECT_EQ(0, tinystrnlen16(u"a", 0));
EXPECT_EQ(3, tinystrnlen16(u"123", 3));
EXPECT_EQ(2, tinystrnlen16(u"123", 2));
EXPECT_EQ(3, tinystrnlen16(u"123", 4));
}

View file

@ -0,0 +1,45 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#define T(NAME) NAME
#define S(S) S
#define C(C) C
#include "test/libc/str/strrchr_test.inc"
#undef C
#undef S
#undef T
#define T(NAME) NAME##16
#define S(S) u##S
#define C(C) u##C
#include "test/libc/str/strrchr_test.inc"
#undef C
#undef S
#undef T
#define T(NAME) NAME##32
#define S(S) L##S
#define C(C) L##C
#include "test/libc/str/strrchr_test.inc"
#undef C
#undef S
#undef T

View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
╚─────────────────────────────────────────────────────────────────────────────*/
TEST(T(strrchr), test) {
EXPECT_EQ(NULL, strrchr(S("hello"), C('z')));
EXPECT_STREQ(S("lo"), strrchr(S("hello"), C('l')));
EXPECT_STREQ(S("llo"), strchr(S("hello"), C('l')));
EXPECT_STREQ(S("hello"), strrchr(S("hello"), C('h')));
EXPECT_STREQ(S("ello"), strrchr(S("hello"), C('e')));
EXPECT_STREQ(S("o"), strrchr(S("hello"), C('o')));
}
TEST(T(strrchr), simdVectorStuffIsntBroken) {
EXPECT_EQ(NULL, strrchr(S("--------------------------------"), C('x')));
EXPECT_STREQ(S("x"), strrchr(S("-------------------------------x"), C('x')));
EXPECT_STREQ(S("x-------------------------------"),
strrchr(S("x-------------------------------"), C('x')));
EXPECT_STREQ(S("x") S("z-------------------------------"),
strrchr(S("x") S("z-------------------------------"), C('x')));
EXPECT_STREQ(S("x-------------------------------")
S("y-------------------------------"),
strrchr(S("x-------------------------------")
S("y-------------------------------"),
C('x')));
EXPECT_STREQ(S("x") S("z-------------------------------")
S("y-------------------------------"),
strrchr(S("x") S("z-------------------------------")
S("y-------------------------------"),
C('x')));
}

View file

@ -0,0 +1,65 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(strtok_r, testEmpty) {
static const char *const kInput = "";
static const char *const kSeparators = "/";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
char *state;
EXPECT_EQ(NULL, strtok_r(s, kSeparators, &state));
tfree(s);
}
TEST(strtok_r, test) {
static const char *const kInput = ".,lol..cat..";
static const char *const kSeparators = ".,";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
char *state;
EXPECT_STREQ("lol", strtok_r(s, kSeparators, &state));
EXPECT_STREQ("cat", strtok_r(NULL, kSeparators, &state));
EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state));
EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state));
tfree(s);
}
TEST(strtok, test) {
static const char *const kInput = ".,lol..cat..";
static const char *const kSeparators = ".,";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
EXPECT_STREQ("lol", strtok(s, kSeparators));
EXPECT_STREQ("cat", strtok(NULL, kSeparators));
EXPECT_EQ(NULL, strtok(NULL, kSeparators));
EXPECT_EQ(NULL, strtok(NULL, kSeparators));
tfree(s);
}
TEST(strtok_r, testHostsTxtLine) {
static const char *const kInput = "203.0.113.1 lol.example. lol";
static const char *const kSeparators = " \t";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
char *state;
EXPECT_STREQ("203.0.113.1", strtok_r(s, kSeparators, &state));
EXPECT_STREQ("lol.example.", strtok_r(NULL, kSeparators, &state));
EXPECT_STREQ("lol", strtok_r(NULL, kSeparators, &state));
EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state));
tfree(s);
}

View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(strntolower, test) {
char s[128] = "ABCD";
strntolower(s, -1);
EXPECT_STREQ("abcd", s);
}
TEST(strntolower, testLong) {
char s[128] = "ABCDabcdABCDabcdABCDabcdABCDabcdABCDabcd";
strntolower(s, -1);
EXPECT_STREQ("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", s);
}

70
test/libc/str/test.mk Normal file
View file

@ -0,0 +1,70 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
PKGS += TEST_LIBC_STR
TEST_LIBC_STR_SRCS := $(wildcard test/libc/str/*.c)
TEST_LIBC_STR_SRCS_TEST = $(filter %_test.c,$(TEST_LIBC_STR_SRCS))
TEST_LIBC_STR_COMS = $(TEST_LIBC_STR_OBJS:%.o=%.com)
TEST_LIBC_STR_OBJS = \
$(TEST_LIBC_STR_SRCS:%=o/$(MODE)/%.zip.o) \
$(TEST_LIBC_STR_SRCS:%.c=o/$(MODE)/%.o)
TEST_LIBC_STR_BINS = \
$(TEST_LIBC_STR_COMS) \
$(TEST_LIBC_STR_COMS:%=%.dbg)
TEST_LIBC_STR_TESTS = \
$(TEST_LIBC_STR_SRCS_TEST:%.c=o/$(MODE)/%.com.ok)
TEST_LIBC_STR_CHECKS = \
$(TEST_LIBC_STR_SRCS_TEST:%.c=o/$(MODE)/%.com.runs)
TEST_LIBC_STR_DIRECTDEPS = \
LIBC_CALLS_HEFTY \
LIBC_FMT \
LIBC_NEXGEN32E \
LIBC_STDIO \
LIBC_MEM \
LIBC_RUNTIME \
LIBC_STR \
LIBC_RAND \
LIBC_UNICODE \
LIBC_CALLS \
LIBC_STUBS \
LIBC_SYSV \
LIBC_TESTLIB \
LIBC_LOG \
LIBC_X \
LIBC_ZIPOS \
THIRD_PARTY_ZLIB
TEST_LIBC_STR_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBC_STR_DIRECTDEPS),$($(x))))
o/$(MODE)/test/libc/str/str.pkg: \
$(TEST_LIBC_STR_OBJS) \
$(foreach x,$(TEST_LIBC_STR_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/test/libc/str/tpenc_test.o: \
OVERRIDE_CFLAGS += \
$(TRADITIONAL)
o/$(MODE)/test/libc/str/%.com.dbg: \
$(TEST_LIBC_STR_DEPS) \
o/$(MODE)/test/libc/str/%.o \
o/$(MODE)/test/libc/str/str.pkg \
$(LIBC_TESTMAIN) \
$(CRT) \
$(APE)
@$(APELINK)
$(TEST_LIBC_STR_OBJS): \
DEFAULT_CCFLAGS += \
-fno-builtin
.PHONY: o/$(MODE)/test/libc/str
o/$(MODE)/test/libc/str: \
$(TEST_LIBC_STR_BINS) \
$(TEST_LIBC_STR_CHECKS)

View file

@ -0,0 +1,80 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/progn.h"
#include "libc/bits/safemacros.h"
#include "libc/errno.h"
#include "libc/fmt/bing.h"
#include "libc/limits.h"
#include "libc/runtime/gc.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
wint_t wc;
TEST(tpdecode, testGlyph) {
EXPECT_EQ(u'', PROGN(ASSERT_EQ(3, tpdecode("", &wc)), wc));
EXPECT_EQ(L'𐌰', PROGN(ASSERT_EQ(4, tpdecode("𐌰𐌱𐌲𐌳", &wc)), wc));
EXPECT_EQ(u'', PROGN(ASSERT_EQ(3, tpdecode("", &wc)), wc));
EXPECT_EQ(u'', PROGN(ASSERT_EQ(3, tpdecode("", &wc)), wc));
}
TEST(tpdecode, testNul_canonicalizesWithFiniteOverlongConsumption) {
EXPECT_EQ('\0', PROGN(ASSERT_EQ(1, tpdecode("\0\0\0\0", &wc)), wc));
EXPECT_EQ('\0',
PROGN(ASSERT_EQ(2, tpdecode(gc(unbingstr(u"└ÇÇÇÇÇ")), &wc)), wc));
EXPECT_EQ('\0',
PROGN(ASSERT_EQ(3, tpdecode(gc(unbingstr(u"αÇÇÇÇÇ")), &wc)), wc));
EXPECT_EQ('\0',
PROGN(ASSERT_EQ(4, tpdecode(gc(unbingstr(u"≡ÇÇÇÇÇ")), &wc)), wc));
EXPECT_EQ('\0',
PROGN(ASSERT_EQ(5, tpdecode(gc(unbingstr(u"°ÇÇÇÇÇ")), &wc)), wc));
EXPECT_EQ('\0',
PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"ⁿÇÇÇÇÇ")), &wc)), wc));
}
TEST(tpdecode, testSynchronization_skipsLeadingContinuations) {
EXPECT_EQ('a',
PROGN(EXPECT_EQ(7, tpdecode(gc(unbingstr(u"Ç╗╝╜╛┐a")), &wc)), wc));
}
TEST(tpdecode, testSpace) {
EXPECT_EQ(0x20, PROGN(ASSERT_EQ(1, tpdecode(" ", &wc)), wc));
}
TEST(tpdecode, testNegativeNumbers) {
EXPECT_EQ(-1, PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"λ┐┐┐┐┐")), &wc)),
(wchar_t)wc));
EXPECT_EQ(INT_MIN,
PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"■ÇÇÇÇÇ")), &wc)),
(wchar_t)wc));
EXPECT_EQ(0x80000000u,
PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"■ÇÇÇÇÇ")), &wc)), wc));
EXPECT_EQ(0xC0000000u,
PROGN(ASSERT_EQ(6, tpdecode(gc(unbingstr(u"λÇÇÇÇÇ")), &wc)), wc));
}
TEST(tpdecode, testInvalidEncoding_endOfString) {
EXPECT_EQ(u'<EFBFBD>', PROGN(EXPECT_EQ(-1, tpdecode(gc(unbingstr(u"")), &wc)), wc));
}
TEST(tpdecode, testInvalidEncoding_tooFewContinuations) {
EXPECT_EQ(u'<EFBFBD>', PROGN(EXPECT_EQ(-1, tpdecode(gc(unbingstr(u"")), &wc)), wc));
}

View file

@ -0,0 +1,52 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/limits.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
STATIC_YOINK("strwidth");
volatile uint64_t v;
TEST(tpenc, test) {
EXPECT_EQ(0, tpenc(0));
EXPECT_EQ(1, tpenc(1));
EXPECT_EQ(' ', tpenc(' '));
EXPECT_EQ(0x7f, tpenc(0x7f));
EXPECT_EQ(0x008496E2, tpenc(L''));
EXPECT_EQ(0x8080808080FEul, tpenc(INT_MIN));
}
uint64_t Tpenc(int x) {
return (v = tpenc(x));
}
BENCH(tpenc, bench) {
EZBENCH(donothing, Tpenc(0));
EZBENCH(donothing, Tpenc(1));
EZBENCH(donothing, Tpenc(' '));
EZBENCH(donothing, Tpenc(0x7f));
EZBENCH(donothing, Tpenc(L''));
EZBENCH(donothing, Tpenc(INT_MIN));
fprintf(stderr, "\n");
}

View file

@ -0,0 +1,61 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/progn.h"
#include "libc/bits/safemacros.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
char buf[8];
TEST(tpencode, testNul) {
ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, tpencode(buf, 8, 0, false)), buf));
ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, (tpencode)(buf, 8, 0, false)), buf));
}
TEST(tpencode, testSpace) {
ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, tpencode(buf, 8, 0x20, false)), buf));
ASSERT_BINEQ(u" ", PROGN(ASSERT_EQ(1, (tpencode)(buf, 8, 0x20, false)), buf));
}
TEST(tpencode, testGlyph) {
ASSERT_BINEQ(u"→", PROGN(ASSERT_EQ(3, tpencode(buf, 8, u'', false)), buf));
ASSERT_BINEQ(u"→",
PROGN(ASSERT_EQ(3, (tpencode)(buf, 8, u'', false)), buf));
}
TEST(tpencode, testMathematicalNotMuhPolicyDrivenBehavior_negativeOne) {
ASSERT_BINEQ(u"λ┐┐┐┐┐",
PROGN(ASSERT_EQ(6, tpencode(buf, 8, -1, false)), buf));
ASSERT_BINEQ(u"λ┐┐┐┐┐",
PROGN(ASSERT_EQ(6, (tpencode)(buf, 8, -1, false)), buf));
}
TEST(tpencode, testMathematicalNotMuhPolicyDrivenBehavior_twosComplementBane) {
ASSERT_BINEQ(u"■ÇÇÇÇÇ",
PROGN(ASSERT_EQ(6, tpencode(buf, 8, 0x80000000, false)), buf));
ASSERT_BINEQ(u"■ÇÇÇÇÇ",
PROGN(ASSERT_EQ(6, (tpencode)(buf, 8, 0x80000000, false)), buf));
}
TEST(tpencode, testMathematicalNotMuhPolicyDrivenBehavior_nonCanonicalNul) {
ASSERT_BINEQ(u"└Ç", PROGN(ASSERT_EQ(2, tpencode(buf, 8, 0, true)), buf));
ASSERT_BINEQ(u"└Ç", PROGN(ASSERT_EQ(2, (tpencode)(buf, 8, 0, true)), buf));
}

View file

@ -0,0 +1,30 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(tprecode8to16, test) {
size_t size = 8;
char16_t *buf = tmalloc(size * sizeof(char16_t));
EXPECT_EQ(7, tprecode8to16(buf, size, "hello☻♥"));
EXPECT_STREQ(u"hello☻♥", buf);
tfree(buf);
}

View file

@ -0,0 +1,166 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/log/check.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/rbx.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/str/undeflate.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/hyperion.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
#include "libc/zip.h"
#include "third_party/zlib/zlib.h"
STATIC_YOINK("libc/testlib/hyperion.txt");
TEST(undeflate, testEmbeddedPlaintextConstant) {
EXPECT_STARTSWITH("The fall of Hyperion - a Dream", kHyperion);
}
TEST(undeflate, testStatCentralDirectory_notFound_noSysCalls) {
uint64_t c;
struct stat st;
c = g_syscount;
ASSERT_EQ(-1, stat("zip:doge.txt", &st));
ASSERT_EQ(0, g_syscount - c);
ASSERT_EQ(ENOENT, errno);
}
TEST(undeflate, testStatCentralDirectory_isFound_noSysCalls) {
uint64_t c;
struct stat st = {0};
c = g_syscount;
ASSERT_NE(-1, stat("zip:libc/testlib/hyperion.txt", &st));
ASSERT_TRUE(S_ISREG(st.st_mode));
ASSERT_EQ(kHyperionSize, st.st_size);
ASSERT_EQ(0, g_syscount - c);
}
TEST(undeflate, testOpenReadCloseEmbeddedZip) {
int fd;
char *data;
ASSERT_NE(-1, (fd = open("zip:libc/testlib/hyperion.txt", O_RDONLY)));
ASSERT_NE(NULL, (data = gc(malloc(kHyperionSize))));
ASSERT_EQ(kHyperionSize, read(fd, data, kHyperionSize));
EXPECT_EQ(0, memcmp(kHyperion, data, kHyperionSize));
EXPECT_NE(-1, close(fd));
}
TEST(undeflate, testEmbeddedCompressedZipFile_theHardWay) {
int fd;
size_t i;
bool found;
struct stat st;
struct DeflateState ds;
uint8_t *map, *cd, *cf, *lf, *data;
found = false;
ASSERT_NE(-1, (fd = open(findcombinary(), O_RDONLY)));
ASSERT_NE(-1, fstat(fd, &st));
ASSERT_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
ASSERT_NE(NULL, (cd = zipfindcentraldir(map, st.st_size)));
ASSERT_GE(ZIP_CDIR_RECORDS(cd), 1);
for (i = 0, cf = map + ZIP_CDIR_OFFSET(cd); i < ZIP_CDIR_RECORDS(cd);
++i, cf += ZIP_CFILE_HDRSIZE(cf)) {
if (strncmp("libc/testlib/hyperion.txt", ZIP_CFILE_NAME(cf),
ZIP_CFILE_NAMESIZE(cf)) == 0) {
lf = map + ZIP_CFILE_OFFSET(cf);
ASSERT_EQ(kZipCompressionDeflate, ZIP_LFILE_COMPRESSIONMETHOD(lf));
ASSERT_EQ(kHyperionSize, ZIP_LFILE_UNCOMPRESSEDSIZE(lf));
undeflate((data = gc(xmalloc(ZIP_LFILE_UNCOMPRESSEDSIZE(lf) * 24))),
ZIP_LFILE_UNCOMPRESSEDSIZE(lf), ZIP_LFILE_CONTENT(lf),
ZIP_LFILE_COMPRESSEDSIZE(lf), &ds);
ASSERT_EQ(ZIP_LFILE_CRC32(lf),
crc32_z(0, data, ZIP_LFILE_UNCOMPRESSEDSIZE(lf)));
ASSERT_EQ(0, memcmp(kHyperion, data, ZIP_LFILE_UNCOMPRESSEDSIZE(lf)));
found = true;
break;
}
}
ASSERT_NE(-1, munmap(map, st.st_size));
ASSERT_NE(-1, close(fd));
ASSERT_TRUE(found);
}
////////////////////////////////////////////////////////////////////////////////
uint8_t *buf_;
size_t bufsize_;
uint8_t *data_;
size_t compressedsize_;
size_t uncompressedsize_;
struct DeflateState ds_;
void Inflate(void) {
z_stream stream;
stream.next_in = data_;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.avail_in = compressedsize_;
stream.total_in = compressedsize_;
stream.next_out = buf_;
stream.avail_out = bufsize_;
stream.total_out = bufsize_;
CHECK_EQ(Z_OK, inflateInit2(&stream, -MAX_WBITS));
CHECK_NE(Z_BUF_ERROR, inflate(&stream, Z_NO_FLUSH));
CHECK_EQ(Z_OK, inflateEnd(&stream));
}
void Undeflate(void) {
undeflate(buf_, uncompressedsize_, data_, compressedsize_, &ds_);
}
static size_t GetLocalFile(const char *name) {
size_t i, cf, namesize;
namesize = strlen(name);
for (i = 0, cf = ZIP_CDIR_OFFSET(__zip_end); i < ZIP_CDIR_RECORDS(__zip_end);
++i, cf += ZIP_CFILE_HDRSIZE(cf)) {
if (namesize == ZIP_CFILE_NAMESIZE(&_base[0] + cf) &&
memcmp(name, ZIP_CFILE_NAME(&_base[0] + cf), namesize) == 0) {
return ZIP_CFILE_OFFSET(&_base[0] + cf);
}
}
abort();
}
BENCH(undeflate, bench) {
size_t lf;
lf = GetLocalFile("libc/testlib/hyperion.txt");
data_ = ZIP_LFILE_CONTENT(&_base[0] + lf);
compressedsize_ = ZIP_LFILE_COMPRESSEDSIZE(&_base[0] + lf);
uncompressedsize_ = ZIP_LFILE_UNCOMPRESSEDSIZE(&_base[0] + lf);
bufsize_ = ROUNDUP(uncompressedsize_, FRAMESIZE / 2);
buf_ = gc(malloc(bufsize_));
EZBENCH(donothing, Inflate());
EZBENCH(donothing, Undeflate());
}

301
test/libc/str/varint_test.c Normal file
View file

@ -0,0 +1,301 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/fmt/bing.h"
#include "libc/limits.h"
#include "libc/macros.h"
#include "libc/runtime/gc.h"
#include "libc/str/str.h"
#include "libc/str/varint.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
#define TV(X, B, I) __FILE__, __LINE__, #X, X, #B, B, #I, I
static const struct VarintTestVectors {
const char *file;
int line;
const char *xcode;
uint64_t x;
const char *bcode;
uint16_t b[11];
const char *icode;
uint8_t i;
} kv[] = {
{TV(0x0000000000000000ul, u"          ", 1)},
{TV(0x0000000000000001ul, u"☺         ", 1)},
{TV(0x0000000000000003ul, u"♥         ", 1)},
{TV(0x0000000000000007ul, u"•         ", 1)},
{TV(0x000000000000000ful, u"☼         ", 1)},
{TV(0x000000000000001ful, u"▼         ", 1)},
{TV(0x000000000000003ful, u"⁇         ", 1)},
{TV(0x000000000000007ful, u"⌂         ", 1)},
{TV(0x00000000000000fful, u"λ☺        ", 2)},
{TV(0x00000000000001fful, u"λ♥        ", 2)},
{TV(0x00000000000003fful, u"λ•        ", 2)},
{TV(0x00000000000007fful, u"λ☼        ", 2)},
{TV(0x0000000000000ffful, u"λ▼        ", 2)},
{TV(0x0000000000001ffful, u"λ⁇        ", 2)},
{TV(0x0000000000003ffful, u"λ⌂        ", 2)},
{TV(0x0000000000007ffful, u"λλ☺       ", 3)},
{TV(0x000000000000fffful, u"λλ♥       ", 3)},
{TV(0x000000000001fffful, u"λλ•       ", 3)},
{TV(0x000000000003fffful, u"λλ☼       ", 3)},
{TV(0x000000000007fffful, u"λλ▼       ", 3)},
{TV(0x00000000000ffffful, u"λλ⁇       ", 3)},
{TV(0x00000000001ffffful, u"λλ⌂       ", 3)},
{TV(0x00000000003ffffful, u"λλλ☺      ", 4)},
{TV(0x00000000007ffffful, u"λλλ♥      ", 4)},
{TV(0x0000000000fffffful, u"λλλ•      ", 4)},
{TV(0x0000000001fffffful, u"λλλ☼      ", 4)},
{TV(0x0000000003fffffful, u"λλλ▼      ", 4)},
{TV(0x0000000007fffffful, u"λλλ⁇      ", 4)},
{TV(0x000000000ffffffful, u"λλλ⌂      ", 4)},
{TV(0x000000001ffffffful, u"λλλλ☺     ", 5)},
{TV(0x000000003ffffffful, u"λλλλ♥     ", 5)},
{TV(0x000000007ffffffful, u"λλλλ•     ", 5)},
{TV(0x00000000fffffffful, u"λλλλ☼     ", 5)},
{TV(0x00000001fffffffful, u"λλλλ▼     ", 5)},
{TV(0x00000003fffffffful, u"λλλλ⁇     ", 5)},
{TV(0x00000007fffffffful, u"λλλλ⌂     ", 5)},
{TV(0x0000000ffffffffful, u"λλλλλ☺    ", 6)},
{TV(0x0000001ffffffffful, u"λλλλλ♥    ", 6)},
{TV(0x0000003ffffffffful, u"λλλλλ•    ", 6)},
{TV(0x0000007ffffffffful, u"λλλλλ☼    ", 6)},
{TV(0x000000fffffffffful, u"λλλλλ▼    ", 6)},
{TV(0x000001fffffffffful, u"λλλλλ⁇    ", 6)},
{TV(0x000003fffffffffful, u"λλλλλ⌂    ", 6)},
{TV(0x000007fffffffffful, u"λλλλλλ☺   ", 7)},
{TV(0x00000ffffffffffful, u"λλλλλλ♥   ", 7)},
{TV(0x00001ffffffffffful, u"λλλλλλ•   ", 7)},
{TV(0x00003ffffffffffful, u"λλλλλλ☼   ", 7)},
{TV(0x00007ffffffffffful, u"λλλλλλ▼   ", 7)},
{TV(0x0000fffffffffffful, u"λλλλλλ⁇   ", 7)},
{TV(0x0001fffffffffffful, u"λλλλλλ⌂   ", 7)},
{TV(0x0003fffffffffffful, u"λλλλλλλ☺  ", 8)},
{TV(0x0007fffffffffffful, u"λλλλλλλ♥  ", 8)},
{TV(0x000ffffffffffffful, u"λλλλλλλ•  ", 8)},
{TV(0x001ffffffffffffful, u"λλλλλλλ☼  ", 8)},
{TV(0x003ffffffffffffful, u"λλλλλλλ▼  ", 8)},
{TV(0x007ffffffffffffful, u"λλλλλλλ⁇  ", 8)},
{TV(0x00fffffffffffffful, u"λλλλλλλ⌂  ", 8)},
{TV(0x01fffffffffffffful, u"λλλλλλλλ☺ ", 9)},
{TV(0x03fffffffffffffful, u"λλλλλλλλ♥ ", 9)},
{TV(0x07fffffffffffffful, u"λλλλλλλλ• ", 9)},
{TV(0x0ffffffffffffffful, u"λλλλλλλλ☼ ", 9)},
{TV(0x1ffffffffffffffful, u"λλλλλλλλ▼ ", 9)},
{TV(0x3ffffffffffffffful, u"λλλλλλλλ⁇ ", 9)},
{TV(0x7ffffffffffffffful, u"λλλλλλλλ⌂ ", 9)},
{TV(0xfffffffffffffffful, u"λλλλλλλλλ☺", 10)},
};
const struct ZigzagTestVectors {
const char *file;
int line;
const char *xcode;
int64_t x;
const char *bcode;
uint16_t b[11];
const char *icode;
uint8_t i;
} kz[] = {
{TV(0, u" ", 1)},
{TV(1, u"", 1)},
{TV(-1, u"", 1)},
{TV(2, u"", 1)},
{TV(-2, u"", 1)},
{TV(4, u"", 1)},
{TV(-4, u"", 1)},
{TV(8, u"", 1)},
{TV(-8, u"", 1)},
{TV(16, u" ", 1)},
{TV(-16, u"", 1)},
{TV(32, u"@", 1)},
{TV(-32, u"", 1)},
{TV(64, u"Ç☺", 2)},
{TV(-64, u"", 1)},
{TV(128, u"Ç☻", 2)},
{TV(-128, u"λ☺", 2)},
{TV(256, u"Ç♦", 2)},
{TV(-256, u"λ♥", 2)},
{TV(512, u"Ç◘", 2)},
{TV(-512, u"λ•", 2)},
{TV(1024, u"Ç►", 2)},
{TV(-1024, u"λ☼", 2)},
{TV(2048, u"Ç ", 2)},
{TV(-2048, u"λ▼", 2)},
{TV(4096, u"Ç@", 2)},
{TV(-4096, u"λ⁇", 2)},
{TV(8192, u"ÇÇ☺", 3)},
{TV(-8192, u"λ⌂", 2)},
{TV(16384, u"ÇÇ☻", 3)},
{TV(-16384, u"λλ☺", 3)},
{TV(32768, u"ÇÇ♦", 3)},
{TV(-32768, u"λλ♥", 3)},
{TV(65536, u"ÇÇ◘", 3)},
{TV(-65536, u"λλ•", 3)},
{TV(131072, u"ÇÇ►", 3)},
{TV(-131072, u"λλ☼", 3)},
{TV(262144, u"ÇÇ ", 3)},
{TV(-262144, u"λλ▼", 3)},
{TV(524288, u"ÇÇ@", 3)},
{TV(-524288, u"λλ⁇", 3)},
{TV(1048576, u"ÇÇÇ☺", 4)},
{TV(-1048576, u"λλ⌂", 3)},
{TV(2097152, u"ÇÇÇ☻", 4)},
{TV(-2097152, u"λλλ☺", 4)},
{TV(4194304, u"ÇÇÇ♦", 4)},
{TV(-4194304, u"λλλ♥", 4)},
{TV(8388608, u"ÇÇÇ◘", 4)},
{TV(-8388608, u"λλλ•", 4)},
{TV(16777216, u"ÇÇÇ►", 4)},
{TV(-16777216, u"λλλ☼", 4)},
{TV(33554432, u"ÇÇÇ ", 4)},
{TV(-33554432, u"λλλ▼", 4)},
{TV(67108864, u"ÇÇÇ@", 4)},
{TV(-67108864, u"λλλ⁇", 4)},
{TV(134217728, u"ÇÇÇÇ☺", 5)},
{TV(-134217728, u"λλλ⌂", 4)},
{TV(268435456, u"ÇÇÇÇ☻", 5)},
{TV(-268435456, u"λλλλ☺", 5)},
{TV(536870912, u"ÇÇÇÇ♦", 5)},
{TV(-536870912, u"λλλλ♥", 5)},
{TV(1073741824, u"ÇÇÇÇ◘", 5)},
{TV(-1073741824, u"λλλλ•", 5)},
{TV(2147483648, u"ÇÇÇÇ►", 5)},
{TV(-2147483648, u"λλλλ☼", 5)},
{TV(4294967296, u"ÇÇÇÇ ", 5)},
{TV(-4294967296, u"λλλλ▼", 5)},
{TV(8589934592, u"ÇÇÇÇ@", 5)},
{TV(-8589934592, u"λλλλ⁇", 5)},
{TV(17179869184, u"ÇÇÇÇÇ☺", 6)},
{TV(-17179869184, u"λλλλ⌂", 5)},
{TV(34359738368, u"ÇÇÇÇÇ☻", 6)},
{TV(-34359738368, u"λλλλλ☺", 6)},
{TV(68719476736, u"ÇÇÇÇÇ♦", 6)},
{TV(-68719476736, u"λλλλλ♥", 6)},
{TV(137438953472, u"ÇÇÇÇÇ◘", 6)},
{TV(-137438953472, u"λλλλλ•", 6)},
{TV(274877906944, u"ÇÇÇÇÇ►", 6)},
{TV(-274877906944, u"λλλλλ☼", 6)},
{TV(549755813888, u"ÇÇÇÇÇ ", 6)},
{TV(-549755813888, u"λλλλλ▼", 6)},
{TV(1099511627776, u"ÇÇÇÇÇ@", 6)},
{TV(-1099511627776, u"λλλλλ⁇", 6)},
{TV(2199023255552, u"ÇÇÇÇÇÇ☺", 7)},
{TV(-2199023255552, u"λλλλλ⌂", 6)},
{TV(4398046511104, u"ÇÇÇÇÇÇ☻", 7)},
{TV(-4398046511104, u"λλλλλλ☺", 7)},
{TV(8796093022208, u"ÇÇÇÇÇÇ♦", 7)},
{TV(-8796093022208, u"λλλλλλ♥", 7)},
{TV(17592186044416, u"ÇÇÇÇÇÇ◘", 7)},
{TV(-17592186044416, u"λλλλλλ•", 7)},
{TV(35184372088832, u"ÇÇÇÇÇÇ►", 7)},
{TV(-35184372088832, u"λλλλλλ☼", 7)},
{TV(70368744177664, u"ÇÇÇÇÇÇ ", 7)},
{TV(-70368744177664, u"λλλλλλ▼", 7)},
{TV(140737488355328, u"ÇÇÇÇÇÇ@", 7)},
{TV(-140737488355328, u"λλλλλλ⁇", 7)},
{TV(281474976710656, u"ÇÇÇÇÇÇÇ☺", 8)},
{TV(-281474976710656, u"λλλλλλ⌂", 7)},
{TV(562949953421312, u"ÇÇÇÇÇÇÇ☻", 8)},
{TV(-562949953421312, u"λλλλλλλ☺", 8)},
{TV(1125899906842624, u"ÇÇÇÇÇÇÇ♦", 8)},
{TV(-1125899906842624, u"λλλλλλλ♥", 8)},
{TV(2251799813685248, u"ÇÇÇÇÇÇÇ◘", 8)},
{TV(-2251799813685248, u"λλλλλλλ•", 8)},
{TV(4503599627370496, u"ÇÇÇÇÇÇÇ►", 8)},
{TV(-4503599627370496, u"λλλλλλλ☼", 8)},
{TV(9007199254740992, u"ÇÇÇÇÇÇÇ ", 8)},
{TV(-9007199254740992, u"λλλλλλλ▼", 8)},
{TV(18014398509481984, u"ÇÇÇÇÇÇÇ@", 8)},
{TV(-18014398509481984, u"λλλλλλλ⁇", 8)},
{TV(36028797018963968, u"ÇÇÇÇÇÇÇÇ☺", 9)},
{TV(-36028797018963968, u"λλλλλλλ⌂", 8)},
{TV(72057594037927936, u"ÇÇÇÇÇÇÇÇ☻", 9)},
{TV(-72057594037927936, u"λλλλλλλλ☺", 9)},
{TV(144115188075855872, u"ÇÇÇÇÇÇÇÇ♦", 9)},
{TV(-144115188075855872, u"λλλλλλλλ♥", 9)},
{TV(288230376151711744, u"ÇÇÇÇÇÇÇÇ◘", 9)},
{TV(-288230376151711744, u"λλλλλλλλ•", 9)},
{TV(576460752303423488, u"ÇÇÇÇÇÇÇÇ►", 9)},
{TV(-576460752303423488, u"λλλλλλλλ☼", 9)},
{TV(1152921504606846976, u"ÇÇÇÇÇÇÇÇ ", 9)},
{TV(-1152921504606846976, u"λλλλλλλλ▼", 9)},
{TV(2305843009213693952, u"ÇÇÇÇÇÇÇÇ@", 9)},
{TV(-2305843009213693952, u"λλλλλλλλ⁇", 9)},
{TV(4611686018427387904, u"ÇÇÇÇÇÇÇÇÇ☺", 10)},
{TV(-4611686018427387904, u"λλλλλλλλ⌂", 9)},
{TV(INT64_MIN, u"λλλλλλλλλ☺", 10)},
{TV(INT64_MAX, u"■λλλλλλλλ☺", 10)}, /* wut */
};
TEST(writevint, test) {
size_t i;
uint8_t b[10], *p;
for (i = 0; i < ARRAYLEN(kv); ++i) {
memset(b, 0, sizeof(b));
p = writevint(b, kv[i].x);
__TEST_EQ(assert, kz[i].file, kz[i].line, __FUNCTION__, kz[i].icode,
kz[i].xcode, kv[i].i, p - b);
assertBinaryEquals$cp437(kz[i].file, kz[i].line, __FUNCTION__, kv[i].b, b,
strlen(kv[i].b), "", false);
}
}
TEST(readvint, test) {
size_t i;
uint64_t x;
uint8_t *b, *p;
for (i = 0; i < ARRAYLEN(kv); ++i) {
b = gc(unbingstr(kv[i].b));
p = readvint(b, b + strlen(kv[i].b), &x);
__TEST_EQ(assert, kv[i].file, kv[i].line, __FUNCTION__, kv[i].icode,
kv[i].xcode, kv[i].i, (intptr_t)(p - b));
assertBinaryEquals$cp437(kv[i].file, kv[i].line, __FUNCTION__, kv[i].b, b,
strlen(kv[i].b), "", false);
}
}
TEST(writesint, test) {
size_t i;
uint8_t b[10], *p;
for (i = 0; i < ARRAYLEN(kz); ++i) {
memset(b, 0, sizeof(b));
p = writesint(b, kz[i].x);
__TEST_EQ(assert, kz[i].file, kz[i].line, __FUNCTION__, kz[i].icode,
kz[i].xcode, kz[i].i, (intptr_t)(p - b));
assertBinaryEquals$cp437(kz[i].file, kz[i].line, __FUNCTION__, kz[i].b, b,
strlen(kz[i].b), "", false);
}
}
TEST(readsint, test) {
size_t i;
int64_t x;
uint8_t *b, *p;
for (i = 0; i < ARRAYLEN(kz); ++i) {
b = gc(unbingstr(kz[i].b));
p = readsint(b, b + strlen(kz[i].b), &x);
__TEST_EQ(assert, kz[i].file, kz[i].line, __FUNCTION__, kz[i].icode,
kz[i].xcode, kz[i].i, (intptr_t)(p - b));
assertBinaryEquals$cp437(kz[i].file, kz[i].line, __FUNCTION__, kz[i].b, b,
strlen(kz[i].b), "", false);
}
}