summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/queue.h1
-rw-r--r--include/test.h23
-rw-r--r--meson.build13
-rw-r--r--python-package.nix1
-rw-r--r--src/evanix.c18
-rw-r--r--src/jobs.c19
-rw-r--r--src/meson.build2
-rw-r--r--src/queue.c4
-rw-r--r--tests/dag.c80
-rw-r--r--tests/dag_merge.json3
-rw-r--r--tests/meson.build19
11 files changed, 154 insertions, 29 deletions
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 = "<none>";
+
+#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 <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#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)