From 72cf8cfcc59f792ff48eb28c3f760678dc10090c Mon Sep 17 00:00:00 2001 From: sinanmohd Date: Tue, 30 Jul 2024 21:31:51 +0530 Subject: tests: init --- include/queue.h | 1 + include/test.h | 23 +++++++++++++++ meson.build | 13 +++++---- python-package.nix | 1 + src/evanix.c | 18 ++++++------ src/jobs.c | 19 +++++++------ src/meson.build | 2 +- src/queue.c | 4 +-- tests/dag.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/dag_merge.json | 3 ++ tests/meson.build | 19 +++++++++++++ 11 files changed, 154 insertions(+), 29 deletions(-) create mode 100644 include/test.h create mode 100644 tests/dag.c create mode 100644 tests/dag_merge.json create mode 100644 tests/meson.build diff --git a/include/queue.h b/include/queue.h index e6178e2..1cef0b3 100644 --- a/include/queue.h +++ b/include/queue.h @@ -36,6 +36,7 @@ void queue_thread_free(struct queue_thread *queue_thread); void *queue_thread_entry(void *queue_thread); int queue_pop(struct queue *queue, struct job **job); int queue_isempty(struct job_clist *jobs); +int queue_htab_job_merge(struct job **job, struct job **htab); #define QUEUE_H #endif diff --git a/include/test.h b/include/test.h new file mode 100644 index 0000000..64716cc --- /dev/null +++ b/include/test.h @@ -0,0 +1,23 @@ +#ifndef _TEST_H +#define _TEST_H + +char *__curtestname = ""; + +#define test_run(func) \ + do { \ + char *orig = __curtestname; \ + __curtestname = #func; \ + func(); \ + __curtestname = orig; \ + } while (0) + +#define test_assert(cond) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, "%s:%d: %s: test_assert failed: %s\n", __FILE__, __LINE__, \ + __curtestname, #cond); \ + abort(); \ + } \ + } while (0) + +#endif diff --git a/meson.build b/meson.build index 2bad179..b9d86e8 100644 --- a/meson.build +++ b/meson.build @@ -23,12 +23,13 @@ highs_dep = dependency('highs') evanix_inc = include_directories('include') if get_option('build-python') - py = import('python').find_installation() - py.extension_module( - 'evanix', - 'src/evanix-py.c', - install: true, - ) + py = import('python').find_installation() + py.extension_module( + 'evanix', + 'src/evanix-py.c', + install: true, + ) endif subdir('src') +subdir('tests') diff --git a/python-package.nix b/python-package.nix index faedbb9..deeb594 100644 --- a/python-package.nix +++ b/python-package.nix @@ -23,6 +23,7 @@ buildPythonPackage { root = ./.; fileset = fs.unions [ ./src + ./tests ./include ./meson.build ./meson_options.txt diff --git a/src/evanix.c b/src/evanix.c index 608345d..d46a366 100644 --- a/src/evanix.c +++ b/src/evanix.c @@ -66,24 +66,20 @@ static int evanix(char *expr) { struct queue_thread *queue_thread = NULL; struct build_thread *build_thread = NULL; - FILE *jobsStream = NULL; /* nix-eval-jobs stdout */ + FILE *jobs_stream = NULL; /* nix-eval-jobs stdout */ int ret = 0; - ret = jobs_init(&jobsStream, expr); + ret = jobs_init(&jobs_stream, expr); if (ret < 0) goto out_free; - ret = queue_thread_new(&queue_thread, jobsStream); - if (ret < 0) { - free(jobsStream); + ret = queue_thread_new(&queue_thread, jobs_stream); + if (ret < 0) goto out_free; - } ret = build_thread_new(&build_thread, queue_thread->queue); - if (ret < 0) { - free(jobsStream); + if (ret < 0) goto out_free; - } ret = pthread_create(&queue_thread->tid, NULL, queue_thread_entry, queue_thread); @@ -122,8 +118,10 @@ static int evanix(char *expr) } out_free: + fclose(jobs_stream); queue_thread_free(queue_thread); free(build_thread); + return ret; } @@ -153,7 +151,7 @@ int opts_read(struct evanix_opts_t *opts, char **expr, int argc, char *argv[]) switch (c) { case 'h': printf("%s", usage); - return -EINVAL; + return 0; break; case 'f': opts->isflake = true; diff --git a/src/jobs.c b/src/jobs.c index 845df08..cb5fe3b 100644 --- a/src/jobs.c +++ b/src/jobs.c @@ -332,15 +332,16 @@ int job_read(FILE *stream, struct job **job) goto out_free; } - temp = cJSON_GetObjectItemCaseSensitive(root, "system"); - if (!cJSON_IsString(temp)) { - ret = JOB_READ_JSON_INVAL; - goto out_free; - } - if (evanix_opts.system != NULL && - strcmp(evanix_opts.system, temp->valuestring)) { - ret = JOB_READ_SYS_MISMATCH; - goto out_free; + if (evanix_opts.system != NULL) { + temp = cJSON_GetObjectItemCaseSensitive(root, "system"); + if (!cJSON_IsString(temp)) { + ret = JOB_READ_JSON_INVAL; + goto out_free; + } + if (strcmp(evanix_opts.system, temp->valuestring)) { + ret = JOB_READ_SYS_MISMATCH; + goto out_free; + } } temp = cJSON_GetObjectItemCaseSensitive(root, "name"); diff --git a/src/meson.build b/src/meson.build index d6cfb00..b88a0da 100644 --- a/src/meson.build +++ b/src/meson.build @@ -19,4 +19,4 @@ e = executable( c_args: [f'-DNIX_EVAL_JOBS_PATH=@NIX_EVAL_JOBS_PATH@'], ) -test('evanix', e) +test('evanix', e, args: '--help') diff --git a/src/queue.c b/src/queue.c index bbfbb0f..b914d0f 100644 --- a/src/queue.c +++ b/src/queue.c @@ -13,7 +13,6 @@ #define MAX_NIX_PKG_COUNT 200000 static int queue_push(struct queue *queue, struct job *job); -static int queue_htab_job_merge(struct job **job, struct job **htab); static int queue_dag_isolate(struct job *job, struct job *keep_parent, struct job_clist *jobs, struct job **htab); @@ -129,7 +128,7 @@ out_mutex_unlock: * - only childrens or dependencies have parent node * - only root node have dependencies */ -static int queue_htab_job_merge(struct job **job, struct job **htab) +int queue_htab_job_merge(struct job **job, struct job **htab) { int ret; struct job *jtab = NULL; @@ -221,7 +220,6 @@ void queue_thread_free(struct queue_thread *queue_thread) print_err("%s", strerror(errno)); free(queue_thread->queue); - fclose(queue_thread->stream); free(queue_thread); } diff --git a/tests/dag.c b/tests/dag.c new file mode 100644 index 0000000..065536b --- /dev/null +++ b/tests/dag.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include "util.h" +#include "queue.h" +#include "evanix.h" +#include "solver_sjf.h" +#include "test.h" + +/* + * A C A C + * \ + + / = \ / + * B B B B + */ + +struct evanix_opts_t evanix_opts = { + .close_unused_fd = false, + .isflake = false, + .ispipelined = true, + .isdryrun = false, + .max_build = 0, + .system = NULL, + .solver_report = false, + .check_cache_status = false, + .solver = solver_sjf, + .break_evanix = false, +}; + +static void test_merge() +{ + FILE *stream; + struct job *job, *a, *b, *c; + struct queue_thread *qt; + int ret; + + stream = fopen("../tests/dag_merge.json", "r"); + test_assert(stream != NULL); + + ret = queue_thread_new(&qt, stream); + if (ret < 0) + goto out_free_stram; + + + /* A */ + ret = job_read(qt->stream, &job); + test_assert(ret == JOB_READ_SUCCESS); + ret = queue_htab_job_merge(&job, &qt->queue->htab); + test_assert(ret >= 0); + a = job; + + /* B */ + ret = job_read(qt->stream, &job); + test_assert(ret == JOB_READ_SUCCESS); + ret = queue_htab_job_merge(&job, &qt->queue->htab); + test_assert(ret >= 0); + b = job; + + /* C */ + ret = job_read(qt->stream, &job); + test_assert(ret == JOB_READ_SUCCESS); + ret = queue_htab_job_merge(&job, &qt->queue->htab); + test_assert(ret >= 0); + c = job; + + ret = job_read(qt->stream, &job); + test_assert(ret == JOB_READ_EOF); + + test_assert(a->deps[0] == b); + test_assert(a->deps[0] == c->deps[0]); + +out_free_stram: + fclose(stream); + queue_thread_free(qt); +} + +int main(void) +{ + test_run(test_merge); +} diff --git a/tests/dag_merge.json b/tests/dag_merge.json new file mode 100644 index 0000000..5aca18e --- /dev/null +++ b/tests/dag_merge.json @@ -0,0 +1,3 @@ +{"name":"a","attr":"a","drvPath":"/nox/store/a.drv","inputDrvs":{"/nox/store/b.drv":["out"]},"outputs":{"out":"/nox/store/a"}} +{"attr":"b","name":"b","drvPath":"/nox/store/b.drv","inputDrvs":{},"outputs":{"out":"/nox/store/b"}} +{"name":"c","attr":"c","drvPath":"/nox/store/c.drv","inputDrvs":{"/nox/store/b.drv":["out"]},"outputs":{"out":"/nox/store/b"}} diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..22ce6b8 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,19 @@ +dag_test = executable( + 'dag_test', + [ + 'dag.c', + '../src/jobs.c', + '../src/util.c', + '../src/queue.c', + '../src/build.c', + '../src/jobid.c', + '../src/solver_conformity.c', + '../src/solver_highs.c', + '../src/solver_sjf.c', + ], + + include_directories: evanix_inc, + dependencies: [ cjson_dep, highs_dep ], +) + +test('dag', dag_test) -- cgit v1.2.3