Don't parse field modifiers in dbChannelTest()
dbChannelDelete() returns void update tests.
This commit is contained in:
committed by
Michael Davidsaver
parent
e37c5c99bb
commit
b4dbcf2b1a
@@ -211,32 +211,30 @@ static const yajl_callbacks chf_callbacks =
|
||||
static const yajl_parser_config chf_config =
|
||||
{ 0, 1 }; /* allowComments = NO , checkUTF8 = YES */
|
||||
|
||||
static long json_validate(const char *json)
|
||||
static void * chf_malloc(void *ctx, unsigned int sz)
|
||||
{
|
||||
yajl_handle yh = yajl_alloc(NULL, &chf_config, NULL, NULL);
|
||||
size_t jlen = strlen(json);
|
||||
yajl_status ys;
|
||||
|
||||
if (!yh)
|
||||
return S_db_noMemory;
|
||||
|
||||
ys = yajl_parse(yh, (const unsigned char *) json, jlen);
|
||||
if (ys == yajl_status_insufficient_data)
|
||||
ys = yajl_parse_complete(yh);
|
||||
|
||||
yajl_free(yh);
|
||||
|
||||
if (ys == yajl_status_ok)
|
||||
return 0;
|
||||
|
||||
return S_db_notFound;
|
||||
return malloc(sz); /* FIXME: free-list */
|
||||
}
|
||||
|
||||
static long chf_parse(dbChannel *chan, const char *json)
|
||||
static void * chf_realloc(void *ctx, void *ptr, unsigned int sz)
|
||||
{
|
||||
return realloc(ptr, sz); /* FIXME: free-list */
|
||||
}
|
||||
|
||||
static void chf_free(void *ctx, void *ptr)
|
||||
{
|
||||
return free(ptr); /* FIXME: free-list */
|
||||
}
|
||||
|
||||
static const yajl_alloc_funcs chf_alloc =
|
||||
{ chf_malloc, chf_realloc, chf_free };
|
||||
|
||||
static long chf_parse(dbChannel *chan, const char **pjson)
|
||||
{
|
||||
parseContext parser =
|
||||
{ chan, NULL, 0 };
|
||||
yajl_handle yh = yajl_alloc(&chf_callbacks, &chf_config, NULL, &parser);
|
||||
yajl_handle yh = yajl_alloc(&chf_callbacks, &chf_config, &chf_alloc, &parser);
|
||||
const char *json = *pjson;
|
||||
size_t jlen = strlen(json);
|
||||
yajl_status ys;
|
||||
long status;
|
||||
@@ -251,13 +249,14 @@ static long chf_parse(dbChannel *chan, const char *json)
|
||||
switch (ys) {
|
||||
case yajl_status_ok:
|
||||
status = 0;
|
||||
*pjson += yajl_get_bytes_consumed(yh);
|
||||
break;
|
||||
|
||||
case yajl_status_error: {
|
||||
unsigned char *err;
|
||||
|
||||
err = yajl_get_error(yh, 1, (const unsigned char *) json, jlen);
|
||||
printf("dbChannelFind: %s\n", err);
|
||||
printf("dbChannelCreate: %s\n", err);
|
||||
yajl_free_error(yh, err);
|
||||
} /* fall through */
|
||||
default:
|
||||
@@ -267,7 +266,7 @@ static long chf_parse(dbChannel *chan, const char *json)
|
||||
if (parser.filter) {
|
||||
assert(status);
|
||||
parser.filter->fif->parse_abort(parser.filter);
|
||||
free(parser.filter);
|
||||
free(parser.filter); /* FIXME: free-list */
|
||||
}
|
||||
yajl_free(yh);
|
||||
return status;
|
||||
@@ -302,37 +301,9 @@ long dbChannelTest(const char *name)
|
||||
return S_db_notFound;
|
||||
|
||||
status = pvNameLookup(&dbEntry, &name);
|
||||
if (status)
|
||||
goto finish;
|
||||
|
||||
/* Test field modifiers */
|
||||
while (*name) {
|
||||
switch (*name) {
|
||||
case '$':
|
||||
switch (dbEntry.pflddes->field_type) {
|
||||
case DBF_STRING:
|
||||
case DBF_INLINK:
|
||||
case DBF_OUTLINK:
|
||||
case DBF_FWDLINK:
|
||||
break;
|
||||
default:
|
||||
status = S_dbLib_fieldNotFound;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case '{':
|
||||
status = json_validate(name);
|
||||
goto finish;
|
||||
default:
|
||||
status = S_dbLib_fieldNotFound;
|
||||
goto finish;
|
||||
}
|
||||
name++;
|
||||
}
|
||||
|
||||
finish:
|
||||
dbFinishEntry(&dbEntry);
|
||||
return status;
|
||||
dbFinishEntry(&dbEntry);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Stolen from dbAccess.c: */
|
||||
@@ -372,9 +343,9 @@ dbChannel * dbChannelCreate(const char *name)
|
||||
if (status)
|
||||
goto finish;
|
||||
|
||||
// FIXME: Use free-list
|
||||
/* FIXME: Use free-list */
|
||||
chan = (dbChannel *) callocMustSucceed(1, sizeof(*chan), "dbChannelCreate");
|
||||
chan->name = strdup(name); // FIXME?
|
||||
chan->name = strdup(name); /* FIXME: free-list */
|
||||
ellInit(&chan->filters);
|
||||
|
||||
paddr = &chan->addr;
|
||||
@@ -391,9 +362,8 @@ dbChannel * dbChannelCreate(const char *name)
|
||||
paddr->dbr_field_type = mapDBFToDBR[dbfType];
|
||||
|
||||
/* Handle field modifiers */
|
||||
while (*pname) {
|
||||
switch (*pname) {
|
||||
case '$':
|
||||
if (*pname) {
|
||||
if (*pname == '$') {
|
||||
/* Some field types can be accessed as char arrays */
|
||||
if (dbfType == DBF_STRING) {
|
||||
paddr->no_elements = pflddes->size;
|
||||
@@ -409,15 +379,20 @@ dbChannel * dbChannelCreate(const char *name)
|
||||
status = S_dbLib_fieldNotFound;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
case '{':
|
||||
status = chf_parse(chan, pname);
|
||||
goto finish;
|
||||
default:
|
||||
pname++;
|
||||
}
|
||||
|
||||
/* JSON may follow a $ */
|
||||
if (*pname == '{') {
|
||||
status = chf_parse(chan, &pname);
|
||||
if (status) goto finish;
|
||||
}
|
||||
|
||||
/* Make sure there's nothing else */
|
||||
if (*pname) {
|
||||
status = S_dbLib_fieldNotFound;
|
||||
goto finish;
|
||||
}
|
||||
pname++;
|
||||
}
|
||||
|
||||
if (paddr->special == SPC_DBADDR) {
|
||||
@@ -533,7 +508,7 @@ void dbChannelFilterShow(dbChannel *chan, int level)
|
||||
}
|
||||
}
|
||||
|
||||
long dbChannelDelete(dbChannel *chan)
|
||||
void dbChannelDelete(dbChannel *chan)
|
||||
{
|
||||
chFilter *filter;
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ epicsShareFunc long dbChannelPutField(dbChannel *chan, short type,
|
||||
const void *pbuffer, long nRequest);
|
||||
epicsShareFunc void dbChannelShow(dbChannel *chan, int level);
|
||||
epicsShareFunc void dbChannelFilterShow(dbChannel *chan, int level);
|
||||
epicsShareFunc long dbChannelDelete(dbChannel *chan);
|
||||
epicsShareFunc void dbChannelDelete(dbChannel *chan);
|
||||
|
||||
epicsShareFunc void dbRegisterFilter(const char *key, const chFilterIf *fif);
|
||||
epicsShareFunc const chFilterIf * dbFindFilter(const char *key, size_t len);
|
||||
|
||||
@@ -132,31 +132,42 @@ MAIN(dbChannelTest)
|
||||
{
|
||||
dbChannel *pch;
|
||||
|
||||
testPlan(64);
|
||||
testPlan(67);
|
||||
|
||||
testOk1(!dbReadDatabase(&pdbbase, "dbChannelTest.dbx", ".:..", NULL));
|
||||
testOk(!!pdbbase, "pdbbase was set");
|
||||
|
||||
r = e = 0;
|
||||
/* Regular record and field names */
|
||||
testOk1(!dbChannelTest("x"));
|
||||
/* dbChannelTest() checks record and field names */
|
||||
testOk1(!dbChannelTest("x.NAME"));
|
||||
testOk1(!dbChannelTest("x.VAL"));
|
||||
testOk1(!dbChannelTest("x."));
|
||||
testOk1(!dbChannelTest("x"));
|
||||
testOk(dbChannelTest("y"), "Test, nonexistent record");
|
||||
testOk(dbChannelTest("x.NOFIELD"), "Test, nonexistent field");
|
||||
|
||||
/* Long string field modifier */
|
||||
/* dbChannelTest() allows but ignores field modifiers */
|
||||
testOk1(!dbChannelTest("x.NAME$"));
|
||||
testOk1(!dbChannelTest("x.{}"));
|
||||
testOk1(!dbChannelTest("x.VAL{\"json\":true}"));
|
||||
|
||||
/* dbChannelCreate() accepts field modifiers */
|
||||
testOk1(!!(pch = dbChannelCreate("x.{}")));
|
||||
if (pch) dbChannelDelete(pch);
|
||||
testOk1(!!(pch = dbChannelCreate("x.VAL{}")));
|
||||
if (pch) dbChannelDelete(pch);
|
||||
testOk1(!!(pch = dbChannelCreate("x.NAME$")));
|
||||
testOk1(pch->addr.no_elements > 1);
|
||||
testOk1(!dbChannelDelete(pch));
|
||||
testOk1(pch && pch->addr.no_elements > 1);
|
||||
if (pch) dbChannelDelete(pch);
|
||||
testOk1(!!(pch = dbChannelCreate("x.NAME${}")));
|
||||
testOk1(pch && pch->addr.no_elements > 1);
|
||||
if (pch) dbChannelDelete(pch);
|
||||
|
||||
/* JSON field modifier validation */
|
||||
testOk1(!dbChannelTest("x.{\"json\":true}"));
|
||||
|
||||
/* Ensure bad PVs get rejected */
|
||||
testOk(dbChannelTest("y"), "Test nonexistent record");
|
||||
testOk(dbChannelCreate("y") == NULL, "Create nonexistent record");
|
||||
|
||||
testOk1(dbChannelTest("x.{not-json}"));
|
||||
testOk1(!dbChannelCreate("x.{\"none\":null}"));
|
||||
/* dbChannelCreate() rejects bad PVs */
|
||||
testOk(!dbChannelCreate("y"), "Create, bad record");
|
||||
testOk(!dbChannelCreate("x.NOFIELD"), "Create, bad field");
|
||||
testOk(!dbChannelCreate("x.{not-json}"), "Create, bad JSON");
|
||||
testOk(!dbChannelCreate("x.{\"none\":null}"), "Create, bad filter");
|
||||
|
||||
dbRegisterFilter("any", &testIf);
|
||||
|
||||
@@ -177,7 +188,7 @@ MAIN(dbChannelTest)
|
||||
e = e_start | e_null | e_end;
|
||||
testOk1(!!(pch = dbChannelCreate("x.{\"any\":null}")));
|
||||
e = e_close;
|
||||
testOk1(!dbChannelDelete(pch));
|
||||
if (pch) dbChannelDelete(pch);
|
||||
|
||||
dbRegisterFilter("scalar", &testIf);
|
||||
|
||||
@@ -188,19 +199,19 @@ MAIN(dbChannelTest)
|
||||
dbChannelShow(pch, 0);
|
||||
|
||||
e = e_close;
|
||||
testOk1(!dbChannelDelete(pch));
|
||||
if (pch) dbChannelDelete(pch);
|
||||
|
||||
e = e_start | e_start_array | e_boolean | e_integer | e_end_array
|
||||
| e_end;
|
||||
testOk1(!!(pch = dbChannelCreate("x.{\"any\":[true,1]}")));
|
||||
e = e_close;
|
||||
testOk1(!dbChannelDelete(pch));
|
||||
if (pch) dbChannelDelete(pch);
|
||||
|
||||
e = e_start | e_start_map | e_map_key | e_double | e_string | e_end_map
|
||||
| e_end;
|
||||
testOk1(!!(pch = dbChannelCreate("x.{\"any\":{\"a\":2.7183,\"b\":\"c\"}}")));
|
||||
e = e_close;
|
||||
testOk1(!dbChannelDelete(pch));
|
||||
if (pch) dbChannelDelete(pch);
|
||||
|
||||
/* More event rejection */
|
||||
r = r_scalar;
|
||||
|
||||
Reference in New Issue
Block a user