blob: e3b4f5a197e7a8142de8ae3de031cf5b701da322 [file]
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>
#include "collation_data_lookup.h"
#include "collation_key.h"
static void
print_collation_key (const char *key, size_t length)
{
unsigned const char *p;
for (p = (unsigned const char *) key;
p < (unsigned const char *) key + length;
p += 2)
{
fprintf (stderr, "%02x%02x ", p[0], p[1]);
}
fprintf (stderr, "\n");
}
static void
string_save (char **buf, size_t *buf_size, const char *string)
{
size_t len = strlen (string);
if (*buf_size < len)
{
*buf = realloc (*buf, len + 1);
*buf_size = len + 1;
}
memmove (*buf, string, len + 1);
}
static int trace;
static int variable_shifted;
static int quiet;
static void
print_usage (void)
{
fprintf (stderr,
"usage: collation_test [--trace] CollationTest_NON_IGNORABLE.txt\n");
}
int
main (int argc, char *argv[])
{
struct option long_options[] = {
{"trace", no_argument, 0, 't'},
{"shifted", no_argument, 0, 's'},
{"quiet", no_argument, 0, 'q'},
{"help", no_argument, 0, '?'},
{0, 0, 0, 0}
};
int opt;
while ((opt = getopt_long (argc, argv, "ts?", long_options, NULL)) != -1)
{
switch (opt)
{
case 't':
trace = 1;
break;
case 's':
variable_shifted = 1;
break;
case 'q':
quiet = 1;
break;
case '?':
print_usage ();
exit (0);
default:
print_usage ();
exit (1);
}
}
if (optind != argc - 1)
{
print_usage ();
exit (1);
}
const char *filename = argv[optind];
FILE *file = fopen (filename, "r");
if (!file)
{
fprintf (stderr, "could not open %s\n", filename);
exit (1);
}
char *line1 = NULL, *line2 = NULL;
size_t line1_size = 0, line2_size = 0;
ssize_t nread;
char *sort_key1 = 0, *sort_key2 = 0;
size_t sort_key1_len = 0, sort_key2_len = 0;
size_t sort_key1_size = 0;
long int line_count = 0;
long int fail_count = 0;
long int skip_count = 0;
Collation_choice collation = unicoll_default ();
collation = unicoll_set_variable (collation,
variable_shifted ? UNICOLL_VARIABLE_SHIFTED
: UNICOLL_VARIABLE_NONIGNORABLE);
/* collation = unicoll_set_normalization (collation, 0); */
while (1)
{
next_line:
nread = getline (&line2, &line2_size, file);
if (nread == -1)
break;
char *semicolon;
if ((semicolon = strchr (line2, ';')))
*semicolon = '\0';
if (trace)
fprintf (stderr, "read line <%s>\n", line2);
line_count++;
#define TEST_MAX_LENGTH 16
char32_t codepoints[TEST_MAX_LENGTH];
size_t length = 0;
char *pline = line2;
char *qline;
while (length < TEST_MAX_LENGTH)
{
unsigned long val = strtoul (pline, &qline, 16);
if (qline == pline)
break;
pline = qline;
if (val > 0x10FFFF)
{
fprintf (stderr, "Error: invalid codepoint %lx\n", val);
exit (1);
}
if (val >= 0xD800 && val <= 0xDFFF)
{
/* UTF-16 surrogate codepoint. Skip this line. */
if (trace)
printf ("skip test of surrogate codepoint\n");
skip_count++;
goto next_line;
}
codepoints[length++] = (char32_t) val;
}
if (length == TEST_MAX_LENGTH)
{
fprintf (stderr, "Max codepoint length exceeded!\n");
exit (1);
}
#define BUF_LEN 1000
static char buffer[BUF_LEN];
sort_key2_len = BUF_LEN;
sort_key2 = u32_make_collation_key (collation, codepoints, length,
buffer, &sort_key2_len);
/* We expect that sort_key1 <= sort_key1. */
if (sort_key1 && sort_key2 && strcmp (sort_key1, sort_key2) > 0)
{
if (!quiet)
{
fprintf (stderr, "Test fail at line %ld\n", line_count);
fprintf (stderr, "line 1: %s\n", line1);
fprintf (stderr, "line 2: %s\n", line2);
fprintf (stderr, "Sort key 1: ");
print_collation_key (sort_key1, sort_key1_len);
fprintf (stderr, "Sort key 2: ");
print_collation_key (sort_key2, sort_key2_len);
fprintf (stderr, "\n");
}
fail_count++;
}
string_save (&sort_key1, &sort_key1_size, sort_key2);
sort_key1_len = sort_key2_len;
string_save (&line1, &line1_size, line2);
}
if (fail_count == 0)
{
printf ("All tests passed\n");
printf ("(Skipped %ld)\n", skip_count);
exit (0);
}
else
{
printf ("Total fails: %ld out of %ld\n", fail_count, line_count);
printf ("(Skipped %ld)\n", skip_count);
exit (1);
}
}