diff --git a/attributes/schema_type_parse.c b/attributes/schema_type_parse.c index 07b4f119becd8f52a821ec1ed3cc82e9fff440ab..9de255da6fc5986bb28a4565adb4a9709f05f74a 100644 --- a/attributes/schema_type_parse.c +++ b/attributes/schema_type_parse.c @@ -81,7 +81,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind) break; case MSTRO_STP_STR: res->str_minlen = 0; - res->str_maxlen = SIZE_MAX; + res->str_maxlen = MSTRO_STP_VAL_SIZE_MAX; res->str_excludedchars = NULL; break; case MSTRO_STP_EXCLSTR: @@ -101,7 +101,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind) break; case MSTRO_STP_BLOB: res->blob_minlen = 0; - res->blob_maxlen = SIZE_MAX; + res->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX; break; case MSTRO_STP_ERROR: res->errmsg = NULL; @@ -1238,10 +1238,19 @@ static void pcc_action_type_arguments_0(mstro_stp_context_t *__pcc_ctx, pcc_thun #define _0s ((const)__pcc_in->data.leaf.capt0.range.start) #define _0e ((const)__pcc_in->data.leaf.capt0.range.end) DEBUG("unnamed and keyword type arguments\n"); + size_t l_a,l_l, l_tot; + struct mstro_stp_val *tmp; + LL_COUNT2(a,tmp,l_a,list_tail); + LL_COUNT2(l,tmp,l_l,list_tail); + assert(a->kind == MSTRO_STP_LIST); assert(l->kind == MSTRO_STP_LIST); __=a; - LL_APPEND2(__,l,list_tail); + LL_CONCAT2(__,l,list_tail); + + LL_COUNT2(__,tmp,l_tot,list_tail); + DEBUG("unnamed count %zu, named count %zu, total %zu\n", l_a, l_l, l_tot); + #undef _0e #undef _0s #undef _0 @@ -3567,7 +3576,9 @@ void mstro_stp_destroy(mstro_stp_context_t *ctx) { #include "maestro/logging.h" -#line 452 "schema_type_parse.peg" +#define MIN(x,y) ((x)<(y) ? (x) : (y)) + +#line 561 "schema_type_parse.peg" mstro_status mstro_schema_type_parse(const char *string, struct mstro_stp_val **res) { @@ -3726,7 +3737,7 @@ mstro_stp_val__build_restricted_type( case MSTRO_STP_MAXUINT: result->uint_max = tmp->list_entry->maxuintval; break; default: - ERR("Illegal type restriction for unsigned integer: %d\n", tmp->kind); + ERR("Illegal type restriction for unsigned integer: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); @@ -3744,10 +3755,22 @@ mstro_stp_val__build_restricted_type( switch(tmp->list_entry->kind) { case MSTRO_STP_MININT: result->int_min = tmp->list_entry->minintval; break; + case MSTRO_STP_MINUINT: + if(tmp->list_entry->minuintval>(uint64_t)INT64_MAX) { + ERR("signed int min %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->minuintval); + } + result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->minuintval); + break; case MSTRO_STP_MAXINT: result->int_max = tmp->list_entry->maxintval; break; + case MSTRO_STP_MAXUINT: + if(tmp->list_entry->maxuintval>(uint64_t)INT64_MAX) { + ERR("signed int max %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->maxuintval); + } + result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->maxuintval); + break; default: - ERR("Illegal type restriction for signed integer: %d\n", tmp->kind); + ERR("Illegal type restriction for signed integer: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); @@ -3768,7 +3791,7 @@ mstro_stp_val__build_restricted_type( case MSTRO_STP_MAXFLOAT: result->float_max = tmp->list_entry->maxfloatval; break; default: - ERR("Illegal type restriction for float: %d\n", tmp->kind); + ERR("Illegal type restriction for float: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); @@ -3789,17 +3812,172 @@ mstro_stp_val__build_restricted_type( case MSTRO_STP_MAXDOUBLE: result->double_max = tmp->list_entry->maxdoubleval; break; default: - ERR("Illegal type restriction for double: %d\n", tmp->kind); + ERR("Illegal type restriction for double: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); }; break; } - case MSTRO_STP_STR: - case MSTRO_STP_REGEX: - case MSTRO_STP_BLOB: + case MSTRO_STP_STR: { + while(args!=NULL) { + assert(args->kind==MSTRO_STP_LIST); + struct mstro_stp_val *tmp = args; + args = args->list_tail; + tmp->list_tail = NULL; + + switch(tmp->list_entry->kind) { + case MSTRO_STP_EXCLSTR: + result->str_excludedchars = tmp->list_entry->exclstrval; + tmp->list_entry->exclstrval = NULL; // passed on to result + break; + case MSTRO_STP_MAXINT: + result->str_maxlen = tmp->list_entry->maxintval; + break; + case MSTRO_STP_MAXUINT: + result->str_maxlen = tmp->list_entry->maxuintval; + break; + case MSTRO_STP_MININT: + result->str_minlen = tmp->list_entry->minintval; + break; + case MSTRO_STP_MINUINT: + result->str_minlen = tmp->list_entry->minuintval; + break; + default: + ERR("Illegal type restriction for string: %d\n", tmp->list_entry->kind); + } + /* clamp to protobuf permitted max */ + if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) { + if(result->str_minlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("string min %zu larger than supported maximum, clamping\n", + result->str_minlen); + result->str_minlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) { + if(result->str_maxlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("string max %zu larger than supported maximum, clamping\n", + result->str_maxlen); + result->str_maxlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + + mstro_stp_val_dispose(tmp); + }; + break; + } + case MSTRO_STP_BLOB: { + while(args!=NULL) { + assert(args->kind==MSTRO_STP_LIST); + struct mstro_stp_val *tmp = args; + args = args->list_tail; + tmp->list_tail = NULL; + + switch(tmp->list_entry->kind) { + case MSTRO_STP_MAXINT: + result->blob_maxlen = tmp->list_entry->maxintval; + break; + case MSTRO_STP_MAXUINT: + result->blob_maxlen = tmp->list_entry->maxuintval; + break; + case MSTRO_STP_MININT: + result->blob_minlen = tmp->list_entry->minintval; + break; + case MSTRO_STP_MINUINT: + result->blob_minlen = tmp->list_entry->minuintval; + break; + default: + ERR("Illegal type restriction for blob: %d\n", tmp->list_entry->kind); + } + /* clamp to protobuf permitted max */ + if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) { + if(result->blob_minlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("blob min %zu larger than supported maximum, clamping\n", + result->blob_minlen); + result->blob_minlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) { + if(result->blob_maxlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("blob max %zu larger than supported maximum, clamping\n", + result->blob_maxlen); + result->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + mstro_stp_val_dispose(tmp); + }; + break; + } + + case MSTRO_STP_REGEX: { + struct mstro_stp_val *patterns = NULL; + result->regex_numpatterns=0; + + while(args!=NULL) { + assert(args->kind==MSTRO_STP_LIST); + struct mstro_stp_val *tmp = args; + args = args->list_tail; + tmp->list_tail = NULL; + + DEBUG("looking at %d\n", tmp->list_entry->kind); + switch(tmp->list_entry->kind) { + case MSTRO_STP_ICASE: + result->regex_ignorecase = tmp->list_entry->icase; + break; + case MSTRO_STP_NAME: + result->regex_name = tmp->list_entry->nameval; + tmp->list_entry->nameval = NULL; // moved to result + DEBUG("regex name '%s'\n", result->regex_name); + break; + case MSTRO_STP_STRVAL: + /* patterns; push to pattern stack and count */ + LL_PREPEND2(patterns,tmp,list_tail); + result->regex_numpatterns++; + tmp=NULL; /* moved to patterns stack */ + DEBUG("Found pattern |%s|, have %zu\n", + patterns->list_entry->strval, + result->regex_numpatterns); + break; + default: + ERR("Illegal type arg or restriction for regex: %d\n", tmp->list_entry->kind); + } + if(tmp!=NULL) + mstro_stp_val_dispose(tmp); + }; + if(result->regex_numpatterns==0) { + ERR("Regex without any pattern, defaulting to \"\"\n"); + result->regex_numpatterns=1; + result->regex_patterns = malloc(sizeof(char*)); + if(result->regex_patterns == NULL) { + ERR("Failed to allocate for regex patterns\n"); + abort(); + } + result->regex_patterns[0] = strdup(""); + if(result->regex_patterns[0] == NULL) { + ERR("Failed to allocate for regex\n"); + abort(); + } + } else { + result->regex_patterns = malloc(sizeof(char*)*result->regex_numpatterns); + if(result->regex_patterns == NULL) { + ERR("Failed to allocate for regex patterns\n"); + abort(); + } + /* insert, reversing */ + struct mstro_stp_val *tmp = patterns; + size_t i; + for(i=result->regex_numpatterns, tmp = patterns; + i-->0; + tmp = tmp->list_tail) { + result->regex_patterns[i] = tmp->list_entry->strval; + tmp->list_entry->strval = NULL; /* moved to result */ + } + mstro_stp_val_dispose(patterns); + } + + break; + } default: ERR("type parse intermediate kind %d should not be returned\n", typename->kind); diff --git a/attributes/schema_type_parse.h b/attributes/schema_type_parse.h index 5ab782e67c8a17ee6f80e8d8ac924e926b64154d..ce7f22e3449416de2c03b84eddd9dcec359b454c 100644 --- a/attributes/schema_type_parse.h +++ b/attributes/schema_type_parse.h @@ -13,7 +13,7 @@ struct mstro_stp_parser_ctx; enum mstro_stp_val_kind { /** error node */ - MSTRO_STP_ERROR, + MSTRO_STP_ERROR = 0, /** plain values, should not be visible in final parse result nodes, but appear during parse */ MSTRO_STP_INTVAL, MSTRO_STP_UINTVAL, @@ -21,7 +21,7 @@ enum mstro_stp_val_kind { MSTRO_STP_DOUBLEVAL, MSTRO_STP_STRVAL, MSTRO_STP_BOOLVAL, - MSTRO_STP_MININT, + MSTRO_STP_MININT = 10, MSTRO_STP_MINUINT, MSTRO_STP_MINFLOAT, MSTRO_STP_MINDOUBLE, @@ -29,13 +29,13 @@ enum mstro_stp_val_kind { MSTRO_STP_MAXUINT, MSTRO_STP_MAXFLOAT, MSTRO_STP_MAXDOUBLE, - MSTRO_STP_EXCLSTR, + MSTRO_STP_EXCLSTR = 20, MSTRO_STP_ICASE, MSTRO_STP_NAME, MSTRO_STP_LIST, /** user-facing node types */ - MSTRO_STP_BOOL, + MSTRO_STP_BOOL = 64, MSTRO_STP_UINT, MSTRO_STP_INT, MSTRO_STP_FLOAT, @@ -45,7 +45,14 @@ enum mstro_stp_val_kind { MSTRO_STP_BLOB }; -/** User-facing: the parsed type. This is also serving as documentation for the permitted restrictions for types. */ +/** User-facing: Protobuf imposes a size limit on strings and blobs + ** (because they need to fit a single message) */ + +#define MSTRO_STP_VAL_SIZE_MAX ((uint64_t) 1U<<31) + +/** User-facing: the parsed type. This is also serving as + ** documentation for the permitted restrictions for types. */ + struct mstro_stp_val { enum mstro_stp_val_kind kind; union { @@ -96,8 +103,8 @@ struct mstro_stp_val { }; struct { - size_t str_minlen; - size_t str_maxlen; + uint64_t str_minlen; + uint64_t str_maxlen; char *str_excludedchars; }; @@ -109,8 +116,8 @@ struct mstro_stp_val { }; struct { - size_t blob_minlen; - size_t blob_maxlen; + uint64_t blob_minlen; + uint64_t blob_maxlen; }; }; diff --git a/attributes/schema_type_parse.peg b/attributes/schema_type_parse.peg index 3c6e2fd98f5e90a7e0d558377358eb426f0b039e..620a0a594bdade6ebe6f60293281e3ea4da241cc 100644 --- a/attributes/schema_type_parse.peg +++ b/attributes/schema_type_parse.peg @@ -67,7 +67,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind) break; case MSTRO_STP_STR: res->str_minlen = 0; - res->str_maxlen = SIZE_MAX; + res->str_maxlen = MSTRO_STP_VAL_SIZE_MAX; res->str_excludedchars = NULL; break; case MSTRO_STP_EXCLSTR: @@ -87,7 +87,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind) break; case MSTRO_STP_BLOB: res->blob_minlen = 0; - res->blob_maxlen = SIZE_MAX; + res->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX; break; case MSTRO_STP_ERROR: res->errmsg = NULL; @@ -174,7 +174,7 @@ struct mstro_stp_parser_ctx; enum mstro_stp_val_kind { /** error node */ - MSTRO_STP_ERROR, + MSTRO_STP_ERROR = 0, /** plain values, should not be visible in final parse result nodes, but appear during parse */ MSTRO_STP_INTVAL, MSTRO_STP_UINTVAL, @@ -182,7 +182,7 @@ enum mstro_stp_val_kind { MSTRO_STP_DOUBLEVAL, MSTRO_STP_STRVAL, MSTRO_STP_BOOLVAL, - MSTRO_STP_MININT, + MSTRO_STP_MININT = 10, MSTRO_STP_MINUINT, MSTRO_STP_MINFLOAT, MSTRO_STP_MINDOUBLE, @@ -190,13 +190,13 @@ enum mstro_stp_val_kind { MSTRO_STP_MAXUINT, MSTRO_STP_MAXFLOAT, MSTRO_STP_MAXDOUBLE, - MSTRO_STP_EXCLSTR, + MSTRO_STP_EXCLSTR = 20, MSTRO_STP_ICASE, MSTRO_STP_NAME, MSTRO_STP_LIST, /** user-facing node types */ - MSTRO_STP_BOOL, + MSTRO_STP_BOOL = 64, MSTRO_STP_UINT, MSTRO_STP_INT, MSTRO_STP_FLOAT, @@ -205,8 +205,15 @@ enum mstro_stp_val_kind { MSTRO_STP_REGEX, MSTRO_STP_BLOB }; - -/** User-facing: the parsed type. This is also serving as documentation for the permitted restrictions for types. */ + +/** User-facing: Protobuf imposes a size limit on strings and blobs + ** (because they need to fit a single message) */ + +#define MSTRO_STP_VAL_SIZE_MAX ((uint64_t) 1U<<31) + +/** User-facing: the parsed type. This is also serving as + ** documentation for the permitted restrictions for types. */ + struct mstro_stp_val { enum mstro_stp_val_kind kind; union { @@ -257,8 +264,8 @@ struct mstro_stp_val { }; struct { - size_t str_minlen; - size_t str_maxlen; + uint64_t str_minlen; + uint64_t str_maxlen; char *str_excludedchars; }; @@ -270,8 +277,8 @@ struct mstro_stp_val { }; struct { - size_t blob_minlen; - size_t blob_maxlen; + uint64_t blob_minlen; + uint64_t blob_maxlen; }; }; @@ -325,10 +332,19 @@ user_type_name <- ide:identifier { $$ = ide; DEBUG("User-defined type name %s\n" ## Type argumets: empty restrictions, keyword=value arguments, unnamed arguments, or both type_arguments <- '(' a:unnamed_args ',' l:type_restriction_list ')' { DEBUG("unnamed and keyword type arguments\n"); + size_t l_a,l_l, l_tot; + struct mstro_stp_val *tmp; + LL_COUNT2(a,tmp,l_a,list_tail); + LL_COUNT2(l,tmp,l_l,list_tail); + assert(a->kind == MSTRO_STP_LIST); assert(l->kind == MSTRO_STP_LIST); $$=a; - LL_APPEND2($$,l,list_tail); + LL_CONCAT2($$,l,list_tail); + + LL_COUNT2($$,tmp,l_tot,list_tail); + DEBUG("unnamed count %zu, named count %zu, total %zu\n", l_a, l_l, l_tot); + } / '(' a:unnamed_args ')' { $$=a; @@ -548,7 +564,9 @@ EOF <- !. %% #include "maestro/logging.h" -#line 452 "schema_type_parse.peg" +#define MIN(x,y) ((x)<(y) ? (x) : (y)) + +#line 561 "schema_type_parse.peg" mstro_status mstro_schema_type_parse(const char *string, struct mstro_stp_val **res) { @@ -707,7 +725,7 @@ mstro_stp_val__build_restricted_type( case MSTRO_STP_MAXUINT: result->uint_max = tmp->list_entry->maxuintval; break; default: - ERR("Illegal type restriction for unsigned integer: %d\n", tmp->kind); + ERR("Illegal type restriction for unsigned integer: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); @@ -725,10 +743,22 @@ mstro_stp_val__build_restricted_type( switch(tmp->list_entry->kind) { case MSTRO_STP_MININT: result->int_min = tmp->list_entry->minintval; break; + case MSTRO_STP_MINUINT: + if(tmp->list_entry->minuintval>(uint64_t)INT64_MAX) { + ERR("signed int min %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->minuintval); + } + result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->minuintval); + break; case MSTRO_STP_MAXINT: result->int_max = tmp->list_entry->maxintval; break; + case MSTRO_STP_MAXUINT: + if(tmp->list_entry->maxuintval>(uint64_t)INT64_MAX) { + ERR("signed int max %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->maxuintval); + } + result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->maxuintval); + break; default: - ERR("Illegal type restriction for signed integer: %d\n", tmp->kind); + ERR("Illegal type restriction for signed integer: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); @@ -749,7 +779,7 @@ mstro_stp_val__build_restricted_type( case MSTRO_STP_MAXFLOAT: result->float_max = tmp->list_entry->maxfloatval; break; default: - ERR("Illegal type restriction for float: %d\n", tmp->kind); + ERR("Illegal type restriction for float: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); @@ -770,17 +800,172 @@ mstro_stp_val__build_restricted_type( case MSTRO_STP_MAXDOUBLE: result->double_max = tmp->list_entry->maxdoubleval; break; default: - ERR("Illegal type restriction for double: %d\n", tmp->kind); + ERR("Illegal type restriction for double: %d\n", tmp->list_entry->kind); } mstro_stp_val_dispose(tmp); }; break; } - case MSTRO_STP_STR: - case MSTRO_STP_REGEX: - case MSTRO_STP_BLOB: + case MSTRO_STP_STR: { + while(args!=NULL) { + assert(args->kind==MSTRO_STP_LIST); + struct mstro_stp_val *tmp = args; + args = args->list_tail; + tmp->list_tail = NULL; + + switch(tmp->list_entry->kind) { + case MSTRO_STP_EXCLSTR: + result->str_excludedchars = tmp->list_entry->exclstrval; + tmp->list_entry->exclstrval = NULL; // passed on to result + break; + case MSTRO_STP_MAXINT: + result->str_maxlen = tmp->list_entry->maxintval; + break; + case MSTRO_STP_MAXUINT: + result->str_maxlen = tmp->list_entry->maxuintval; + break; + case MSTRO_STP_MININT: + result->str_minlen = tmp->list_entry->minintval; + break; + case MSTRO_STP_MINUINT: + result->str_minlen = tmp->list_entry->minuintval; + break; + default: + ERR("Illegal type restriction for string: %d\n", tmp->list_entry->kind); + } + /* clamp to protobuf permitted max */ + if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) { + if(result->str_minlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("string min %zu larger than supported maximum, clamping\n", + result->str_minlen); + result->str_minlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) { + if(result->str_maxlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("string max %zu larger than supported maximum, clamping\n", + result->str_maxlen); + result->str_maxlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + + mstro_stp_val_dispose(tmp); + }; + break; + } + case MSTRO_STP_BLOB: { + while(args!=NULL) { + assert(args->kind==MSTRO_STP_LIST); + struct mstro_stp_val *tmp = args; + args = args->list_tail; + tmp->list_tail = NULL; + + switch(tmp->list_entry->kind) { + case MSTRO_STP_MAXINT: + result->blob_maxlen = tmp->list_entry->maxintval; + break; + case MSTRO_STP_MAXUINT: + result->blob_maxlen = tmp->list_entry->maxuintval; + break; + case MSTRO_STP_MININT: + result->blob_minlen = tmp->list_entry->minintval; + break; + case MSTRO_STP_MINUINT: + result->blob_minlen = tmp->list_entry->minuintval; + break; + default: + ERR("Illegal type restriction for blob: %d\n", tmp->list_entry->kind); + } + /* clamp to protobuf permitted max */ + if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) { + if(result->blob_minlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("blob min %zu larger than supported maximum, clamping\n", + result->blob_minlen); + result->blob_minlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) { + if(result->blob_maxlen > MSTRO_STP_VAL_SIZE_MAX) { + ERR("blob max %zu larger than supported maximum, clamping\n", + result->blob_maxlen); + result->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX; + } + } + mstro_stp_val_dispose(tmp); + }; break; + } + + case MSTRO_STP_REGEX: { + struct mstro_stp_val *patterns = NULL; + result->regex_numpatterns=0; + + while(args!=NULL) { + assert(args->kind==MSTRO_STP_LIST); + struct mstro_stp_val *tmp = args; + args = args->list_tail; + tmp->list_tail = NULL; + + DEBUG("looking at %d\n", tmp->list_entry->kind); + switch(tmp->list_entry->kind) { + case MSTRO_STP_ICASE: + result->regex_ignorecase = tmp->list_entry->icase; + break; + case MSTRO_STP_NAME: + result->regex_name = tmp->list_entry->nameval; + tmp->list_entry->nameval = NULL; // moved to result + DEBUG("regex name '%s'\n", result->regex_name); + break; + case MSTRO_STP_STRVAL: + /* patterns; push to pattern stack and count */ + LL_PREPEND2(patterns,tmp,list_tail); + result->regex_numpatterns++; + tmp=NULL; /* moved to patterns stack */ + DEBUG("Found pattern |%s|, have %zu\n", + patterns->list_entry->strval, + result->regex_numpatterns); + break; + default: + ERR("Illegal type arg or restriction for regex: %d\n", tmp->list_entry->kind); + } + if(tmp!=NULL) + mstro_stp_val_dispose(tmp); + }; + if(result->regex_numpatterns==0) { + ERR("Regex without any pattern, defaulting to \"\"\n"); + result->regex_numpatterns=1; + result->regex_patterns = malloc(sizeof(char*)); + if(result->regex_patterns == NULL) { + ERR("Failed to allocate for regex patterns\n"); + abort(); + } + result->regex_patterns[0] = strdup(""); + if(result->regex_patterns[0] == NULL) { + ERR("Failed to allocate for regex\n"); + abort(); + } + } else { + result->regex_patterns = malloc(sizeof(char*)*result->regex_numpatterns); + if(result->regex_patterns == NULL) { + ERR("Failed to allocate for regex patterns\n"); + abort(); + } + /* insert, reversing */ + struct mstro_stp_val *tmp = patterns; + size_t i; + for(i=result->regex_numpatterns, tmp = patterns; + i-->0; + tmp = tmp->list_tail) { + result->regex_patterns[i] = tmp->list_entry->strval; + tmp->list_entry->strval = NULL; /* moved to result */ + } + mstro_stp_val_dispose(patterns); + } + + + break; + } default: ERR("type parse intermediate kind %d should not be returned\n", typename->kind); diff --git a/tests/Makefile.am b/tests/Makefile.am index 8d63ed47589fd2d7b48dadf988045fcd7f95011a..76af787fd946abc1935468028ca0c06ce1f3d737 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -51,6 +51,9 @@ LDADD = $(top_builddir)/libmaestro.la check_HEADERS = cheat.h TESTS = check_version check_init\ + check_schema_parse \ + check_type_parser \ + check_symtab \ check_protobuf_c \ check_transport_gfs \ check_declare \ @@ -64,14 +67,11 @@ TESTS = check_version check_init\ run_demo.sh \ check_pool_manager \ check_pm_declare.sh \ - check_pm_interlock.sh + check_pm_interlock.sh -# will come when 46-* branch is completely merged -# check_schema_parse \ -# check_type_parser \ -# check_symtab - -# too expensive: check_pool_local_multi +# too expensive, actually more of a benchmark: +# check_pool_local_multi +# broken for now: # check_mempool check_PROGRAMS = check_version check_init \ diff --git a/tests/check_schema_parse.c b/tests/check_schema_parse.c index bf72e7d23cf1beeec415996e32b8be32d9950523..cc8b6f5ae477dbba9558326365e43b4a9cbc66ef 100644 --- a/tests/check_schema_parse.c +++ b/tests/check_schema_parse.c @@ -53,8 +53,9 @@ #define XSTRINGIFY(s) #s #define STRINGIFY(s) XSTRINGIFY(s) -#define CORE_YAML STRINGIFY(TOPSRCDIR) "/attributes/maestro-core.yaml" -#define USER_YAML STRINGIFY(TOPSRCDIR) "/attributes/user.yaml" +#define CORE_YAML STRINGIFY(TOPSRCDIR) "/attributes/maestro-core.yaml" +#define USER_YAML STRINGIFY(TOPSRCDIR) "/attributes/user.yaml" +#define ECMWF_YAML STRINGIFY(TOPSRCDIR) "/attributes/ecmwf.yaml" #define SAMPLE_YAML_STRING \ ".maestro.core.cdo:\n" \ @@ -67,7 +68,7 @@ CHEAT_TEST(core_schema_parse, - mstro_schema s1, s2; + mstro_schema s1, s2, s3; mstro_attribute_dict dict; mstro_status s=MSTRO_OK; @@ -77,6 +78,8 @@ CHEAT_TEST(core_schema_parse, s=mstro_schema_parse_from_file(CORE_YAML, &s1); if(MSTRO_OK!=s) { + /* clean up successful one so that valgrind is happy + * even on failure */ cheat_assert(MSTRO_OK==mstro_schema_free(s2)); } cheat_assert(MSTRO_OK==s); @@ -85,9 +88,28 @@ CHEAT_TEST(core_schema_parse, /* cheat_assert(MSTRO_OK==mstro_schema_merge(s1, s2)); */ /* cheat_yield(); */ - cheat_assert(MSTRO_OK==mstro_attributes_parse(s1,SAMPLE_YAML_STRING, &dict)); + s=mstro_schema_parse_from_file(ECMWF_YAML, &s3); + if(MSTRO_OK!=s) { + /* clean up successful ones so that valgrind is happy + * even on failure */ + cheat_assert(MSTRO_OK==mstro_schema_free(s1)); + cheat_assert(MSTRO_OK==mstro_schema_free(s2)); + } + cheat_assert(MSTRO_OK==s); + cheat_yield(); + + + /* now use the merged schema to parse some sample defs */ + cheat_assert(MSTRO_OK==mstro_attributes_parse(s1, + SAMPLE_YAML_STRING, + &dict)); cheat_yield(); + + + /* cheat_assert(MSTRO_OK==mstro_schema_add_from_file(CORE_YAML)); */ /* cheat_assert(MSTRO_OK==mstro_schema_add_from_file(USER_YAML)); */ + + ) diff --git a/tests/check_type_parser.c b/tests/check_type_parser.c index ddf6ffad0e8e5a46f2cbc0ac21e5afe022b6696e..ffe91b09601d68269355ab95a5f9462d86b5eeeb 100644 --- a/tests/check_type_parser.c +++ b/tests/check_type_parser.c @@ -53,20 +53,26 @@ CHEAT_DECLARE( const char *strings[] = { /* built-in types, no restrictions */ - "bool()", "uint()", "int()", "float()", "double()", "regex()", "str()", "blob()", - /* /\* typical restricted types *\/ */ - "uint(max=10, min=7)", - "int(min=-17, max=42)", - "str(exclude='XYZ')", /* string that can not include the specified characters */ - "str(min=42)", - "str(max=8)", - "str(max=8, min=8)", - "\tblob ( max = 4711) ", - "regex(';.*$',ignore_case=False, name='lisp comment')", - /* multiple patterns */ - "regex('^$','^[ \\t\\n\\r\\v]*#.*$',ignore_case=true, name='empty line or shell block comment')", - /* FIXME: add nested types */ - NULL, + "bool()", "uint()", "int()", "float()", "double()", + "str()", "blob()", + /* regex is also built-in but can't be used without args; + * see below */ + + /* typical restricted types */ + "uint(max=10, min=7)", + "int(min=-17, max=42)", + "str(exclude='XYZ')", /* string that can not include the + * specified characters */ + "str(min=42)", + "str(max=8)", + "str(max=8, min=8)", + "\tblob ( max = 4711) ", + "regex(';.*$',ignore_case=False, name='lisp comment')", + "regex(';.*$',ignore_case=True, name='lisp comment')", + /* multiple patterns */ + "regex('^$','^[ \\t\\n\\r\\v]*#.*$',ignore_case=true, name='empty line or shell block comment')", + /* /\* FIXME: add nested types *\/ */ + NULL, }; ) @@ -75,7 +81,8 @@ CHEAT_TEST(core_schema_parse, struct mstro_stp_val *result; const char **s; for(s=strings; (*s)!=NULL; s++) { - /* FIXME: could be improved to also have expected parse results listed above and compare them */ + /* FIXME: could be improved to also have expected parse + * results listed above and compare them */ INFO("parsing type |%s|\n", *s); cheat_assert(MSTRO_OK==mstro_schema_type_parse(*s, &result)); cheat_yield();