Commit b931f476 authored by Rusty Russell's avatar Rusty Russell

ccanlint: keep separate array of compiled versions.

Rather than mug the old ->compiled version when we reduce features,
keep both in the structure.  This makes it clear that we are using the
right version (we weren't in all cases, in particular we weren't
recompiling the test helpers correctly.
parent ad6a6711
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
4 == Describe every action. */ 4 == Describe every action. */
extern int verbose; extern int verbose;
enum compile_type {
COMPILE_NORMAL,
COMPILE_NOFEAT,
COMPILE_TYPES
};
struct manifest { struct manifest {
char *dir; char *dir;
/* The module name, ie. final element of dir name */ /* The module name, ie. final element of dir name */
...@@ -26,7 +32,7 @@ struct manifest { ...@@ -26,7 +32,7 @@ struct manifest {
/* Linked off deps. */ /* Linked off deps. */
struct list_node list; struct list_node list;
/* Where our final compiled output is */ /* Where our final compiled output is */
char *compiled; char *compiled[COMPILE_TYPES];
struct list_head c_files; struct list_head c_files;
struct list_head h_files; struct list_head h_files;
...@@ -174,7 +180,7 @@ struct ccan_file { ...@@ -174,7 +180,7 @@ struct ccan_file {
struct list_head *doc_sections; struct list_head *doc_sections;
/* If this file gets compiled (eg. .C file to .o file), result here. */ /* If this file gets compiled (eg. .C file to .o file), result here. */
char *compiled; char *compiled[COMPILE_TYPES];
/* Compiled with coverage information. */ /* Compiled with coverage information. */
char *cov_compiled; char *cov_compiled;
......
#ifndef CCANLINT_BUILD_H #ifndef CCANLINT_BUILD_H
#define CCANLINT_BUILD_H #define CCANLINT_BUILD_H
char *build_module(struct manifest *m, bool keep, char **errstr); char *build_module(struct manifest *m, bool keep, enum compile_type ctype,
char *build_submodule(struct manifest *m); char **errstr);
char *build_submodule(struct manifest *m, const char *flags,
enum compile_type ctype);
void build_objects(struct manifest *m, void build_objects(struct manifest *m,
bool keep, struct score *score, const char *flags); bool keep, struct score *score, const char *flags,
enum compile_type ctype);
#endif /* CCANLINT_BUILD_H */ #endif /* CCANLINT_BUILD_H */
...@@ -28,7 +28,9 @@ static bool expect_obj_file(struct manifest *m) ...@@ -28,7 +28,9 @@ static bool expect_obj_file(struct manifest *m)
return !list_empty(&m->c_files); return !list_empty(&m->c_files);
} }
static char *build_subdir_objs(struct manifest *m) static char *build_subdir_objs(struct manifest *m,
const char *flags,
enum compile_type ctype)
{ {
struct ccan_file *i; struct ccan_file *i;
...@@ -36,11 +38,11 @@ static char *build_subdir_objs(struct manifest *m) ...@@ -36,11 +38,11 @@ static char *build_subdir_objs(struct manifest *m)
char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name); char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name);
char *output; char *output;
i->compiled = maybe_temp_file(m, "", false, fullfile); i->compiled[ctype] = maybe_temp_file(m, "", false, fullfile);
if (!compile_object(m, fullfile, ccan_dir, compiler, cflags, if (!compile_object(m, fullfile, ccan_dir, compiler, flags,
i->compiled, &output)) { i->compiled[ctype], &output)) {
talloc_free(i->compiled); talloc_free(i->compiled[ctype]);
i->compiled = NULL; i->compiled[ctype] = NULL;
return talloc_asprintf(m, return talloc_asprintf(m,
"Dependency %s" "Dependency %s"
" did not build:\n%s", " did not build:\n%s",
...@@ -50,11 +52,12 @@ static char *build_subdir_objs(struct manifest *m) ...@@ -50,11 +52,12 @@ static char *build_subdir_objs(struct manifest *m)
return NULL; return NULL;
} }
char *build_submodule(struct manifest *m) char *build_submodule(struct manifest *m, const char *flags,
enum compile_type ctype)
{ {
char *errstr; char *errstr;
if (m->compiled) if (m->compiled[ctype])
return NULL; return NULL;
if (!expect_obj_file(m)) if (!expect_obj_file(m))
...@@ -63,12 +66,12 @@ char *build_submodule(struct manifest *m) ...@@ -63,12 +66,12 @@ char *build_submodule(struct manifest *m)
if (verbose >= 2) if (verbose >= 2)
printf(" Building dependency %s\n", m->dir); printf(" Building dependency %s\n", m->dir);
errstr = build_subdir_objs(m); errstr = build_subdir_objs(m, flags, ctype);
if (errstr) if (errstr)
return errstr; return errstr;
m->compiled = build_module(m, false, &errstr); m->compiled[ctype] = build_module(m, false, ctype, &errstr);
if (!m->compiled) if (!m->compiled[ctype])
return errstr; return errstr;
return NULL; return NULL;
} }
...@@ -80,7 +83,7 @@ static void check_depends_built(struct manifest *m, ...@@ -80,7 +83,7 @@ static void check_depends_built(struct manifest *m,
struct manifest *i; struct manifest *i;
list_for_each(&m->deps, i, list) { list_for_each(&m->deps, i, list) {
char *errstr = build_submodule(i); char *errstr = build_submodule(i, cflags, COMPILE_NORMAL);
if (errstr) { if (errstr) {
score->error = talloc_asprintf(score, score->error = talloc_asprintf(score,
......
...@@ -33,6 +33,7 @@ static bool add_dep(struct manifest *m, const char *dep, struct score *score) ...@@ -33,6 +33,7 @@ static bool add_dep(struct manifest *m, const char *dep, struct score *score)
return true; return true;
} }
/* FIXME: check this is still true once we reduce features. */
static void check_depends_exist(struct manifest *m, static void check_depends_exist(struct manifest *m,
bool keep, bool keep,
unsigned int *timeleft, struct score *score) unsigned int *timeleft, struct score *score)
...@@ -47,7 +48,8 @@ static void check_depends_exist(struct manifest *m, ...@@ -47,7 +48,8 @@ static void check_depends_exist(struct manifest *m,
if (safe_mode) if (safe_mode)
deps = get_safe_ccan_deps(m, m->dir, true); deps = get_safe_ccan_deps(m, m->dir, true);
else else
deps = get_deps(m, m->dir, true, &m->info_file->compiled); deps = get_deps(m, m->dir, true,
&m->info_file->compiled[COMPILE_NORMAL]);
for (i = 0; deps[i]; i++) { for (i = 0; deps[i]; i++) {
if (!strstarts(deps[i], "ccan/")) if (!strstarts(deps[i], "ccan/"))
......
...@@ -22,24 +22,28 @@ static const char *can_build(struct manifest *m) ...@@ -22,24 +22,28 @@ static const char *can_build(struct manifest *m)
return NULL; return NULL;
} }
static char *obj_list(const struct manifest *m) static char *obj_list(const struct manifest *m, enum compile_type ctype)
{ {
char *list = talloc_strdup(m, ""); char *list = talloc_strdup(m, "");
struct ccan_file *i; struct ccan_file *i;
/* Objects from all the C files. */ /* Objects from all the C files. */
list_for_each(&m->c_files, i, list) list_for_each(&m->c_files, i, list)
list = talloc_asprintf_append(list, "%s ", i->compiled); list = talloc_asprintf_append(list, "%s ",
i->compiled[ctype]);
return list; return list;
} }
char *build_module(struct manifest *m, bool keep, char **errstr) char *build_module(struct manifest *m, bool keep,
enum compile_type ctype, char **errstr)
{ {
char *name = link_objects(m, m->basename, false, obj_list(m), errstr); char *name = link_objects(m, m->basename, false, obj_list(m, ctype),
errstr);
if (name) { if (name) {
if (keep) { if (keep) {
char *realname = talloc_asprintf(m, "%s.o", m->dir); char *realname = talloc_asprintf(m, "%s.o", m->dir);
assert(ctype == COMPILE_NORMAL);
/* We leave this object file around, all built. */ /* We leave this object file around, all built. */
if (!move_file(name, realname)) if (!move_file(name, realname))
err(1, "Renaming %s to %s", name, realname); err(1, "Renaming %s to %s", name, realname);
...@@ -63,8 +67,9 @@ static void do_build(struct manifest *m, ...@@ -63,8 +67,9 @@ static void do_build(struct manifest *m,
return; return;
} }
m->compiled = build_module(m, keep, &errstr); m->compiled[COMPILE_NORMAL]
if (!m->compiled) { = build_module(m, keep, COMPILE_NORMAL, &errstr);
if (!m->compiled[COMPILE_NORMAL]) {
score_file_error(score, NULL, 0, "%s", errstr); score_file_error(score, NULL, 0, "%s", errstr);
return; return;
} }
......
...@@ -28,9 +28,10 @@ static char *obj_list(const struct manifest *m) ...@@ -28,9 +28,10 @@ static char *obj_list(const struct manifest *m)
/* Other CCAN deps. */ /* Other CCAN deps. */
list_for_each(&m->deps, i, list) { list_for_each(&m->deps, i, list) {
if (i->compiled) if (i->compiled[COMPILE_NORMAL])
list = talloc_asprintf_append(list, "%s ", list = talloc_asprintf_append(list, "%s ",
i->compiled); i->compiled
[COMPILE_NORMAL]);
} }
return list; return list;
} }
...@@ -38,7 +39,8 @@ static char *obj_list(const struct manifest *m) ...@@ -38,7 +39,8 @@ static char *obj_list(const struct manifest *m)
static char *lib_list(const struct manifest *m) static char *lib_list(const struct manifest *m)
{ {
unsigned int i, num; unsigned int i, num;
char **libs = get_libs(m, ".", &num, &m->info_file->compiled); char **libs = get_libs(m, ".",
&num, &m->info_file->compiled[COMPILE_NORMAL]);
char *ret = talloc_strdup(m, ""); char *ret = talloc_strdup(m, "");
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
......
...@@ -23,7 +23,8 @@ static const char *can_build(struct manifest *m) ...@@ -23,7 +23,8 @@ static const char *can_build(struct manifest *m)
} }
void build_objects(struct manifest *m, void build_objects(struct manifest *m,
bool keep, struct score *score, const char *flags) bool keep, struct score *score, const char *flags,
enum compile_type ctype)
{ {
struct ccan_file *i; struct ccan_file *i;
bool errors = false, warnings = false; bool errors = false, warnings = false;
...@@ -37,10 +38,10 @@ void build_objects(struct manifest *m, ...@@ -37,10 +38,10 @@ void build_objects(struct manifest *m,
char *output; char *output;
char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name); char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name);
i->compiled = maybe_temp_file(m, "", keep, fullfile); i->compiled[ctype] = maybe_temp_file(m, "", keep, fullfile);
if (!compile_object(score, fullfile, ccan_dir, compiler, flags, if (!compile_object(score, fullfile, ccan_dir, compiler, flags,
i->compiled, &output)) { i->compiled[ctype], &output)) {
talloc_free(i->compiled); talloc_free(i->compiled[ctype]);
score_file_error(score, i, 0, score_file_error(score, i, 0,
"Compiling object files:\n%s", "Compiling object files:\n%s",
output); output);
...@@ -64,7 +65,7 @@ static void check_objs_build(struct manifest *m, ...@@ -64,7 +65,7 @@ static void check_objs_build(struct manifest *m,
bool keep, bool keep,
unsigned int *timeleft, struct score *score) unsigned int *timeleft, struct score *score)
{ {
build_objects(m, keep, score, cflags); build_objects(m, keep, score, cflags, COMPILE_NORMAL);
} }
struct ccanlint objects_build = { struct ccanlint objects_build = {
......
...@@ -81,7 +81,7 @@ struct ccan_file *new_ccan_file(const void *ctx, const char *dir, char *name) ...@@ -81,7 +81,7 @@ struct ccan_file *new_ccan_file(const void *ctx, const char *dir, char *name)
f->lines = NULL; f->lines = NULL;
f->line_info = NULL; f->line_info = NULL;
f->doc_sections = NULL; f->doc_sections = NULL;
f->compiled = NULL; f->compiled[COMPILE_NORMAL] = f->compiled[COMPILE_NOFEAT] = NULL;
f->name = talloc_steal(f, name); f->name = talloc_steal(f, name);
f->fullname = talloc_asprintf(f, "%s/%s", dir, f->name); f->fullname = talloc_asprintf(f, "%s/%s", dir, f->name);
f->contents = NULL; f->contents = NULL;
...@@ -229,7 +229,7 @@ struct manifest *get_manifest(const void *ctx, const char *dir) ...@@ -229,7 +229,7 @@ struct manifest *get_manifest(const void *ctx, const char *dir)
m = talloc_linked(ctx, talloc(NULL, struct manifest)); m = talloc_linked(ctx, talloc(NULL, struct manifest));
m->info_file = NULL; m->info_file = NULL;
m->compiled = NULL; m->compiled[COMPILE_NORMAL] = m->compiled[COMPILE_NOFEAT] = NULL;
m->dir = talloc_steal(m, canon_dir); m->dir = talloc_steal(m, canon_dir);
list_head_init(&m->c_files); list_head_init(&m->c_files);
list_head_init(&m->h_files); list_head_init(&m->h_files);
......
#include <tools/ccanlint/ccanlint.h>
#include <tools/tools.h>
#include <ccan/talloc/talloc.h>
#include <ccan/str/str.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <string.h>
#include <ctype.h>
#include "../compulsory_tests/build.h"
static const char *can_build(struct manifest *m)
{
if (safe_mode)
return "Safe mode enabled";
return NULL;
}
static void check_depends_built_without_features(struct manifest *m,
bool keep,
unsigned int *timeleft,
struct score *score)
{
struct manifest *i;
char *flags;
flags = talloc_asprintf(score, "%s -I.", cflags);
list_for_each(&m->deps, i, list) {
char *errstr = build_submodule(i, flags, COMPILE_NOFEAT);
if (errstr) {
score->error = talloc_asprintf(score,
"Dependency %s"
" did not build:\n%s",
i->basename, errstr);
return;
}
}
score->pass = true;
score->score = score->total;
}
struct ccanlint depends_build_without_features = {
.key = "depends_build_without_features",
.name = "Module's CCAN dependencies can be found or built (reduced features)",
.check = check_depends_built_without_features,
.can_run = can_build,
.needs = "depends_exist"
};
REGISTER_TEST(depends_build_without_features);
...@@ -51,7 +51,7 @@ static void add_dep(struct manifest ***deps, const char *basename) ...@@ -51,7 +51,7 @@ static void add_dep(struct manifest ***deps, const char *basename)
m = get_manifest(*deps, talloc_asprintf(*deps, "%s/ccan/%s", m = get_manifest(*deps, talloc_asprintf(*deps, "%s/ccan/%s",
ccan_dir, basename)); ccan_dir, basename));
errstr = build_submodule(m); errstr = build_submodule(m, cflags, COMPILE_NORMAL);
if (errstr) if (errstr)
errx(1, "%s", errstr); errx(1, "%s", errstr);
...@@ -62,7 +62,8 @@ static void add_dep(struct manifest ***deps, const char *basename) ...@@ -62,7 +62,8 @@ static void add_dep(struct manifest ***deps, const char *basename)
if (m->info_file) { if (m->info_file) {
char **infodeps; char **infodeps;
infodeps = get_deps(m, m->dir, false, &m->info_file->compiled); infodeps = get_deps(m, m->dir, false,
&m->info_file->compiled[COMPILE_NORMAL]);
for (i = 0; infodeps[i]; i++) { for (i = 0; infodeps[i]; i++) {
if (strstarts(infodeps[i], "ccan/")) if (strstarts(infodeps[i], "ccan/"))
...@@ -96,19 +97,23 @@ static char *example_obj_list(struct manifest *m, struct ccan_file *f) ...@@ -96,19 +97,23 @@ static char *example_obj_list(struct manifest *m, struct ccan_file *f)
list = talloc_strdup(f, ""); list = talloc_strdup(f, "");
for (i = 0; i < talloc_get_size(deps) / sizeof(*deps); i++) { for (i = 0; i < talloc_get_size(deps) / sizeof(*deps); i++) {
if (deps[i]->compiled) if (deps[i]->compiled[COMPILE_NORMAL])
list = talloc_asprintf_append(list, " %s", list = talloc_asprintf_append(list, " %s",
deps[i]->compiled); deps[i]->compiled
[COMPILE_NORMAL]);
} }
return list; return list;
} }
/* FIXME: Test with reduced features! */
static char *lib_list(const struct manifest *m) static char *lib_list(const struct manifest *m)
{ {
unsigned int i, num; unsigned int i, num;
char **libs = get_libs(m, m->dir, &num, &m->info_file->compiled); char **libs;
char *ret = talloc_strdup(m, ""); char *ret = talloc_strdup(m, "");
libs = get_libs(m, m->dir, &num,
&m->info_file->compiled[COMPILE_NORMAL]);
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
ret = talloc_asprintf_append(ret, "-l%s ", libs[i]); ret = talloc_asprintf_append(ret, "-l%s ", libs[i]);
return ret; return ret;
...@@ -119,16 +124,18 @@ static bool compile(const void *ctx, ...@@ -119,16 +124,18 @@ static bool compile(const void *ctx,
struct ccan_file *file, struct ccan_file *file,
bool keep, char **output) bool keep, char **output)
{ {
file->compiled = maybe_temp_file(ctx, "", keep, file->fullname); file->compiled[COMPILE_NORMAL]
= maybe_temp_file(ctx, "", keep, file->fullname);
if (!compile_and_link(ctx, file->fullname, ccan_dir, if (!compile_and_link(ctx, file->fullname, ccan_dir,
example_obj_list(m, file), example_obj_list(m, file),
compiler, cflags, compiler, cflags,
lib_list(m), file->compiled, output)) { lib_list(m), file->compiled[COMPILE_NORMAL],
output)) {
/* Don't keep failures. */ /* Don't keep failures. */
if (keep) if (keep)
unlink(file->compiled); unlink(file->compiled[COMPILE_NORMAL]);
talloc_free(file->compiled); talloc_free(file->compiled[COMPILE_NORMAL]);
file->compiled = NULL; file->compiled[COMPILE_NORMAL] = NULL;
return false; return false;
} }
return true; return true;
......
...@@ -209,7 +209,7 @@ static char *unexpected(struct ccan_file *i, const char *input, ...@@ -209,7 +209,7 @@ static char *unexpected(struct ccan_file *i, const char *input,
unsigned int default_time = default_timeout_ms; unsigned int default_time = default_timeout_ms;
cmd = talloc_asprintf(i, "echo '%s' | %s %s", cmd = talloc_asprintf(i, "echo '%s' | %s %s",
input, i->compiled, input); input, i->compiled[COMPILE_NORMAL], input);
output = run_with_timeout(i, cmd, &ok, &default_time); output = run_with_timeout(i, cmd, &ok, &default_time);
if (!ok) if (!ok)
...@@ -248,7 +248,7 @@ static void run_examples(struct manifest *m, bool keep, ...@@ -248,7 +248,7 @@ static void run_examples(struct manifest *m, bool keep,
linenum++, linenum++,
expect = find_expect(i, lines, &input, expect = find_expect(i, lines, &input,
&exact, &linenum)) { &exact, &linenum)) {
if (i->compiled == NULL) if (i->compiled[COMPILE_NORMAL] == NULL)
continue; continue;
score->total++; score->total++;
...@@ -268,6 +268,7 @@ static void run_examples(struct manifest *m, bool keep, ...@@ -268,6 +268,7 @@ static void run_examples(struct manifest *m, bool keep,
} }
} }
/* FIXME: Test with reduced features, valgrind! */
struct ccanlint examples_run = { struct ccanlint examples_run = {
.key = "examples_run", .key = "examples_run",
.name = "Module examples with expected output give that output", .name = "Module examples with expected output give that output",
......
...@@ -8,7 +8,7 @@ static void check_objs_build_without_features(struct manifest *m, ...@@ -8,7 +8,7 @@ static void check_objs_build_without_features(struct manifest *m,
struct score *score) struct score *score)
{ {
const char *flags = talloc_asprintf(score, "-I. %s", cflags); const char *flags = talloc_asprintf(score, "-I. %s", cflags);
build_objects(m, keep, score, flags); build_objects(m, keep, score, flags, COMPILE_NOFEAT);
} }
struct ccanlint objects_build_without_features = { struct ccanlint objects_build_without_features = {
......
...@@ -23,8 +23,8 @@ static const char *can_build(struct manifest *m) ...@@ -23,8 +23,8 @@ static const char *can_build(struct manifest *m)
return NULL; return NULL;
} }
/* FIXME: Merge this into one place. */ static char *obj_list(const struct manifest *m, bool link_with_module,
static char *obj_list(const struct manifest *m, bool link_with_module) enum compile_type ctype)
{ {
char *list = talloc_strdup(m, ""); char *list = talloc_strdup(m, "");
struct ccan_file *i; struct ccan_file *i;
...@@ -32,27 +32,30 @@ static char *obj_list(const struct manifest *m, bool link_with_module) ...@@ -32,27 +32,30 @@ static char *obj_list(const struct manifest *m, bool link_with_module)
/* Objects from any other C files. */ /* Objects from any other C files. */
list_for_each(&m->other_test_c_files, i, list) list_for_each(&m->other_test_c_files, i, list)
list = talloc_asprintf_append(list, " %s", i->compiled); list = talloc_asprintf_append(list, " %s",
i->compiled[ctype]);
/* Our own object files. */ /* Our own object files. */
if (link_with_module) if (link_with_module)
list_for_each(&m->c_files, i, list) list_for_each(&m->c_files, i, list)
list = talloc_asprintf_append(list, " %s", i->compiled); list = talloc_asprintf_append(list, " %s",
i->compiled[ctype]);
/* Other ccan modules. */ /* Other ccan modules. */
list_for_each(&m->deps, subm, list) { list_for_each(&m->deps, subm, list) {
if (subm->compiled) if (subm->compiled[ctype])
list = talloc_asprintf_append(list, " %s", list = talloc_asprintf_append(list, " %s",
subm->compiled); subm->compiled[ctype]);
} }
return list; return list;
} }
static char *lib_list(const struct manifest *m) static char *lib_list(const struct manifest *m, enum compile_type ctype)
{ {
unsigned int i, num; unsigned int i, num;
char **libs = get_libs(m, m->dir, &num, &m->info_file->compiled); char **libs = get_libs(m, m->dir, &num,
&m->info_file->compiled[ctype]);
char *ret = talloc_strdup(m, ""); char *ret = talloc_strdup(m, "");
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
...@@ -63,26 +66,34 @@ static char *lib_list(const struct manifest *m) ...@@ -63,26 +66,34 @@ static char *lib_list(const struct manifest *m)
static bool compile(const void *ctx, static bool compile(const void *ctx,
struct manifest *m, struct manifest *m,
struct ccan_file *file, struct ccan_file *file,
const char *flags,
bool fail, bool fail,
bool link_with_module, bool link_with_module,
bool keep, char **output) bool keep,
enum compile_type ctype,
char **output)
{ {
char *f = talloc_asprintf(ctx, "%s%s%s", char *fname, *flags;
flags, fail ? "-DFAIL " : "", cflags);
flags = talloc_asprintf(ctx, "%s%s%s",
fail ? "-DFAIL " : "",
cflags,
ctype == COMPILE_NOFEAT ? " -I." : "");
file->compiled = maybe_temp_file(ctx, "", keep, file->fullname); fname = maybe_temp_file(ctx, "", keep, file->fullname);
if (!compile_and_link(ctx, file->fullname, ccan_dir, if (!compile_and_link(ctx, file->fullname, ccan_dir,
obj_list(m, link_with_module), compiler, f, obj_list(m, link_with_module, ctype), compiler,
lib_list(m), file->compiled, output)) { flags, lib_list(m, ctype), fname, output)) {
talloc_free(file->compiled); talloc_free(fname);
return false; return false;
} }
file->compiled[ctype] = fname;
return true; return true;
} }
static void compile_tests(struct manifest *m, bool keep, static void compile_tests(struct manifest *m, bool keep,
struct score *score, const char *incl) struct score *score,
enum compile_type ctype)
{ {
char *cmdout; char *cmdout;
struct ccan_file *i; struct ccan_file *i;
...@@ -91,8 +102,9 @@ static void compile_tests(struct manifest *m, bool keep, ...@@ -91,8 +102,9 @@ static void compile_tests(struct manifest *m, bool keep,
foreach_ptr(list, &m->compile_ok_tests, &m->run_tests, &m->api_tests) { foreach_ptr(list, &m->compile_ok_tests, &m->run_tests, &m->api_tests) {
list_for_each(list, i, list) { list_for_each(list, i, list) {
if (!compile(score, m, i, incl, false, if (!compile(score, m, i, false,
list == &m->api_tests, keep, &cmdout)) { list == &m->api_tests, keep,
ctype, &cmdout)) {
score_file_error(score, i, 0, score_file_error(score, i, 0,
"Compile failed:\n%s", "Compile failed:\n%s",
cmdout); cmdout);
...@@ -112,7 +124,8 @@ static void compile_tests(struct manifest *m, bool keep, ...@@ -112,7 +124,8 @@ static void compile_tests(struct manifest *m, bool keep,
/* For historical reasons, "fail" often means "gives warnings" */ /* For historical reasons, "fail" often means "gives warnings" */
list_for_each(&m->compile_fail_tests, i, list) { list_for_each(&m->compile_fail_tests, i, list) {
if (!compile(score, m, i, incl, false, false, false, &cmdout)) { if (!compile(score, m, i, false, false, false,
ctype, &cmdout)) {
score_file_error(score, i, 0, score_file_error(score, i, 0,
"Compile without -DFAIL failed:\n%s", "Compile without -DFAIL failed:\n%s",
cmdout); cmdout);
...@@ -125,7 +138,8 @@ static void compile_tests(struct manifest *m, bool keep, ...@@ -125,7 +138,8 @@ static void compile_tests(struct manifest *m, bool keep,
cmdout); cmdout);
return; return;
} }
if (compile(score, m, i, incl, true, false, false, &cmdout) if (compile(score, m, i, true, false, false,
ctype, &cmdout)
&& streq(cmdout, "")) { && streq(cmdout, "")) {
score_file_error(score, i, 0, score_file_error(score, i, 0,
"Compiled successfully with -DFAIL?"); "Compiled successfully with -DFAIL?");
...@@ -142,7 +156,7 @@ static void do_compile_tests(struct manifest *m, ...@@ -142,7 +156,7 @@ static void do_compile_tests(struct manifest *m,
bool keep, bool keep,
unsigned int *timeleft, struct score *score) unsigned int *timeleft, struct score *score)
{ {
return compile_tests(m, keep, score, ""); compile_tests(m, keep, score, COMPILE_NORMAL);
} }
struct ccanlint tests_compile = { struct ccanlint tests_compile = {
...@@ -167,7 +181,7 @@ static void do_compile_tests_without_features(struct manifest *m, ...@@ -167,7 +181,7 @@ static void do_compile_tests_without_features(struct manifest *m,
unsigned int *timeleft, unsigned int *timeleft,
struct score *score) struct score *score)
{ {
compile_tests(m, keep, score, "-I. "); compile_tests(m, keep, score, COMPILE_NOFEAT);
} }
struct ccanlint tests_compile_without_features = { struct ccanlint tests_compile_without_features = {
...@@ -175,6 +189,6 @@ struct ccanlint tests_compile_without_features = { ...@@ -175,6 +189,6 @@ struct ccanlint tests_compile_without_features = {
.name = "Module tests compile (without features)", .name = "Module tests compile (without features)",
.check = do_compile_tests_without_features, .check = do_compile_tests_without_features,
.can_run = features_reduced, .can_run = features_reduced,
.needs = "tests_compile reduce_features" .needs = "tests_helpers_compile_without_features reduce_features"
}; };
REGISTER_TEST(tests_compile_without_features); REGISTER_TEST(tests_compile_without_features);
...@@ -60,16 +60,18 @@ static char *obj_list(const struct manifest *m, const char *modobjs) ...@@ -60,16 +60,18 @@ static char *obj_list(const struct manifest *m, const char *modobjs)
/* Objects from any other C files. */ /* Objects from any other C files. */
list_for_each(&m->other_test_c_files, i, list) list_for_each(&m->other_test_c_files, i, list)
list = talloc_asprintf_append(list, " %s", i->compiled); list = talloc_asprintf_append(list, " %s",
i->compiled[COMPILE_NORMAL]);
if (modobjs) if (modobjs)
list = talloc_append_string(list, modobjs); list = talloc_append_string(list, modobjs);
/* Other ccan modules (don't need coverage versions of those). */ /* Other ccan modules (don't need coverage versions of those). */
list_for_each(&m->deps, subm, list) { list_for_each(&m->deps, subm, list) {
if (subm->compiled) if (subm->compiled[COMPILE_NORMAL])
list = talloc_asprintf_append(list, " %s", list = talloc_asprintf_append(list, " %s",
subm->compiled); subm->compiled
[COMPILE_NORMAL]);
} }
return list; return list;
...@@ -78,7 +80,8 @@ static char *obj_list(const struct manifest *m, const char *modobjs) ...@@ -78,7 +80,8 @@ static char *obj_list(const struct manifest *m, const char *modobjs)
static char *lib_list(const struct manifest *m) static char *lib_list(const struct manifest *m)
{ {
unsigned int i, num; unsigned int i, num;
char **libs = get_libs(m, m->dir, &num, &m->info_file->compiled); char **libs = get_libs(m, m->dir, &num,
&m->info_file->compiled[COMPILE_NORMAL]);
char *ret = talloc_strdup(m, ""); char *ret = talloc_strdup(m, "");
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
......
...@@ -138,7 +138,8 @@ static void do_run_coverage_tests(struct manifest *m, ...@@ -138,7 +138,8 @@ static void do_run_coverage_tests(struct manifest *m,
bool ran_some = false; bool ran_some = false;
/* This tells gcov where we put those .gcno files. */ /* This tells gcov where we put those .gcno files. */
outdir = talloc_dirname(score, m->info_file->compiled); outdir = talloc_dirname(score,
m->info_file->compiled[COMPILE_NORMAL]);
covcmd = talloc_asprintf(m, "gcov %s -o %s", covcmd = talloc_asprintf(m, "gcov %s -o %s",
full_gcov ? "" : "-n", full_gcov ? "" : "-n",
outdir); outdir);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <err.h> #include <err.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "reduce_features.h"
static const char *can_run(struct manifest *m) static const char *can_run(struct manifest *m)
{ {
...@@ -24,17 +25,21 @@ static const char *can_run(struct manifest *m) ...@@ -24,17 +25,21 @@ static const char *can_run(struct manifest *m)
static bool compile(struct manifest *m, static bool compile(struct manifest *m,
bool keep, bool keep,
struct ccan_file *cfile, struct ccan_file *cfile,
const char *flags,
enum compile_type ctype,
char **output) char **output)
{ {
cfile->compiled = maybe_temp_file(m, ".o", keep, cfile->fullname); cfile->compiled[ctype] = maybe_temp_file(m, ".o", keep, cfile->fullname);
return compile_object(m, cfile->fullname, ccan_dir, compiler, cflags, return compile_object(m, cfile->fullname, ccan_dir, compiler, flags,
cfile->compiled, output); cfile->compiled[ctype], output);
} }
static void do_compile_test_helpers(struct manifest *m, static void compile_test_helpers(struct manifest *m,
bool keep, bool keep,
unsigned int *timeleft, unsigned int *timeleft,
struct score *score) struct score *score,
const char *flags,
enum compile_type ctype)
{ {
struct ccan_file *i; struct ccan_file *i;
bool errors = false, warnings = false; bool errors = false, warnings = false;
...@@ -47,7 +52,7 @@ static void do_compile_test_helpers(struct manifest *m, ...@@ -47,7 +52,7 @@ static void do_compile_test_helpers(struct manifest *m,
list_for_each(&m->other_test_c_files, i, list) { list_for_each(&m->other_test_c_files, i, list) {
char *cmdout; char *cmdout;
if (!compile(m, keep, i, &cmdout)) { if (!compile(m, keep, i, flags, ctype, &cmdout)) {
errors = true; errors = true;
score_file_error(score, i, 0, "Compile failed:\n%s", score_file_error(score, i, 0, "Compile failed:\n%s",
cmdout); cmdout);
...@@ -64,6 +69,15 @@ static void do_compile_test_helpers(struct manifest *m, ...@@ -64,6 +69,15 @@ static void do_compile_test_helpers(struct manifest *m,
} }
} }
static void do_compile_test_helpers(struct manifest *m,
bool keep,
unsigned int *timeleft,
struct score *score)
{
compile_test_helpers(m, keep, timeleft, score, cflags,
COMPILE_NORMAL);
}
struct ccanlint tests_helpers_compile = { struct ccanlint tests_helpers_compile = {
.key = "tests_helpers_compile", .key = "tests_helpers_compile",
.name = "Module test helper objects compile", .name = "Module test helper objects compile",
...@@ -73,3 +87,32 @@ struct ccanlint tests_helpers_compile = { ...@@ -73,3 +87,32 @@ struct ccanlint tests_helpers_compile = {
}; };
REGISTER_TEST(tests_helpers_compile); REGISTER_TEST(tests_helpers_compile);
static const char *features_reduced(struct manifest *m)
{
if (features_were_reduced)
return NULL;
return "No features to turn off";
}
static void do_compile_test_helpers_without_features(struct manifest *m,
bool keep,
unsigned int *timeleft,
struct score *score)
{
char *flags;
flags = talloc_asprintf(score, "%s -I.", cflags);
compile_test_helpers(m, keep, timeleft, score, flags,
COMPILE_NOFEAT);
}
struct ccanlint tests_helpers_compile_without_features = {
.key = "tests_helpers_compile_without_features",
.name = "Module tests helpers compile (without features)",
.check = do_compile_test_helpers_without_features,
.can_run = features_reduced,
.needs = "depends_build_without_features tests_exist"
};
REGISTER_TEST(tests_helpers_compile_without_features);
...@@ -49,10 +49,9 @@ static const char *concat(struct score *score, char *bits[]) ...@@ -49,10 +49,9 @@ static const char *concat(struct score *score, char *bits[])
static bool run_test(void *ctx, static bool run_test(void *ctx,
struct manifest *m, struct manifest *m,
unsigned int *timeleft, char **cmdout, unsigned int *timeleft, char **cmdout,
struct ccan_file *i, struct ccan_file *i)
bool use_valgrind)
{ {
if (use_valgrind) { if (do_valgrind) {
const char *options; const char *options;
options = concat(ctx, options = concat(ctx,
per_file_options(&tests_pass_valgrind, i)); per_file_options(&tests_pass_valgrind, i));
...@@ -62,8 +61,8 @@ static bool run_test(void *ctx, ...@@ -62,8 +61,8 @@ static bool run_test(void *ctx,
* unreadable by humans *and* doesn't support * unreadable by humans *and* doesn't support
* children reporting. */ * children reporting. */
i->valgrind_log = talloc_asprintf(m, i->valgrind_log = talloc_asprintf(m,
"%s.valgrind-log", "%s.valgrind-log",
i->compiled); i->compiled[COMPILE_NORMAL]);
talloc_set_destructor(i->valgrind_log, talloc_set_destructor(i->valgrind_log,
unlink_file_destructor); unlink_file_destructor);
...@@ -73,18 +72,19 @@ static bool run_test(void *ctx, ...@@ -73,18 +72,19 @@ static bool run_test(void *ctx,
" --log-fd=3 %s %s" " --log-fd=3 %s %s"
" 3> %s", " 3> %s",
options, options,
i->compiled, i->valgrind_log); i->compiled[COMPILE_NORMAL],
i->valgrind_log);
} }
} }
return run_command(m, timeleft, cmdout, "%s", i->compiled); return run_command(m, timeleft, cmdout, "%s",
i->compiled[COMPILE_NORMAL]);
} }
static void run_tests(struct manifest *m, static void do_run_tests(struct manifest *m,
bool keep, bool keep,
unsigned int *timeleft, unsigned int *timeleft,
struct score *score, struct score *score)
bool use_valgrind)
{ {
struct list_head *list; struct list_head *list;
struct ccan_file *i; struct ccan_file *i;
...@@ -94,8 +94,7 @@ static void run_tests(struct manifest *m, ...@@ -94,8 +94,7 @@ static void run_tests(struct manifest *m,
foreach_ptr(list, &m->run_tests, &m->api_tests) { foreach_ptr(list, &m->run_tests, &m->api_tests) {
list_for_each(list, i, list) { list_for_each(list, i, list) {
score->total++; score->total++;
if (run_test(score, m, timeleft, &cmdout, i, if (run_test(score, m, timeleft, &cmdout, i))
use_valgrind))
score->score++; score->score++;
else else
score_file_error(score, i, 0, "%s", cmdout); score_file_error(score, i, 0, "%s", cmdout);
...@@ -106,21 +105,6 @@ static void run_tests(struct manifest *m, ...@@ -106,21 +105,6 @@ static void run_tests(struct manifest *m,
score->pass = true; score->pass = true;
} }
static void do_run_tests(struct manifest *m,
bool keep,
unsigned int *timeleft,
struct score *score)
{
run_tests(m, keep, timeleft, score, do_valgrind);
}
static void do_run_tests_without_features(struct manifest *m,
bool keep,
unsigned int *timeleft,
struct score *score)
{
run_tests(m, keep, timeleft, score, false);
}
/* Gcc's warn_unused_result is fascist bullshit. */ /* Gcc's warn_unused_result is fascist bullshit. */
#define doesnt_matter() #define doesnt_matter()
...@@ -136,7 +120,7 @@ static void run_under_debugger(struct manifest *m, struct score *score) ...@@ -136,7 +120,7 @@ static void run_under_debugger(struct manifest *m, struct score *score)
return; return;
command = talloc_asprintf(m, "gdb -ex 'break tap.c:139' -ex 'run' %s", command = talloc_asprintf(m, "gdb -ex 'break tap.c:139' -ex 'run' %s",
first->file->compiled); first->file->compiled[COMPILE_NORMAL]);
if (system(command)) if (system(command))
doesnt_matter(); doesnt_matter();
} }
...@@ -151,13 +135,3 @@ struct ccanlint tests_pass = { ...@@ -151,13 +135,3 @@ struct ccanlint tests_pass = {
}; };
REGISTER_TEST(tests_pass); REGISTER_TEST(tests_pass);
struct ccanlint tests_pass_without_features = {
.key = "tests_pass_without_features",
.name = "Module's run and api tests pass (without features)",
.check = do_run_tests_without_features,
.handle = run_under_debugger,
.needs = "tests_compile_without_features"
};
REGISTER_TEST(tests_pass_without_features);
...@@ -246,7 +246,7 @@ static void run_under_debugger_vg(struct manifest *m, struct score *score) ...@@ -246,7 +246,7 @@ static void run_under_debugger_vg(struct manifest *m, struct score *score)
concat(score, concat(score,
per_file_options(&tests_pass_valgrind, per_file_options(&tests_pass_valgrind,
first->file)), first->file)),
first->file->compiled); first->file->compiled[COMPILE_NORMAL]);
if (system(command)) if (system(command))
doesnt_matter(); doesnt_matter();
} }
......
#include <tools/ccanlint/ccanlint.h>
#include <tools/tools.h>
#include <ccan/talloc/talloc.h>
#include <ccan/str/str.h>
#include <ccan/foreach/foreach.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <string.h>
#include <ctype.h>
/* We don't do these under valgrind: too slow! */
static void do_run_tests_no_features(struct manifest *m,
bool keep,
unsigned int *timeleft,
struct score *score)
{
struct list_head *list;
struct ccan_file *i;
char *cmdout;
score->total = 0;
foreach_ptr(list, &m->run_tests, &m->api_tests) {
list_for_each(list, i, list) {
score->total++;
if (run_command(m, timeleft, &cmdout, "%s",
i->compiled[COMPILE_NOFEAT]))
score->score++;
else
score_file_error(score, i, 0, "%s", cmdout);
}
}
if (score->score == score->total)
score->pass = true;
}
/* Gcc's warn_unused_result is fascist bullshit. */
#define doesnt_matter()
static void run_under_debugger(struct manifest *m, struct score *score)
{
char *command;
struct file_error *first;
first = list_top(&score->per_file_errors, struct file_error, list);
if (!ask("Should I run the first failing test under the debugger?"))
return;
command = talloc_asprintf(m, "gdb -ex 'break tap.c:139' -ex 'run' %s",
first->file->compiled
[COMPILE_NOFEAT]);
if (system(command))
doesnt_matter();
}
struct ccanlint tests_pass_without_features = {
.key = "tests_pass_without_features",
.name = "Module's run and api tests pass (without features)",
.check = do_run_tests_no_features,
.handle = run_under_debugger,
.needs = "tests_compile_without_features"
};
REGISTER_TEST(tests_pass_without_features);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment