PostgreSQL Source Code git master
Loading...
Searching...
No Matches
case_test.c File Reference
#include "postgres_fe.h"
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wctype.h>
#include "common/unicode_case.h"
#include "common/unicode_category.h"
#include "common/unicode_version.h"
#include "mb/pg_wchar.h"
Include dependency graph for case_test.c:

Go to the source code of this file.

Data Structures

struct  WordBoundaryState
 

Macros

#define BUFSZ   256
 

Typedefs

typedef size_t(* TestFunc) (char *dst, size_t dstsize, const char *src, size_t srclen)
 

Functions

static size_t initcap_wbnext (void *state)
 
static void test_convert (TestFunc tfunc, const char *test_string, const char *expected)
 
static size_t tfunc_lower (char *dst, size_t dstsize, const char *src, size_t srclen)
 
static size_t tfunc_title (char *dst, size_t dstsize, const char *src, size_t srclen)
 
static size_t tfunc_upper (char *dst, size_t dstsize, const char *src, size_t srclen)
 
static size_t tfunc_fold (char *dst, size_t dstsize, const char *src, size_t srclen)
 
static void test_convert_case (void)
 
int main (int argc, char **argv)
 

Macro Definition Documentation

◆ BUFSZ

#define BUFSZ   256

Definition at line 30 of file case_test.c.

Typedef Documentation

◆ TestFunc

Definition at line 36 of file case_test.c.

Function Documentation

◆ initcap_wbnext()

static size_t initcap_wbnext ( void state)
static

Definition at line 51 of file case_test.c.

52{
54
55 while (wbstate->offset < wbstate->len &&
56 wbstate->str[wbstate->offset] != '\0')
57 {
58 char32_t u = utf8_to_unicode((const unsigned char *) wbstate->str +
59 wbstate->offset);
60 bool curr_alnum = pg_u_isalnum(u, wbstate->posix);
61
62 if (!wbstate->init || curr_alnum != wbstate->prev_alnum)
63 {
64 size_t prev_offset = wbstate->offset;
65
66 wbstate->init = true;
67 wbstate->offset += unicode_utf8len(u);
68 wbstate->prev_alnum = curr_alnum;
69 return prev_offset;
70 }
71
72 wbstate->offset += unicode_utf8len(u);
73 }
74
75 return wbstate->len;
76}
static char32_t utf8_to_unicode(const unsigned char *c)
Definition mbprint.c:53
static int unicode_utf8len(char32_t c)
Definition pg_wchar.h:460
static int fb(int x)
bool pg_u_isalnum(char32_t code, bool posix)

References fb(), pg_u_isalnum(), unicode_utf8len(), and utf8_to_unicode().

Referenced by tfunc_title().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 359 of file case_test.c.

360{
361#ifdef USE_ICU
362 UErrorCode status = U_ZERO_ERROR;
363
364 /*
365 * Disable ICU's word break adjustment for titlecase to match the expected
366 * behavior of unicode_strtitle().
367 */
369 if (U_FAILURE(status))
370 {
371 printf("case_test: failure opening UCaseMap: %s\n",
372 u_errorName(status));
373 exit(1);
374 }
375#endif
376
377 printf("case_test: Postgres Unicode version:\t%s\n", PG_UNICODE_VERSION);
378#ifdef USE_ICU
379 printf("case_test: ICU Unicode version:\t\t%s\n", U_UNICODE_VERSION);
380 test_icu();
381#else
382 printf("case_test: ICU not available; skipping\n");
383#endif
384
386
387#ifdef USE_ICU
389#endif
390 exit(0);
391}
static void test_convert_case(void)
Definition case_test.c:305
#define printf(...)
Definition port.h:267
static enum CaseMapResult casemap(char32_t u1, CaseKind casekind, bool full, const char *src, size_t srclen, size_t srcoff, char32_t *simple, const char32_t **special)
#define PG_UNICODE_VERSION

References casemap(), fb(), PG_UNICODE_VERSION, printf, and test_convert_case().

◆ test_convert()

static void test_convert ( TestFunc  tfunc,
const char test_string,
const char expected 
)
static

Definition at line 211 of file case_test.c.

212{
213 size_t src1len = strlen(test_string);
214 size_t dst1len = strlen(expected);
215 size_t dst2len = strlen(expected) + 1; /* NUL-terminated */
216 char *src1 = malloc(src1len);
217 char *dst1 = malloc(dst1len);
218 char *dst2 = malloc(dst2len);
219 size_t needed;
220
221 memcpy(src1, test_string, src1len); /* not NUL-terminated */
222
223 /* destination is not NUL-terminated */
224 memset(dst1, 0x7F, dst1len);
226 if (needed != strlen(expected))
227 {
228 printf("case_test: convert_case test1 FAILURE: '%s' needed %zu expected %zu\n",
230 exit(1);
231 }
232 if (memcmp(dst1, expected, dst1len) != 0)
233 {
234 printf("case_test: convert_case test1 FAILURE: test: '%s' result: '%.*s' expected: '%s'\n",
236 exit(1);
237 }
238
239 /* destination is NUL-terminated */
240 memset(dst2, 0x7F, dst2len);
242 if (needed != strlen(expected))
243 {
244 printf("case_test: convert_case test2 FAILURE: '%s' needed %zu expected %zu\n",
246 exit(1);
247 }
248 if (strcmp(dst2, expected) != 0)
249 {
250 printf("case_test: convert_case test2 FAILURE: test: '%s' result: '%s' expected: '%s'\n",
252 exit(1);
253 }
254
255 free(src1);
256 free(dst1);
257 free(dst2);
258}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define free(a)
#define malloc(a)

References fb(), free, malloc, memcpy(), and printf.

Referenced by test_convert_case().

◆ test_convert_case()

static void test_convert_case ( void  )
static

Definition at line 305 of file case_test.c.

306{
307 size_t needed;
308 size_t consumed;
309
310 /* test string with no case changes */
311 test_convert(tfunc_lower, "√∞", "√∞");
312 /* test adjust-to-cased behavior */
313 test_convert(tfunc_title, "abc 123xyz", "Abc 123xyz");
314 /* test string with case changes */
315 test_convert(tfunc_upper, "abc", "ABC");
316 /* test string with case changes and byte length changes */
317 test_convert(tfunc_lower, "ȺȺȺ", "ⱥⱥⱥ");
318 /* test special case conversions */
319 test_convert(tfunc_upper, "ß", "SS");
320 test_convert(tfunc_lower, "ıiIİ", "ıiii\u0307");
321 test_convert(tfunc_upper, "ıiIİ", "IIIİ");
322 test_convert(tfunc_fold, "ıiIİ", "ıiii\u0307");
323 /* test final sigma */
324 test_convert(tfunc_lower, "σςΣ ΣΣΣ", "σςς σσς");
325 test_convert(tfunc_lower, "σς'Σ' ΣΣ'Σ'", "σς'ς' σσ'ς'");
326 test_convert(tfunc_title, "σςΣ ΣΣΣ", "Σςς Σσς");
327 test_convert(tfunc_fold, "σςΣ ΣΣΣ", "σσσ σσσ");
328 /* test that alphanumerics are word characters */
329 test_convert(tfunc_title, "λλ", "Λλ");
330 test_convert(tfunc_title, "1a", "1a");
331 /* U+FF11 FULLWIDTH ONE is alphanumeric for full case mapping */
332 test_convert(tfunc_title, "\uFF11a", "\uFF11a");
333
334 /* invalid UTF8: truncated multibyte sequence */
335 needed = unicode_strfold(NULL, 0, "abc\xCE", 4, &consumed, false);
336 Assert(needed == 3 && consumed == 3);
337 /* invalid UTF8: leading byte invalid length */
338 needed = unicode_strfold(NULL, 0, "abc\xF8xyz", 7, &consumed, false);
339 Assert(needed == 3 && consumed == 3);
340
341#ifdef USE_ICU
342 icu_test_full("");
343 icu_test_full("ȺȺȺ");
344 icu_test_full("ßßß");
345 icu_test_full("√∞");
346 icu_test_full("a b");
347 icu_test_full("abc 123xyz");
348 icu_test_full("σςΣ ΣΣΣ");
349 icu_test_full("ıiIİ");
350 icu_test_full("\uFF11a");
351 /* test <alpha><iota_subscript><acute> */
352 icu_test_full("\u0391\u0345\u0301");
353#endif
354
355 printf("case_test: convert_case: success\n");
356}
#define Assert(condition)
Definition c.h:1002
static void test_convert(TestFunc tfunc, const char *test_string, const char *expected)
Definition case_test.c:211
static size_t tfunc_lower(char *dst, size_t dstsize, const char *src, size_t srclen)
Definition case_test.c:261
static size_t tfunc_fold(char *dst, size_t dstsize, const char *src, size_t srclen)
Definition case_test.c:296
static size_t tfunc_upper(char *dst, size_t dstsize, const char *src, size_t srclen)
Definition case_test.c:287
static size_t tfunc_title(char *dst, size_t dstsize, const char *src, size_t srclen)
Definition case_test.c:270
size_t unicode_strfold(char *dst, size_t dstsize, const char *src, size_t srclen, size_t *pconsumed, bool full)

References Assert, fb(), printf, test_convert(), tfunc_fold(), tfunc_lower(), tfunc_title(), tfunc_upper(), and unicode_strfold().

Referenced by main().

◆ tfunc_fold()

static size_t tfunc_fold ( char dst,
size_t  dstsize,
const char src,
size_t  srclen 
)
static

Definition at line 296 of file case_test.c.

298{
299 size_t consumed;
300
301 return unicode_strfold(dst, dstsize, src, srclen, &consumed, true);
302}

References fb(), and unicode_strfold().

Referenced by test_convert_case().

◆ tfunc_lower()

static size_t tfunc_lower ( char dst,
size_t  dstsize,
const char src,
size_t  srclen 
)
static

Definition at line 261 of file case_test.c.

263{
264 size_t consumed;
265
266 return unicode_strlower(dst, dstsize, src, srclen, &consumed, true);
267}
size_t unicode_strlower(char *dst, size_t dstsize, const char *src, size_t srclen, size_t *pconsumed, bool full)

References fb(), and unicode_strlower().

Referenced by test_convert_case().

◆ tfunc_title()

static size_t tfunc_title ( char dst,
size_t  dstsize,
const char src,
size_t  srclen 
)
static

Definition at line 270 of file case_test.c.

272{
273 size_t consumed;
274 struct WordBoundaryState wbstate = {
275 .str = src,
276 .len = srclen,
277 .offset = 0,
278 .init = false,
279 .prev_alnum = false,
280 };
281
282 return unicode_strtitle(dst, dstsize, src, srclen, &consumed, true,
284}
static size_t initcap_wbnext(void *state)
Definition case_test.c:51
size_t unicode_strtitle(char *dst, size_t dstsize, const char *src, size_t srclen, size_t *pconsumed, bool full, WordBoundaryNext wbnext, void *wbstate)

References fb(), initcap_wbnext(), WordBoundaryState::str, and unicode_strtitle().

Referenced by test_convert_case().

◆ tfunc_upper()

static size_t tfunc_upper ( char dst,
size_t  dstsize,
const char src,
size_t  srclen 
)
static

Definition at line 287 of file case_test.c.

289{
290 size_t consumed;
291
292 return unicode_strupper(dst, dstsize, src, srclen, &consumed, true);
293}
size_t unicode_strupper(char *dst, size_t dstsize, const char *src, size_t srclen, size_t *pconsumed, bool full)

References fb(), and unicode_strupper().

Referenced by test_convert_case().