builder: add Index.write_entry function

Add a function to properly write virt-builder source index entries.
Note that this function is very similar to Index.print_entry that is
meant for debugging purposes.
This commit is contained in:
Cédric Bosdonnat
2017-10-27 16:08:20 +02:00
committed by Richard W.M. Jones
parent 0933d2d818
commit 7e3689bfe0
6 changed files with 218 additions and 2 deletions

1
.gitignore vendored
View File

@@ -90,6 +90,7 @@ Makefile.in
/builder/*.img
/builder/index-parse.c
/builder/index-parse.h
/builder/index_parser_tests
/builder/index-scan.c
/builder/libguestfs.conf
/builder/opensuse.conf

View File

@@ -21,6 +21,7 @@ AM_YFLAGS = -d
EXTRA_DIST = \
$(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \
index_parser_tests.ml \
libguestfs.gpg \
opensuse.gpg \
test-console.sh \
@@ -240,13 +241,38 @@ yajl_tests_BOBJECTS = \
yajl_tests.cmo
yajl_tests_XOBJECTS = $(yajl_tests_BOBJECTS:.cmo=.cmx)
index_parser_tests_SOURCES = \
index-scan.c \
index-struct.c \
index-parser-c.c \
index-parse.c \
yajl-c.c
index_parser_tests_CPPFLAGS = $(virt_builder_CPPFLAGS)
index_parser_tests_BOBJECTS = \
yajl.cmo \
utils.cmo \
cache.cmo \
downloader.cmo \
sigchecker.cmo \
index.cmo \
ini_reader.cmo \
index_parser.cmo \
index_parser_tests.cmo
index_parser_tests_XOBJECTS = $(index_parser_tests_BOBJECTS:.cmo=.cmx)
# Can't call the following as <test>_OBJECTS because automake gets confused.
if HAVE_OCAMLOPT
yajl_tests_THEOBJECTS = $(yajl_tests_XOBJECTS)
yajl_tests.cmx: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS)
index_parser_tests_THEOBJECTS = $(index_parser_tests_XOBJECTS)
index_parser_tests.cmx: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS)
else
yajl_tests_THEOBJECTS = $(yajl_tests_BOBJECTS)
yajl_tests.cmo: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS)
index_parser_tests_THEOBJECTS = $(index_parser_tests_BOBJECTS)
index_parser_tests.cmo: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS)
endif
yajl_tests_DEPENDENCIES = \
@@ -262,6 +288,15 @@ yajl_tests_LINK = \
$(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLPACKAGES_TESTS) $(OCAMLLINKFLAGS) \
$(yajl_tests_THEOBJECTS) -o $@
index_parser_tests_DEPENDENCIES = \
$(index_parser_tests_THEOBJECTS) \
../common/mltools/mltools.$(MLARCHIVE) \
$(top_srcdir)/ocaml-link.sh
index_parser_tests_LINK = \
$(top_srcdir)/ocaml-link.sh -cclib '$(OCAMLCLIBS)' -- \
$(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLPACKAGES_TESTS) $(OCAMLLINKFLAGS) \
$(index_parser_tests_THEOBJECTS) -o $@
TESTS = \
test-docs.sh \
test-virt-builder-list.sh \
@@ -275,8 +310,8 @@ if ENABLE_APPLIANCE
TESTS += test-virt-builder.sh
endif ENABLE_APPLIANCE
if HAVE_OCAML_PKG_OUNIT
check_PROGRAMS += yajl_tests
TESTS += yajl_tests
check_PROGRAMS += yajl_tests index_parser_tests
TESTS += yajl_tests index_parser_tests
endif
check-valgrind:

View File

@@ -39,3 +39,6 @@ and entry = {
}
val print_entry : out_channel -> (string * entry) -> unit
(** Debugging helper function dumping an index entry to a stream.
To write entries for non-debugging purpose, use the
[Index_parser.write_entry] function. *)

View File

@@ -226,3 +226,46 @@ let get_index ~downloader ~sigchecker { Sources.uri; proxy } =
in
get_index ()
let write_entry chan (name, { Index.printable_name; file_uri; arch; osinfo;
signature_uri; checksums; revision; format; size;
compressed_size; expand; lvexpand; notes;
aliases; hidden}) =
let fp fs = fprintf chan fs in
fp "[%s]\n" name;
Option.may (fp "name=%s\n") printable_name;
Option.may (fp "osinfo=%s\n") osinfo;
fp "file=%s\n" file_uri;
fp "arch=%s\n" arch;
Option.may (fp "sig=%s\n") signature_uri;
(match checksums with
| None -> ()
| Some checksums ->
List.iter (
fun c ->
fp "checksum[%s]=%s\n"
(Checksums.string_of_csum_t c) (Checksums.string_of_csum c)
) checksums
);
fp "revision=%s\n" (string_of_revision revision);
Option.may (fp "format=%s\n") format;
fp "size=%Ld\n" size;
Option.may (fp "compressed_size=%Ld\n") compressed_size;
Option.may (fp "expand=%s\n") expand;
Option.may (fp "lvexpand=%s\n") lvexpand;
let format_notes notes =
String.concat "\n " (String.nsplit "\n" notes) in
List.iter (
fun (lang, notes) ->
match lang with
| "" -> fp "notes=%s\n" (format_notes notes)
| lang -> fp "notes[%s]=%s\n" lang (format_notes notes)
) notes;
(match aliases with
| None -> ()
| Some l -> fp "aliases=%s\n" (String.concat " " l)
);
if hidden then fp "hidden=true\n";
fp "\n"

View File

@@ -17,3 +17,7 @@
*)
val get_index : downloader:Downloader.t -> sigchecker:Sigchecker.t -> Sources.source -> Index.index
val write_entry : out_channel -> (string * Index.entry) -> unit
(** [write_entry chan entry] writes the index entry to the chan output
stream.*)

View File

@@ -0,0 +1,130 @@
(* builder
* Copyright (C) 2017 SUSE Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
(* This file tests the Index_parser module. *)
open Printf
open OUnit2
open Std_utils
open Unix_utils
open Tools_utils
let tmpdir =
let tmpdir = Mkdtemp.temp_dir "guestfs-tests." in
rmdir_on_exit tmpdir;
tmpdir
let dummy_sigchecker = Sigchecker.create ~gpg:"gpg"
~check_signature:false
~gpgkey:Utils.No_Key
~tmpdir
let dummy_downloader = Downloader.create ~curl:"do-not-use-curl"
~cache:None ~tmpdir
(* Utils. *)
let write_entries file entries =
let chan = open_out (tmpdir // file) in
List.iter (Index_parser.write_entry chan) entries;
close_out chan
let read_file file =
read_whole_file (tmpdir // "out")
let parse_file file =
let source = { Sources.name = "input";
uri = tmpdir // file;
gpgkey = Utils.No_Key;
proxy = Curl.SystemProxy;
format = Sources.FormatNative } in
let entries = Index_parser.get_index ~downloader:dummy_downloader
~sigchecker:dummy_sigchecker
source in
List.map (
fun (id, e) -> (id, { e with Index.file_uri = Filename.basename e.Index.file_uri })
) entries
let format_entries entries =
let format_entry entry =
write_entries "out" [entry];
read_file "out" in
List.map format_entry entries
let assert_equal_string = assert_equal ~printer:(fun x -> sprintf "\"%s\"" x)
let assert_equal_list formatter =
let printer = (
fun x -> "(" ^ (String.escaped (String.concat "," (formatter x))) ^ ")"
) in
assert_equal ~printer
let test_write_complete ctx =
let entry =
("test-id", { Index.printable_name = Some "test_name";
osinfo = Some "osinfo_data";
file_uri = "image_path";
arch = "test_arch";
signature_uri = None;
checksums = Some [Checksums.SHA512 "512checksum"];
revision = Utils.Rev_int 42;
format = Some "qcow2";
size = Int64.of_int 123456;
compressed_size = Some (Int64.of_int 12345);
expand = Some "/dev/sda1";
lvexpand = Some "/some/lv";
notes = [ ("", "Notes split\non several lines\n\n with starting space ") ];
hidden = false;
aliases = Some ["alias1"; "alias2"];
sigchecker = dummy_sigchecker;
proxy = Curl.SystemProxy }) in
write_entries "out" [entry];
let actual = read_file "out" in
let expected = "[test-id]
name=test_name
osinfo=osinfo_data
file=image_path
arch=test_arch
checksum[sha512]=512checksum
revision=42
format=qcow2
size=123456
compressed_size=12345
expand=/dev/sda1
lvexpand=/some/lv
notes=Notes split
on several lines
with starting space
aliases=alias1 alias2
" in
assert_equal_string expected actual;
let parsed_entries = parse_file "out" in
assert_equal_list format_entries [entry] parsed_entries
let suite =
"builder Index_parser" >:::
[
"write.complete" >:: test_write_complete;
]
let () =
run_test_tt_main suite