Add first prompt type.

pull/9/head
Joshua Potter 2023-11-24 12:23:52 -07:00
parent 795307f2a1
commit 9eeb858a9a
7 changed files with 112 additions and 25 deletions

8
main.c
View File

@ -58,14 +58,20 @@ static int run(const char *root_dir, const char *target) {
goto cleanup_parsed;
}
// TODO: Extract the prompts out of the `spec.json` file.
// TODO: Load in the curses interface.
// TODO: Run `run.sh`.
retval = EXIT_SUCCESS;
cleanup_prompts:
if (prompts) {
dyn_array_free(prompts);
}
cleanup_parsed:
if (parsed) {
cJSON_Delete(parsed);
}
cleanup_config:
config_free(config);

View File

@ -1 +1,3 @@
[]
{
"test": "$STRING"
}

View File

@ -30,6 +30,9 @@ void dyn_array_free(struct DynArray *a) {
if (!a) {
return;
}
for (int i = 0; i < a->size; ++i) {
free(a->buf[i]);
}
free(a->buf);
free(a);
}

View File

@ -1,7 +1,22 @@
#include <assert.h>
#include <string.h>
#include "validator.h"
static struct Prompt *create_prompt(const cJSON *const kv) {
if (!kv->string) {
return 0;
}
if (cJSON_IsString(kv) && strcmp(kv->valuestring, "$STRING") == 0) {
struct Prompt *prompt = malloc(sizeof(struct Prompt));
prompt->key = kv->string;
prompt->type = PT_STRING;
return prompt;
}
return 0;
}
enum SpecValidationError
validate_spec_json(const cJSON *const parsed, struct DynArray **prompts) {
*prompts = 0;
@ -16,13 +31,27 @@ validate_spec_json(const cJSON *const parsed, struct DynArray **prompts) {
}
enum SpecValidationError retval = 0;
// `cJSON_GetArraySize` works because internally objects are stored as arrays.
// `cJSON_GetArraySize` works because internally JSON objects are stored as
// arrays.
*prompts = dyn_array_new(cJSON_GetArraySize(parsed));
assert(0);
cJSON *child = parsed->child;
while (child) {
struct Prompt *prompt = create_prompt(child);
if (!prompt) {
retval = SVE_INVALID_VALUE;
goto cleanup;
}
dyn_array_push(*prompts, prompt);
child = child->next;
}
return 0;
cleanup:
if (*prompts) {
dyn_array_free(*prompts);
*prompts = 0;
}
return retval;
}

View File

@ -29,6 +29,7 @@ int main(int argc, char *argv[]) {
sput_enter_suite("validator");
sput_run_test(test_validate_spec_json_not_toplevel_object);
sput_run_test(test_validate_spec_json_invalid_value_type);
sput_finish_testing();

View File

@ -12,13 +12,13 @@ static void test_dyn_array_zero_capacity() {
sput_fail_unless(a->size == 0, "a->size == 0");
sput_fail_unless(a->_capacity == 1, "a->_capacity == 1");
int x;
dyn_array_push(a, &x);
int *x = malloc(sizeof(int));
dyn_array_push(a, x);
sput_fail_unless(a->size == 1, "a->size == 1");
sput_fail_unless(a->_capacity == 1, "a->_capacity == 1");
int y;
dyn_array_push(a, &y);
int *y = malloc(sizeof(int));
dyn_array_push(a, y);
sput_fail_unless(a->size == 2, "a->size == 2");
sput_fail_unless(a->_capacity == 2, "a->_capacity == 2");
@ -26,24 +26,25 @@ static void test_dyn_array_zero_capacity() {
}
/*
A @DynArray with nonzero capacity can be instantiated and have entries pushed onto.
A @DynArray with nonzero capacity can be instantiated and have entries pushed
onto.
*/
static void test_dyn_array_nonzero_capacity() {
struct DynArray *a = dyn_array_new(3);
sput_fail_unless(a->size == 0, "a->size == 0");
sput_fail_unless(a->_capacity == 3, "a->_capacity == 3");
int x;
int y;
int z;
dyn_array_push(a, &x);
dyn_array_push(a, &y);
dyn_array_push(a, &z);
int *x = malloc(sizeof(int));
int *y = malloc(sizeof(int));
int *z = malloc(sizeof(int));
dyn_array_push(a, x);
dyn_array_push(a, y);
dyn_array_push(a, z);
sput_fail_unless(a->size == 3, "a->size == 3");
sput_fail_unless(a->_capacity == 3, "a->_capacity == 3");
int w;
dyn_array_push(a, &w);
int *w = malloc(sizeof(int));
dyn_array_push(a, w);
sput_fail_unless(a->size == 4, "a->size == 4");
sput_fail_unless(a->_capacity == 6, "a->_capacity == 6");

View File

@ -5,13 +5,58 @@
#include "sput.h"
#include "validator.h"
struct TestValidatorFixture {
const char *json;
struct DynArray *prompts;
cJSON *parsed;
};
static struct TestValidatorFixture *test_validator_setup(const char *json) {
struct TestValidatorFixture *fixture =
malloc(sizeof(struct TestValidatorFixture));
fixture->json = json;
fixture->prompts = 0;
fixture->parsed = cJSON_Parse(json);
return fixture;
}
static void test_validator_teardown(struct TestValidatorFixture *fixture) {
if (fixture->parsed) {
cJSON_Delete(fixture->parsed);
}
free(fixture);
}
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);
struct TestValidatorFixture *fixture = test_validator_setup("[]");
enum SpecValidationError retval =
validate_spec_json(fixture->parsed, &fixture->prompts);
sput_fail_unless(retval == SVE_NOT_TOPLEVEL_OBJECT, "not top-level object");
cJSON_Delete(parsed);
test_validator_teardown(fixture);
}
static void test_validate_spec_json_invalid_value_type() {
struct TestValidatorFixture *fixture =
test_validator_setup("{\"key\": \"$UNKNOWN\"}");
enum SpecValidationError retval =
validate_spec_json(fixture->parsed, &fixture->prompts);
sput_fail_unless(retval == SVE_INVALID_VALUE, "invalid value");
test_validator_teardown(fixture);
}
static void test_validate_spec_json_valid() {
struct TestValidatorFixture *fixture =
test_validator_setup("{\"key\": \"$STRING\"}");
enum SpecValidationError retval =
validate_spec_json(fixture->parsed, &fixture->prompts);
sput_fail_unless(retval == 0, "valid");
test_validator_teardown(fixture);
}
#endif /* _BOOTSTRAP_TEST_VALIDATOR */