Build a list of all the features used in action tests, and lazily read
them as needed. This reduces the number of guestfs_feature_available
calls for a full run from 117 to 18.
---
generator/tests_c_api.ml | 77 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 73 insertions(+), 4 deletions(-)
diff --git a/generator/tests_c_api.ml b/generator/tests_c_api.ml
index 6be753f..8c4e5ef 100644
--- a/generator/tests_c_api.ml
+++ b/generator/tests_c_api.ml
@@ -28,6 +28,8 @@ open Optgroups
open Actions
open Structs
+module StringSet = Set.Make (String)
+
(* Generate the C API tests. *)
let rec generate_c_api_tests () =
generate_header CStyle GPLv2plus;
@@ -41,6 +43,7 @@ let rec generate_c_api_tests () =
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdbool.h>
#include \"guestfs.h\"
#include \"guestfs-internal-frontend.h\"
@@ -53,6 +56,74 @@ let rec generate_c_api_tests () =
#error Missing GUESTFS_ISO_SYSTEM_ID for the current OS
#endif
+struct feature {
+ const char *name;
+ bool read;
+ bool available;
+};
+
+";
+
+ (* Get a list of all the features. *)
+ let features =
+ List.fold_left (
+ fun acc { optional = optional; tests = tests } ->
+ let acc =
+ match optional with
+ | Some group -> StringSet.add group acc
+ | None -> acc in
+ List.fold_left (
+ fun acc test ->
+ match test with
+ | (_, IfAvailable group, _, _) -> StringSet.add group acc
+ | (_, (Always|IfNotCrossAppliance|Disabled), _, _) -> acc
+ ) acc tests
+ ) StringSet.empty all_functions in
+ let features = List.sort compare (StringSet.elements features) in
+ let nr_features = List.length features in
+ pr "size_t nr_features = %d;\n" nr_features;
+ pr "\n";
+ pr "struct feature features[%d] = {\n" nr_features;
+ List.iter (
+ fun feature ->
+ pr " { .name = \"%s\", .read = false, .available = false
},\n"
+ feature
+ ) features;
+ pr "};\n";
+ pr "\n";
+
+ pr "\
+static bool
+is_feature_available (guestfs_h *g, const char *feature)
+{
+ size_t i;
+
+ for (i = 0; i < nr_features; ++i) {
+ struct feature *f = &features[i];
+
+ if (STRNEQ (f->name, feature))
+ continue;
+
+ if (!f->read) {
+ const char *array[] = { f->name, NULL };
+ int res = guestfs_feature_available (g, (char **) array);
+ if (res < 0) {
+ fprintf (stderr,
+ \"call to guestfs_feature_available(%%s) failed: %%d,
%%s\\n\",
+ f->name, guestfs_last_errno (g), guestfs_last_error (g));
+ exit (EXIT_FAILURE);
+ }
+
+ f->available = res > 0;
+ f->read = true;
+ }
+
+ return f->available;
+ }
+
+ return false;
+}
+
";
(* Generate a list of commands which are not tested anywhere. *)
@@ -140,12 +211,10 @@ static int
* support is available in the daemon.
*)
let group_test group =
- let sym = gensym "features" in
- pr " const char *%s[] = { \"%s\", NULL };\n" sym group;
- pr " if (!guestfs_feature_available (g, (char **) %s)) {\n" sym;
+ pr " if (!is_feature_available (g, \"%s\")) {\n" group;
pr " skipped (\"%s\", \"group %%s not available in
daemon\",\n"
test_name;
- pr " %s[0]);\n" sym;
+ pr " \"%s\");\n" group;
pr " return 0;\n";
pr " }\n";
pr "\n"
--
2.1.0