Add draft for `spec.json` validation.

pull/9/head
Joshua Potter 2023-11-24 10:27:44 -07:00
parent 1194d70975
commit aba0439858
7 changed files with 97 additions and 3 deletions

26
include/validator.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef _BOOTSTRAP_VALIDATOR_H
#define _BOOTSTRAP_VALIDATOR_H
#include "cJSON.h"
#include "dyn_array.h"
enum PromptType {
PT_STRING = 1,
};
struct Prompt {
const char *key;
enum PromptType type;
};
enum SpecValidationError {
SVE_NOT_TOPLEVEL_OBJECT = 1,
// The value of a top-level key does not correspond to one of the following:
// * "$STRING"
SVE_INVALID_VALUE,
};
enum SpecValidationError
validate_spec_json(const cJSON *const parsed, struct DynArray **prompts);
#endif /* _BOOTSTRAP_VALIDATOR_H */

18
main.c
View File

@ -5,6 +5,7 @@
#include "cJSON.h"
#include "config.h"
#include "parser.h"
#include "validator.h"
const char *ENV_BOOTSTRAP_ROOT_DIR = "BOOTSTRAP_ROOT_DIR";
@ -51,10 +52,27 @@ int main(int argc, char **argv) {
goto config_cleanup;
}
// `parsed` must be free'd.
struct DynArray *prompts = 0;
switch (validate_spec_json(parsed, &prompts)) {
case SVE_NOT_TOPLEVEL_OBJECT:
fprintf(stderr, "`spec.json` top-level JSON value must be object.");
retval = EXIT_FAILURE;
goto parsed_cleanup;
case SVE_INVALID_VALUE:
fprintf(stderr, "Encountered unknown `spec.json` value type.");
retval = EXIT_FAILURE;
goto parsed_cleanup;
}
// TODO: Extract the prompts out of the `spec.json` file.
// TODO: Load in the curses interface.
// TODO: Run `run.sh`.
parsed_cleanup:
cJSON_Delete(parsed);
config_cleanup:
config_free(config);

1
specs/clang/spec.json Normal file
View File

@ -0,0 +1 @@
[]

28
src/validator.c Normal file
View File

@ -0,0 +1,28 @@
#include <assert.h>
#include "validator.h"
enum SpecValidationError
validate_spec_json(const cJSON *const parsed, struct DynArray **prompts) {
*prompts = 0;
if (!parsed) {
// Indicates no `spec.json` file was found.
return 0;
}
if (!cJSON_IsObject(parsed)) {
return SVE_NOT_TOPLEVEL_OBJECT;
}
enum SpecValidationError retval = 0;
// `cJSON_GetArraySize` works because internally objects are stored as arrays.
*prompts = dyn_array_new(cJSON_GetArraySize(parsed));
assert(0);
cleanup:
dyn_array_free(*prompts);
*prompts = 0;
return retval;
}

View File

@ -3,6 +3,7 @@
#include "test_dyn_array.h"
#include "test_parser.h"
#include "test_path.h"
#include "test_validator.h"
int main(int argc, char *argv[]) {
sput_start_testing();
@ -25,6 +26,9 @@ int main(int argc, char *argv[]) {
sput_run_test(test_parse_spec_json_minimal);
sput_run_test(test_parse_spec_json_invalid);
sput_enter_suite("validator");
sput_run_test(test_validate_spec_json_not_toplevel_object);
sput_finish_testing();
return sput_get_return_value();

View File

@ -1,5 +1,5 @@
#ifndef _BOOTSTRAP_TEST_LOADER
#define _BOOTSTRAP_TEST_LOADER
#ifndef _BOOTSTRAP_TEST_PARSER
#define _BOOTSTRAP_TEST_PARSER
#include <unistd.h>
@ -81,4 +81,4 @@ static void test_parse_spec_json_invalid() {
free(root_dir);
}
#endif /* _BOOTSTRAP_TEST_LOADER */
#endif /* _BOOTSTRAP_TEST_PARSER */

17
test/test_validator.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef _BOOTSTRAP_TEST_VALIDATOR
#define _BOOTSTRAP_TEST_VALIDATOR
#include "dyn_array.h"
#include "sput.h"
#include "validator.h"
static void test_validate_spec_json_not_toplevel_object() {
struct DynArray *prompts = 0;
cJSON *parsed = cJSON_Parse("[]");
enum SpecValidationError retval = validate_spec_json(parsed, &prompts);
sput_fail_unless(retval == SVE_NOT_TOPLEVEL_OBJECT, "not top-level object");
cJSON_Delete(parsed);
}
#endif /* _BOOTSTRAP_TEST_VALIDATOR */