44static const char*
rec_get(
const char* field,
void* ud) {
45 const REC* r = (
const REC*)ud;
46 if (strcmp(field,
"host") == 0)
48 if (strcmp(field,
"method") == 0)
50 if (strcmp(field,
"path") == 0)
52 if (strcmp(field,
"status") == 0)
54 if (strcmp(field,
"mime") == 0)
60static int run(
const char* expr,
const REC* r) {
73static void expect(
const char* label,
int got,
int want) {
75 n_log(
LOG_ERR,
"%s: got %d, expected %d", label, got, want);
93 r.
host =
"api.example.com";
95 r.
path =
"/admin/login";
100 expect(
"eq",
run(
"host = api.example.com", &r), 1);
101 expect(
"eq ci",
run(
"host = API.EXAMPLE.COM", &r), 1);
102 expect(
"eq no",
run(
"host = other.test", &r), 0);
103 expect(
"contains",
run(
"host ~ example", &r), 1);
104 expect(
"contains path",
run(
"path ~ admin", &r), 1);
105 expect(
"not contains",
run(
"path !~ secret", &r), 1);
106 expect(
"ne",
run(
"mime != text/html", &r), 0);
109 expect(
"ge",
run(
"status >= 400", &r), 1);
110 expect(
"gt no",
run(
"status > 500", &r), 0);
111 expect(
"range",
run(
"status >= 400 AND status < 500", &r), 1);
114 expect(
"regex",
run(
"mime =~ ^text/", &r), 1);
115 expect(
"regex no",
run(
"mime =~ ^json", &r), 0);
118 expect(
"and",
run(
"method = GET AND status >= 400", &r), 1);
119 expect(
"or",
run(
"method = POST OR status = 403", &r), 1);
120 expect(
"not",
run(
"NOT (status = 200)", &r), 1);
121 expect(
"paren",
run(
"(method = POST OR method = GET) AND status = 403", &r), 1);
122 expect(
"prec",
run(
"method = POST AND status = 200 OR host ~ example", &r), 1);
125 expect(
"quoted",
run(
"path = \"/admin/login\"", &r), 1);
126 expect(
"unknown field",
run(
"bogus = x", &r), 0);
127 expect(
"empty match-all",
run(
"", &r), 1);
128 expect(
"blank match-all",
run(
" ", &r), 1);
142 static const char*
const KNOWN[] = {
"host",
"status",
"mime"};
143 const size_t nknown =
sizeof(KNOWN) /
sizeof(KNOWN[0]);
148 if (q || !strstr(err,
"stauts")) {
149 n_log(
LOG_ERR,
"FAIL: a misspelled field was accepted (err=%s)", err);
158 q =
n_query_compile_ex(
"STATUS >= 400 AND host ~ example", KNOWN, nknown, err,
sizeof(err));
160 n_log(
LOG_ERR,
"FAIL: a known field was refused (err=%s)", err);
172 n_log(
LOG_ERR,
"FAIL: validation ran without a vocabulary (err=%s)", err);
175 n_log(
LOG_INFO,
"PASS: no vocabulary means no field validation");
static int expect(BITMAP *bmp, int x, int y, int r, int g, int b, const char *what)
static const char * rec_get(const char *field, void *ud)
static void expect_parse_error(const char *expr)
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
#define LOG_NOTICE
normal but significant condition
#define LOG_INFO
informational
int n_query_eval(const N_QUERY *query, N_QUERY_GET get, void *user_data)
Evaluate a compiled query against one record via get.
N_QUERY * n_query_compile(const char *expr, char *errbuf, size_t errlen)
Compile an expression into a query.
N_QUERY * n_query_compile_ex(const char *expr, const char *const *fields, size_t nfields, char *errbuf, size_t errlen)
Compile expr, rejecting any field not in fields.
void n_query_free(N_QUERY **query)
Free a compiled query and set the pointer to NULL.
Opaque compiled query (see n_query_compile / n_query_eval / n_query_free).
Small boolean query language over caller-named fields.