132 lines
3.0 KiB
C
132 lines
3.0 KiB
C
#include "test.h"
|
|
|
|
void
|
|
str_init_utf8(struct ct *t)
|
|
{
|
|
static char badtail[] = { 'a', (char)0x80 };
|
|
static char incomplete[] = { (char)0xea, (char)0xb0 };
|
|
static char overlong[] = { (char)0xc0, (char)0xaf };
|
|
static char outofrange[] = {
|
|
(char)0xf4, (char)0x90, (char)0x80, (char)0x80,
|
|
};
|
|
static char surrogate[] = {
|
|
(char)0xed, (char)0xa0, (char)0x80,
|
|
};
|
|
static char unexpected[] = { (char)0x80 };
|
|
static const struct {
|
|
char *name;
|
|
char *src;
|
|
int n;
|
|
int ok;
|
|
char *want;
|
|
} cases[] = {
|
|
{ "canonical Runeerror", "\xef\xbf\xbd", 3, 1, "\xef\xbf\xbd" },
|
|
{ "incomplete", incomplete, sizeof incomplete, 0, "" },
|
|
{ "unexpected continuation", unexpected, sizeof unexpected, 0, "" },
|
|
{ "overlong", overlong, sizeof overlong, 0, "" },
|
|
{ "surrogate", surrogate, sizeof surrogate, 0, "" },
|
|
{ "out of range", outofrange, sizeof outofrange, 0, "" },
|
|
{ "bad tail", badtail, sizeof badtail, 0, "" },
|
|
};
|
|
char full[Maxrunes+2];
|
|
Str s;
|
|
int i;
|
|
|
|
s = mkstr("A한😀");
|
|
CT_EQ_INT(t, 3, s.n);
|
|
checkstr(t, "round trip", "A한😀", &s);
|
|
for(i = 0; i < nelem(cases); i++){
|
|
memset(&s, 0xa5, sizeof s);
|
|
if(sinit(&s, cases[i].src, cases[i].n) != cases[i].ok)
|
|
CT_ERRORF(t, "%s: wrong validity", cases[i].name);
|
|
checkstr(t, cases[i].name, cases[i].want, &s);
|
|
}
|
|
memset(full, 'a', sizeof full);
|
|
full[sizeof full-1] = '\0';
|
|
CT_CHECK(t, !sinit(&s, full, strlen(full)));
|
|
CT_EQ_INT(t, 0, s.n);
|
|
}
|
|
|
|
void
|
|
str_edit_and_alias(struct ct *t)
|
|
{
|
|
Str s;
|
|
int i;
|
|
|
|
s = mkstr("ab");
|
|
sappend(&s, &s);
|
|
checkstr(t, "self append", "abab", &s);
|
|
for(i = 0; i < 40; i++)
|
|
s.r[i] = 'a' + i % 26;
|
|
s.n = 40;
|
|
sappend(&s, &s);
|
|
CT_EQ_INT(t, Maxrunes, s.n);
|
|
for(i = 0; i < 24; i++)
|
|
if(s.r[40+i] != s.r[i])
|
|
CT_ERRORF(t, "capped self append differs at rune %d", i);
|
|
}
|
|
|
|
void
|
|
str_utf8_capacity(struct ct *t)
|
|
{
|
|
static const struct {
|
|
int size;
|
|
int n;
|
|
char *want;
|
|
} cases[] = {
|
|
{ 0, 0, nil },
|
|
{ 1, 0, "" },
|
|
{ 2, 1, "a" },
|
|
{ 3, 1, "a" },
|
|
{ 4, 1, "a" },
|
|
{ 5, 4, "a한" },
|
|
{ 6, 5, "a한b" },
|
|
};
|
|
char buf[16];
|
|
Str s;
|
|
int i, n;
|
|
|
|
s = mkstr("a한b");
|
|
for(i = 0; i < nelem(cases); i++){
|
|
memset(buf, 'Z', sizeof buf);
|
|
n = stoutf(&s, buf, cases[i].size);
|
|
if(n != cases[i].n)
|
|
CT_ERRORF(t, "size %d: want length %d, got %d",
|
|
cases[i].size, cases[i].n, n);
|
|
if(cases[i].size == 0){
|
|
CT_EQ_INT(t, 'Z', buf[0]);
|
|
continue;
|
|
}
|
|
if(strcmp(cases[i].want, buf) != 0)
|
|
CT_ERRORF(t, "size %d: want \"%s\", got \"%s\"",
|
|
cases[i].size, cases[i].want, buf);
|
|
CT_EQ_INT(t, 'Z', buf[cases[i].size]);
|
|
}
|
|
|
|
s = mkstr("😀");
|
|
memset(buf, 'Z', sizeof buf);
|
|
CT_EQ_INT(t, 0, stoutf(&s, buf, 4));
|
|
CT_EQ_STR(t, "", buf);
|
|
CT_EQ_INT(t, 4, stoutf(&s, buf, 5));
|
|
CT_EQ_STR(t, "😀", buf);
|
|
CT_EQ_INT(t, 'Z', buf[5]);
|
|
}
|
|
|
|
void
|
|
str_invalid_and_full_appends(struct ct *t)
|
|
{
|
|
Str s;
|
|
int i;
|
|
|
|
CT_CHECK(t, !sinit(&s, nil, 1));
|
|
CT_EQ_INT(t, 0, s.n);
|
|
CT_CHECK(t, !sinit(&s, "x", -1));
|
|
CT_EQ_INT(t, 0, s.n);
|
|
for(i = 0; i < Maxrunes; i++)
|
|
s.r[i] = 'a';
|
|
s.n = Maxrunes;
|
|
sputr(&s, 'z');
|
|
CT_EQ_INT(t, Maxrunes, s.n);
|
|
CT_EQ_INT(t, 'a', s.r[Maxrunes-1]);
|
|
}
|