Add consistent error output.
parent
df65c8bcac
commit
80b1f4ed49
|
@ -2,10 +2,6 @@
|
||||||
|
|
||||||
CLI utility for defining custom project initialization scripts.
|
CLI utility for defining custom project initialization scripts.
|
||||||
|
|
||||||
TODO:
|
|
||||||
- [ ] Add evaluator tests.
|
|
||||||
- [ ] Color output to console.
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
`bootstrap` is a tool for quickly defining your own init-like scripts. If you
|
`bootstrap` is a tool for quickly defining your own init-like scripts. If you
|
||||||
|
|
|
@ -95,7 +95,7 @@ Take the `__VA_ARGS__` list and append a list of decreasing numbers
|
||||||
__VA_ARGS__, \
|
__VA_ARGS__, \
|
||||||
0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, \
|
0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, \
|
||||||
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, \
|
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, \
|
||||||
0x0E, 0x0F, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, \
|
0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, \
|
||||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00)
|
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00)
|
||||||
|
|
||||||
#define ALEN0( \
|
#define ALEN0( \
|
||||||
|
@ -121,13 +121,20 @@ It is the responsibility of the caller to free the @ref Error instance.
|
||||||
#define ERROR_NEW(code, ...) \
|
#define ERROR_NEW(code, ...) \
|
||||||
ERROR_NEW0(code, ALEN(__VA_ARGS__), __VA_ARGS__)
|
ERROR_NEW0(code, ALEN(__VA_ARGS__), __VA_ARGS__)
|
||||||
|
|
||||||
#define ERROR_NEW0(code, nargs, ...) \
|
#define ERROR_NEW0(code, nargs, ...) \
|
||||||
priv_error_new( \
|
priv_error_new((code), (nargs), (const char *[nargs]){__VA_ARGS__})
|
||||||
(code), (nargs + 1), (const char * [nargs + 1]){__VA_ARGS__, "\n"} \
|
|
||||||
)
|
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
#define ANSI_BLACK(...) "\e[0;30m", __VA_ARGS__, "\e[0m"
|
||||||
|
#define ANSI_RED(...) "\e[0;31m", __VA_ARGS__, "\e[0m"
|
||||||
|
#define ANSI_GREEN(...) "\e[0;32m", __VA_ARGS__, "\e[0m"
|
||||||
|
#define ANSI_YELLOW(...) "\e[0;33m", __VA_ARGS__, "\e[0m"
|
||||||
|
#define ANSI_BLUE(...) "\e[0;34m", __VA_ARGS__, "\e[0m"
|
||||||
|
#define ANSI_PURPLE(...) "\e[0;35m", __VA_ARGS__, "\e[0m"
|
||||||
|
#define ANSI_CYAN(...) "\e[0;36m", __VA_ARGS__, "\e[0m"
|
||||||
|
#define ANSI_WHITE(...) "\e[0;37m", __VA_ARGS__, "\e[0m"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Deallocates a previously allocated @ref Error isntance.
|
@brief Deallocates a previously allocated @ref Error isntance.
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define _BOOTSTRAP_VALIDATOR_H
|
#define _BOOTSTRAP_VALIDATOR_H
|
||||||
|
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
|
#include "config.h"
|
||||||
#include "dyn_array.h"
|
#include "dyn_array.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
@ -52,6 +53,8 @@ struct Field {
|
||||||
/**
|
/**
|
||||||
@brief Verify the `spec.json` file is formatted correctly.
|
@brief Verify the `spec.json` file is formatted correctly.
|
||||||
|
|
||||||
|
@param config
|
||||||
|
A reference to the parameters describing the desired spec.
|
||||||
@param parsed
|
@param parsed
|
||||||
A possible null pointer to the parsed `spec.json` file. If null, this method
|
A possible null pointer to the parsed `spec.json` file. If null, this method
|
||||||
simply sets *fields to a null pointer.
|
simply sets *fields to a null pointer.
|
||||||
|
@ -62,7 +65,9 @@ struct Field {
|
||||||
A null pointer if no error occurs. Otherwise an @ref Error pointer.
|
A null pointer if no error occurs. Otherwise an @ref Error pointer.
|
||||||
*/
|
*/
|
||||||
struct Error *validate_spec_json(
|
struct Error *validate_spec_json(
|
||||||
const cJSON *const parsed, struct DynArray **fields
|
const struct Config *const config,
|
||||||
|
const cJSON *const parsed,
|
||||||
|
struct DynArray **fields
|
||||||
);
|
);
|
||||||
|
|
||||||
#endif /* _BOOTSTRAP_VALIDATOR_H */
|
#endif /* _BOOTSTRAP_VALIDATOR_H */
|
||||||
|
|
2
main.c
2
main.c
|
@ -33,7 +33,7 @@ static int run(const char *root_dir, const char *target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DynArray *prompts = 0;
|
struct DynArray *prompts = 0;
|
||||||
if ((error = validate_spec_json(parsed, &prompts))) {
|
if ((error = validate_spec_json(config, parsed, &prompts))) {
|
||||||
fprintf(stderr, "%s", error->message);
|
fprintf(stderr, "%s", error->message);
|
||||||
goto cleanup_parsed;
|
goto cleanup_parsed;
|
||||||
}
|
}
|
||||||
|
|
30
src/config.c
30
src/config.c
|
@ -17,11 +17,19 @@ struct Error *config_new(
|
||||||
assert(target);
|
assert(target);
|
||||||
|
|
||||||
if (cwd == 0) {
|
if (cwd == 0) {
|
||||||
return ERROR_NEW(ERROR_CONFIG_ENV_CWD_INVALID, "Could not retrieve $CWD.");
|
return ERROR_NEW(
|
||||||
|
ERROR_CONFIG_ENV_CWD_INVALID,
|
||||||
|
ANSI_RED("ERROR"),
|
||||||
|
": Could not retrieve ",
|
||||||
|
ANSI_CYAN("CWD"),
|
||||||
|
"."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (root_dir == 0) {
|
if (root_dir == 0) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_CONFIG_ENV_ROOT_DIR_INVALID, "No specified root directory."
|
ERROR_CONFIG_ENV_ROOT_DIR_INVALID,
|
||||||
|
ANSI_RED("ERROR"),
|
||||||
|
": Could not find root directory."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,18 +43,30 @@ struct Error *config_new(
|
||||||
if (stat_res == -1) {
|
if (stat_res == -1) {
|
||||||
if (errno == ENOENT) {
|
if (errno == ENOENT) {
|
||||||
error = ERROR_NEW(
|
error = ERROR_NEW(
|
||||||
ERROR_CONFIG_TARGET_NOT_FOUND, "Spec ", filepath, " not found."
|
ERROR_CONFIG_TARGET_NOT_FOUND,
|
||||||
|
ANSI_RED("ERROR"),
|
||||||
|
": Could not find ",
|
||||||
|
ANSI_BLUE(target),
|
||||||
|
" spec."
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
error = ERROR_NEW(
|
error = ERROR_NEW(
|
||||||
ERROR_CONFIG_TARGET_INVALID, "Spec ", filepath, " is invalid."
|
ERROR_CONFIG_TARGET_INVALID,
|
||||||
|
ANSI_RED("ERROR"),
|
||||||
|
": ",
|
||||||
|
ANSI_BLUE(target),
|
||||||
|
" is invalid."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (!S_ISDIR(sb.st_mode)) {
|
if (!S_ISDIR(sb.st_mode)) {
|
||||||
error = ERROR_NEW(
|
error = ERROR_NEW(
|
||||||
ERROR_CONFIG_TARGET_NOT_DIR, "Spec ", filepath, " is not a directory."
|
ERROR_CONFIG_TARGET_NOT_DIR,
|
||||||
|
ANSI_RED("ERROR"),
|
||||||
|
": ",
|
||||||
|
ANSI_CYAN(filepath),
|
||||||
|
" is not a directory."
|
||||||
);
|
);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,17 +23,20 @@ static struct Error *find_run_exec(const struct Config *const config) {
|
||||||
if (stat_res == -1 && errno == ENOENT) {
|
if (stat_res == -1 && errno == ENOENT) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_EVALUATOR_RUNNER_NOT_FOUND,
|
ERROR_EVALUATOR_RUNNER_NOT_FOUND,
|
||||||
"Could not find ",
|
ANSI_RED("NOT_FOUND"),
|
||||||
config->target,
|
": Could not find ",
|
||||||
"/runner"
|
ANSI_BLUE(config->target, "/runner"),
|
||||||
|
"."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sb.st_mode & S_IXUSR)) {
|
if (!(sb.st_mode & S_IXUSR)) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_EVALUATOR_RUNNER_NOT_EXEC,
|
ERROR_EVALUATOR_RUNNER_NOT_EXEC,
|
||||||
config->target,
|
ANSI_RED("ERROR"),
|
||||||
"/runner is not executable."
|
": ",
|
||||||
|
ANSI_BLUE(config->target, "/runner"),
|
||||||
|
" is not executable."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,20 +45,21 @@ static struct Error *find_run_exec(const struct Config *const config) {
|
||||||
|
|
||||||
static const char *prompt_field(struct Field *field) {
|
static const char *prompt_field(struct Field *field) {
|
||||||
assert(field);
|
assert(field);
|
||||||
|
printf("%s", field->prompt);
|
||||||
|
|
||||||
|
char *response = calloc(1, 1024);
|
||||||
|
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case FT_TEXT:
|
case FT_TEXT:
|
||||||
printf("%s", field->prompt);
|
|
||||||
// TODO: Probably want this buffer size to be a bit more dynamic.
|
// TODO: Probably want this buffer size to be a bit more dynamic.
|
||||||
char *input = calloc(1, 1024);
|
if (fgets(response, 1024, stdin)) {
|
||||||
if (fgets(input, 1024, stdin)) {
|
size_t len = strlen(response);
|
||||||
size_t len = strlen(input);
|
if (len > 0 && response[len - 1] == '\n') {
|
||||||
if (len > 0 && input[len - 1] == '\n') {
|
response[len - 1] = '\0';
|
||||||
input[len - 1] = '\0';
|
|
||||||
}
|
}
|
||||||
return input;
|
return response;
|
||||||
} else {
|
} else {
|
||||||
free(input);
|
free(response);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +96,9 @@ int evaluate_runner(
|
||||||
const char *response = prompt_field(field);
|
const char *response = prompt_field(field);
|
||||||
if (!response) {
|
if (!response) {
|
||||||
*error = ERROR_NEW(
|
*error = ERROR_NEW(
|
||||||
ERROR_EVALUATOR_RESPONSE_INVALID, "Could not read in response."
|
ERROR_EVALUATOR_RESPONSE_INVALID,
|
||||||
|
ANSI_RED("ERROR"),
|
||||||
|
": Could not read response."
|
||||||
);
|
);
|
||||||
string_buf_free(env_buf);
|
string_buf_free(env_buf);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
11
src/parser.c
11
src/parser.c
|
@ -19,7 +19,11 @@ static struct Error *find_spec_json(
|
||||||
*handle = fopen(filepath, "r");
|
*handle = fopen(filepath, "r");
|
||||||
if (!*handle && errno != ENOENT) {
|
if (!*handle && errno != ENOENT) {
|
||||||
error = ERROR_NEW(
|
error = ERROR_NEW(
|
||||||
ERROR_PARSER_SPEC_JSON_INVALID, config->target, "/spec.json is invalid."
|
ERROR_PARSER_SPEC_JSON_INVALID,
|
||||||
|
ANSI_RED("ERROR"),
|
||||||
|
": ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" is invalid."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +64,10 @@ struct Error *parse_spec_json(
|
||||||
if (!*parsed) {
|
if (!*parsed) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_PARSER_SPEC_JSON_INVALID_SYNTAX,
|
ERROR_PARSER_SPEC_JSON_INVALID_SYNTAX,
|
||||||
"The spec.json file contains invalid JSON."
|
ANSI_RED("ERROR"),
|
||||||
|
": ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" contains invalid JSON."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,27 +4,44 @@
|
||||||
|
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
|
|
||||||
static struct Error *read_field(const cJSON *const field, struct Field **out) {
|
static struct Error *read_field(
|
||||||
|
const struct Config *const config,
|
||||||
|
const cJSON *const field,
|
||||||
|
struct Field **out
|
||||||
|
) {
|
||||||
if (!cJSON_IsObject(field)) {
|
if (!cJSON_IsObject(field)) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_VALIDATOR_FIELD_NOT_OBJECT,
|
ERROR_VALIDATOR_FIELD_NOT_OBJECT,
|
||||||
"Field \"",
|
ANSI_RED("ERROR"),
|
||||||
field->string,
|
": Field ",
|
||||||
"\" is not a JSON object."
|
ANSI_PURPLE(field->string),
|
||||||
|
" in ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" is not a JSON object."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isdigit(field->string[0])) {
|
if (isdigit(field->string[0])) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_VALIDATOR_FIELD_NAME_INVALID,
|
ERROR_VALIDATOR_FIELD_NAME_INVALID,
|
||||||
"Field names may not begin with a digit."
|
ANSI_RED("ERROR"),
|
||||||
|
": Field ",
|
||||||
|
ANSI_PURPLE(field->string),
|
||||||
|
" in ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" may not begin with a digit."
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
for (const char *c = field->string; *c; ++c) {
|
for (const char *c = field->string; *c; ++c) {
|
||||||
if (*c != '_' && !isalnum(*c)) {
|
if (*c != '_' && !isalnum(*c)) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_VALIDATOR_FIELD_NAME_INVALID,
|
ERROR_VALIDATOR_FIELD_NAME_INVALID,
|
||||||
"Field names must consist of alphanumeric characters or underscores."
|
ANSI_RED("ERROR"),
|
||||||
|
": Field ",
|
||||||
|
ANSI_PURPLE(field->string),
|
||||||
|
" in ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" must consist of only alphanumeric characters and underscores."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,9 +55,14 @@ static struct Error *read_field(const cJSON *const field, struct Field **out) {
|
||||||
if (!cJSON_IsString(type)) {
|
if (!cJSON_IsString(type)) {
|
||||||
error = ERROR_NEW(
|
error = ERROR_NEW(
|
||||||
ERROR_VALIDATOR_FIELD_TYPE_INVALID,
|
ERROR_VALIDATOR_FIELD_TYPE_INVALID,
|
||||||
"Field \"",
|
ANSI_RED("ERROR"),
|
||||||
field->string,
|
": Field ",
|
||||||
"\" has non-string \"type\"."
|
ANSI_PURPLE(field->string),
|
||||||
|
" in ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" has non-string ",
|
||||||
|
ANSI_PURPLE("type"),
|
||||||
|
"."
|
||||||
);
|
);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -50,9 +72,14 @@ static struct Error *read_field(const cJSON *const field, struct Field **out) {
|
||||||
} else {
|
} else {
|
||||||
error = ERROR_NEW(
|
error = ERROR_NEW(
|
||||||
ERROR_VALIDATOR_FIELD_TYPE_UNKNOWN,
|
ERROR_VALIDATOR_FIELD_TYPE_UNKNOWN,
|
||||||
"Field \"",
|
ANSI_RED("ERROR"),
|
||||||
field->string,
|
": Field ",
|
||||||
"\" has unknown \"type\"."
|
ANSI_PURPLE(field->string),
|
||||||
|
" in ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" has unknown ",
|
||||||
|
ANSI_PURPLE("type"),
|
||||||
|
"."
|
||||||
);
|
);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -63,9 +90,14 @@ static struct Error *read_field(const cJSON *const field, struct Field **out) {
|
||||||
} else {
|
} else {
|
||||||
error = ERROR_NEW(
|
error = ERROR_NEW(
|
||||||
ERROR_VALIDATOR_FIELD_PROMPT_INVALID,
|
ERROR_VALIDATOR_FIELD_PROMPT_INVALID,
|
||||||
"Field \"",
|
ANSI_RED("ERROR"),
|
||||||
field->string,
|
": Field ",
|
||||||
"\" has non-string \"prompt\"."
|
ANSI_PURPLE(field->string),
|
||||||
|
" in ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" has non-string ",
|
||||||
|
ANSI_PURPLE("prompt"),
|
||||||
|
"."
|
||||||
);
|
);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +110,9 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Error *validate_spec_json(
|
struct Error *validate_spec_json(
|
||||||
const cJSON *const parsed, struct DynArray **fields
|
const struct Config *const config,
|
||||||
|
const cJSON *const parsed,
|
||||||
|
struct DynArray **fields
|
||||||
) {
|
) {
|
||||||
*fields = 0;
|
*fields = 0;
|
||||||
|
|
||||||
|
@ -90,7 +124,10 @@ struct Error *validate_spec_json(
|
||||||
if (!cJSON_IsObject(parsed)) {
|
if (!cJSON_IsObject(parsed)) {
|
||||||
return ERROR_NEW(
|
return ERROR_NEW(
|
||||||
ERROR_VALIDATOR_TOP_LEVEL_NOT_OBJECT,
|
ERROR_VALIDATOR_TOP_LEVEL_NOT_OBJECT,
|
||||||
"Top-level JSON value in spec.json is not an object."
|
ANSI_RED("ERROR"),
|
||||||
|
": Top-level JSON value in ",
|
||||||
|
ANSI_BLUE(config->target, "/spec.json"),
|
||||||
|
" is not an object."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +139,7 @@ struct Error *validate_spec_json(
|
||||||
cJSON *child = parsed->child;
|
cJSON *child = parsed->child;
|
||||||
while (child) {
|
while (child) {
|
||||||
struct Field *field = 0;
|
struct Field *field = 0;
|
||||||
error = read_field(child, &field);
|
error = read_field(config, child, &field);
|
||||||
if (error) {
|
if (error) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
#ifndef _BOOTSTRAP_TEST_VALIDATOR
|
#ifndef _BOOTSTRAP_TEST_VALIDATOR
|
||||||
#define _BOOTSTRAP_TEST_VALIDATOR
|
#define _BOOTSTRAP_TEST_VALIDATOR
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "dyn_array.h"
|
#include "dyn_array.h"
|
||||||
#include "sput.h"
|
#include "sput.h"
|
||||||
|
#include "string_utils.h"
|
||||||
#include "validator.h"
|
#include "validator.h"
|
||||||
|
|
||||||
struct TestValidatorFixture {
|
struct TestValidatorFixture {
|
||||||
const char *json;
|
const char *json;
|
||||||
struct DynArray *prompts;
|
struct DynArray *prompts;
|
||||||
cJSON *parsed;
|
cJSON *parsed;
|
||||||
|
struct Config config;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct TestValidatorFixture *test_validator_setup(const char *json) {
|
static struct TestValidatorFixture *test_validator_setup(const char *json) {
|
||||||
|
@ -17,6 +21,15 @@ static struct TestValidatorFixture *test_validator_setup(const char *json) {
|
||||||
fixture->json = json;
|
fixture->json = json;
|
||||||
fixture->prompts = 0;
|
fixture->prompts = 0;
|
||||||
fixture->parsed = cJSON_Parse(json);
|
fixture->parsed = cJSON_Parse(json);
|
||||||
|
|
||||||
|
char *cwd = getcwd(0, 0);
|
||||||
|
const char *segments[] = {cwd, "test", "specs"};
|
||||||
|
char *root_dir = join(sizeof(segments) / sizeof(char *), segments, '/');
|
||||||
|
|
||||||
|
fixture->config.cwd = cwd;
|
||||||
|
fixture->config.root_dir = root_dir;
|
||||||
|
fixture->config.target = "minimal_spec_json";
|
||||||
|
|
||||||
return fixture;
|
return fixture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +37,16 @@ static void test_validator_teardown(struct TestValidatorFixture *fixture) {
|
||||||
if (fixture->parsed) {
|
if (fixture->parsed) {
|
||||||
cJSON_Delete(fixture->parsed);
|
cJSON_Delete(fixture->parsed);
|
||||||
}
|
}
|
||||||
|
free((void *)fixture->config.cwd);
|
||||||
|
free((void *)fixture->config.root_dir);
|
||||||
free(fixture);
|
free(fixture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_validator_toplevel_not_object() {
|
static void test_validator_toplevel_not_object() {
|
||||||
struct TestValidatorFixture *fixture = test_validator_setup("[]");
|
struct TestValidatorFixture *fixture = test_validator_setup("[]");
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(
|
sput_fail_unless(
|
||||||
error->code == ERROR_VALIDATOR_TOP_LEVEL_NOT_OBJECT, "top-level not object"
|
error->code == ERROR_VALIDATOR_TOP_LEVEL_NOT_OBJECT, "top-level not object"
|
||||||
);
|
);
|
||||||
|
@ -43,7 +59,8 @@ static void test_validator_field_not_object() {
|
||||||
struct TestValidatorFixture *fixture =
|
struct TestValidatorFixture *fixture =
|
||||||
test_validator_setup("{\"key\": \"$UNKNOWN\"}");
|
test_validator_setup("{\"key\": \"$UNKNOWN\"}");
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(
|
sput_fail_unless(
|
||||||
error->code == ERROR_VALIDATOR_FIELD_NOT_OBJECT, "field not object"
|
error->code == ERROR_VALIDATOR_FIELD_NOT_OBJECT, "field not object"
|
||||||
);
|
);
|
||||||
|
@ -61,7 +78,8 @@ static void test_validator_field_name_leading_digit() {
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(
|
sput_fail_unless(
|
||||||
error->code == ERROR_VALIDATOR_FIELD_NAME_INVALID,
|
error->code == ERROR_VALIDATOR_FIELD_NAME_INVALID,
|
||||||
"field name leading digit"
|
"field name leading digit"
|
||||||
|
@ -80,7 +98,8 @@ static void test_validator_field_name_non_alnum() {
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(
|
sput_fail_unless(
|
||||||
error->code == ERROR_VALIDATOR_FIELD_NAME_INVALID, "field name non alnum"
|
error->code == ERROR_VALIDATOR_FIELD_NAME_INVALID, "field name non alnum"
|
||||||
);
|
);
|
||||||
|
@ -98,7 +117,8 @@ static void test_validator_field_type_invalid() {
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(
|
sput_fail_unless(
|
||||||
error->code == ERROR_VALIDATOR_FIELD_TYPE_INVALID, "field type invalid"
|
error->code == ERROR_VALIDATOR_FIELD_TYPE_INVALID, "field type invalid"
|
||||||
);
|
);
|
||||||
|
@ -116,7 +136,8 @@ static void test_validator_field_type_unknown() {
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(
|
sput_fail_unless(
|
||||||
error->code == ERROR_VALIDATOR_FIELD_TYPE_UNKNOWN, "field type unknown"
|
error->code == ERROR_VALIDATOR_FIELD_TYPE_UNKNOWN, "field type unknown"
|
||||||
);
|
);
|
||||||
|
@ -135,7 +156,8 @@ static void test_validator_valid_type_ci() {
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(error == 0, "valid");
|
sput_fail_unless(error == 0, "valid");
|
||||||
|
|
||||||
test_validator_teardown(fixture);
|
test_validator_teardown(fixture);
|
||||||
|
@ -151,7 +173,8 @@ static void test_validator_field_prompt_invalid() {
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(
|
sput_fail_unless(
|
||||||
error->code == ERROR_VALIDATOR_FIELD_PROMPT_INVALID, "field prompt invalid"
|
error->code == ERROR_VALIDATOR_FIELD_PROMPT_INVALID, "field prompt invalid"
|
||||||
);
|
);
|
||||||
|
@ -170,7 +193,8 @@ static void test_validator_valid() {
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct Error *error = validate_spec_json(fixture->parsed, &fixture->prompts);
|
struct Error *error =
|
||||||
|
validate_spec_json(&fixture->config, fixture->parsed, &fixture->prompts);
|
||||||
sput_fail_unless(error == 0, "valid");
|
sput_fail_unless(error == 0, "valid");
|
||||||
|
|
||||||
test_validator_teardown(fixture);
|
test_validator_teardown(fixture);
|
||||||
|
|
Loading…
Reference in New Issue