mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
209 lines
5.4 KiB
C
209 lines
5.4 KiB
C
/*************************************************
|
|
* PCRE2 POSIX interface test program *
|
|
*************************************************/
|
|
|
|
/*
|
|
Written by Philip Hazel, December 2022
|
|
Copyright (c) 2022
|
|
File last edited: December 2022
|
|
|
|
This program tests the POSIX wrapper to the PCRE2 regular expression library.
|
|
The main PCRE2 test program is pcre2test, which also tests these function
|
|
calls. This little program is needed to test the case where the client includes
|
|
pcre2posix.h but not pcre2.h, mainly to make sure that it builds successfully.
|
|
However, the code is written as a flexible test program to which extra tests
|
|
can be added.
|
|
|
|
Compile with -lpcre2-posix -lpcre2-8
|
|
|
|
If run with no options, there is no output on success, and the return code is
|
|
zero. If any test fails there is output to stderr, and the return code is 1.
|
|
|
|
For testing purposes, the "-v" option causes verification output to be written
|
|
to stdout. */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "pcre2posix.h"
|
|
|
|
#define CAPCOUNT 5 /* Number of captures supported */
|
|
#define PRINTF if (v) printf /* Shorthand for testing output */
|
|
|
|
/* This vector contains compiler flags for each pattern that is tested. */
|
|
|
|
static int cflags[] = {
|
|
0, /* Test 0 */
|
|
REG_ICASE, /* Test 1 */
|
|
0, /* Test 2 */
|
|
REG_NEWLINE, /* Test 3 */
|
|
0 /* Test 4 */
|
|
};
|
|
|
|
/* This vector contains match flags for each pattern that is tested. */
|
|
|
|
static int mflags[] = {
|
|
0, /* Test 0 */
|
|
0, /* Test 1 */
|
|
0, /* Test 2 */
|
|
REG_NOTBOL, /* Test 3 */
|
|
0 /* Test 4 */
|
|
};
|
|
|
|
/* Automate the number of patterns */
|
|
|
|
#define count (int)(sizeof(cflags)/sizeof(int))
|
|
|
|
/* The data for each pattern consists of a pattern string, followed by any
|
|
number of subject strings, terminated by NULL. Some tests share data, but use
|
|
different flags. */
|
|
|
|
static const char *data0_1[] = { "posix", "lower posix", "upper POSIX", NULL };
|
|
static const char *data2_3[] = { "^(cat|dog)", "catastrophic\ncataclysm",
|
|
"dogfight", "no animals", NULL };
|
|
static const char *data4[] = { "*badpattern", NULL };
|
|
|
|
/* Index the data strings */
|
|
|
|
static char **data[] = {
|
|
(char **)(&data0_1),
|
|
(char **)(&data0_1),
|
|
(char **)(&data2_3),
|
|
(char **)(&data2_3),
|
|
(char **)(&data4)
|
|
};
|
|
|
|
/* The expected results for each pattern consist of a compiler return code,
|
|
optionally followed, for each subject string, by a match return code and, for a
|
|
successful match, up to CAPCOUNT pairs of returned match data. */
|
|
|
|
static int results0[] = {
|
|
0, /* Compiler rc */
|
|
0, 6, 11, /* 1st match */
|
|
REG_NOMATCH /* 2nd match */
|
|
};
|
|
|
|
static int results1[] = {
|
|
0, /* Compiler rc */
|
|
0, 6, 11, /* 1st match */
|
|
0, 6, 11 /* 2nd match */
|
|
};
|
|
|
|
static int results2[] = {
|
|
0, /* Compiler rc */
|
|
0, 0, 3, 0, 3, /* 1st match */
|
|
0, 0, 3, 0, 3, /* 2nd match */
|
|
REG_NOMATCH /* 3rd match */
|
|
};
|
|
|
|
static int results3[] = {
|
|
0, /* Compiler rc */
|
|
0, 13, 16, 13, 16, /* 1st match */
|
|
REG_NOMATCH, /* 2nd match */
|
|
REG_NOMATCH /* 3rd match */
|
|
};
|
|
|
|
static int results4[] = {
|
|
REG_BADRPT /* Compiler rc */
|
|
};
|
|
|
|
/* Index the result vectors */
|
|
|
|
static int *results[] = {
|
|
(int *)(&results0),
|
|
(int *)(&results1),
|
|
(int *)(&results2),
|
|
(int *)(&results3),
|
|
(int *)(&results4)
|
|
};
|
|
|
|
/* And here is the program */
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
regex_t re;
|
|
regmatch_t match[CAPCOUNT];
|
|
int v = argc > 1 && strcmp(argv[1], "-v") == 0;
|
|
|
|
PRINTF("Test of pcre2posix.h without pcre2.h\n");
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
char *pattern = data[i][0];
|
|
char **subjects = data[i] + 1;
|
|
int *rd = results[i];
|
|
int rc = regcomp(&re, pattern, cflags[i]);
|
|
|
|
PRINTF("Pattern: %s flags=0x%02x\n", pattern, cflags[i]);
|
|
|
|
if (rc != *rd)
|
|
{
|
|
fprintf(stderr, "Unexpected compile error %d (expected %d)\n", rc, *rd);
|
|
fprintf(stderr, "Pattern is: %s\n", pattern);
|
|
return 1;
|
|
}
|
|
|
|
if (rc != 0)
|
|
{
|
|
if (v)
|
|
{
|
|
char buffer[256];
|
|
(void)regerror(rc, &re, buffer, sizeof(buffer));
|
|
PRINTF("Compile error %d: %s (expected)\n", rc, buffer);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
for (; *subjects != NULL; subjects++)
|
|
{
|
|
rc = regexec(&re, *subjects, CAPCOUNT, match, mflags[i]);
|
|
|
|
PRINTF("Subject: %s\n", *subjects);
|
|
PRINTF("Return: %d", rc);
|
|
|
|
if (rc != *(++rd))
|
|
{
|
|
PRINTF("\n");
|
|
fprintf(stderr, "Unexpected match error %d (expected %d)\n", rc, *rd);
|
|
fprintf(stderr, "Pattern is: %s\n", pattern);
|
|
fprintf(stderr, "Subject is: %s\n", *subjects);
|
|
return 1;
|
|
}
|
|
|
|
if (rc == 0)
|
|
{
|
|
for (int j = 0; j < CAPCOUNT; j++)
|
|
{
|
|
regmatch_t *m = match + j;
|
|
if (m->rm_so < 0) continue;
|
|
if (m->rm_so != *(++rd) || m->rm_eo != *(++rd))
|
|
{
|
|
PRINTF("\n");
|
|
fprintf(stderr, "Mismatched results for successful match\n");
|
|
fprintf(stderr, "Pattern is: %s\n", pattern);
|
|
fprintf(stderr, "Subject is: %s\n", *subjects);
|
|
fprintf(stderr, "Result %d: expected %d %d received %d %d\n",
|
|
j, rd[-1], rd[0], m->rm_so, m->rm_eo);
|
|
return 1;
|
|
}
|
|
PRINTF(" (%d %d %d)", j, m->rm_so, m->rm_eo);
|
|
}
|
|
}
|
|
|
|
else if (v)
|
|
{
|
|
char buffer[256];
|
|
(void)regerror(rc, &re, buffer, sizeof(buffer));
|
|
PRINTF(": %s (expected)", buffer);
|
|
}
|
|
|
|
PRINTF("\n");
|
|
}
|
|
|
|
regfree(&re);
|
|
}
|
|
|
|
PRINTF("End of test\n");
|
|
return 0;
|
|
}
|
|
|
|
/* End of pcre2posix_test.c */
|