Ensure keys are alphanumeric, underscores, and do not begin with digits.

pull/9/head
Joshua Potter 2023-11-25 15:58:13 -07:00
parent 0fc476ceed
commit df65c8bcac
5 changed files with 62 additions and 2 deletions

View File

@ -5,7 +5,6 @@ CLI utility for defining custom project initialization scripts.
TODO:
- [ ] Add evaluator tests.
- [ ] Color output to console.
- [ ] Ensure keys are alphanumeric, underscore
## Overview
@ -120,7 +119,8 @@ a string (submitted with a newline).
If the user were to enter, say `fieldvalue`, in response to the prompt,
the `runner` script would then have access to an environment variable
`FIELDNAME` set to `fieldvalue` on launch.
`FIELDNAME` set to `fieldvalue` on launch. Field names should consist of
alphanumeric characters or underscores, and may not start with a digit.
#### Types

View File

@ -37,6 +37,9 @@ enum ErrorCode {
ERROR_VALIDATOR_TOP_LEVEL_NOT_OBJECT,
/// A field in `spec.json` is not an object.
ERROR_VALIDATOR_FIELD_NOT_OBJECT,
/// A field name in `spec.json` is not alphanumeric and beginning with a
/// non-digit.
ERROR_VALIDATOR_FIELD_NAME_INVALID,
/// The `type` of a `spec.json` field is not a string.
ERROR_VALIDATOR_FIELD_TYPE_INVALID,
/// The `type` of a `spec.json` field does not correspond to a known prompt

View File

@ -1,5 +1,7 @@
#include "validator.h"
#include <ctype.h>
#include "string_utils.h"
static struct Error *read_field(const cJSON *const field, struct Field **out) {
@ -12,6 +14,22 @@ static struct Error *read_field(const cJSON *const field, struct Field **out) {
);
}
if (isdigit(field->string[0])) {
return ERROR_NEW(
ERROR_VALIDATOR_FIELD_NAME_INVALID,
"Field names may not begin with a digit."
);
} else {
for (const char *c = field->string; *c; ++c) {
if (*c != '_' && !isalnum(*c)) {
return ERROR_NEW(
ERROR_VALIDATOR_FIELD_NAME_INVALID,
"Field names must consist of alphanumeric characters or underscores."
);
}
}
}
struct Error *error = 0;
*out = malloc(sizeof(struct Field));
(*out)->key = field->string;

View File

@ -36,6 +36,8 @@ int main(int argc, char *argv[]) {
sput_enter_suite("validator");
sput_run_test(test_validator_toplevel_not_object);
sput_run_test(test_validator_field_not_object);
sput_run_test(test_validator_field_name_leading_digit);
sput_run_test(test_validator_field_name_non_alnum);
sput_run_test(test_validator_field_type_invalid);
sput_run_test(test_validator_field_type_unknown);
sput_run_test(test_validator_valid_type_ci);

View File

@ -52,6 +52,43 @@ static void test_validator_field_not_object() {
test_validator_teardown(fixture);
}
static void test_validator_field_name_leading_digit() {
struct TestValidatorFixture *fixture = test_validator_setup(
"{"
" \"1abc\": {"
" \"type\": \"text\""
" }"
"}"
);
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
sput_fail_unless(
error->code == ERROR_VALIDATOR_FIELD_NAME_INVALID,
"field name leading digit"
);
error_free(error);
test_validator_teardown(fixture);
}
static void test_validator_field_name_non_alnum() {
struct TestValidatorFixture *fixture = test_validator_setup(
"{"
" \"a~bc\": {"
" \"type\": \"text\""
" }"
"}"
);
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
sput_fail_unless(
error->code == ERROR_VALIDATOR_FIELD_NAME_INVALID, "field name non alnum"
);
error_free(error);
test_validator_teardown(fixture);
}
static void test_validator_field_type_invalid() {
struct TestValidatorFixture *fixture = test_validator_setup(
"{"