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. --- .gitignore | 1 + builder/Makefile.am | 36 +++++++++++- builder/index.mli | 3 + builder/index_parser.ml | 54 ++++++++++++++++++ builder/index_parser.mli | 4 ++ builder/index_parser_tests.ml | 129 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 builder/index_parser_tests.ml
diff --git a/.gitignore b/.gitignore index 69e1ae160..b9e00ee04 100644 --- a/.gitignore +++ b/.gitignore @@ -106,6 +106,7 @@ Makefile.in /builder/virt-index-validate /builder/virt-index-validate.1 /builder/*.xz +/builder/index_parser_tests /builder/yajl_tests /cat/stamp-virt-*.pod /cat/virt-cat diff --git a/builder/Makefile.am b/builder/Makefile.am index 218f64b4c..bf4ccb7d7 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -217,13 +217,36 @@ 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 +index_parser_tests_CPPFLAGS = $(virt_builder_CPPFLAGS) +index_parser_tests_BOBJECTS = \ + 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 = \ @@ -236,6 +259,15 @@ yajl_tests_LINK = \ $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLPACKAGES_TESTS) $(OCAMLLINKFLAGS) \ $(yajl_tests_THEOBJECTS) -o $@ +index_parser_tests_DEPENDENCIES = \ + $(index_parser_tests_THEOBJECTS) \ + ../mllib/mllib.$(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 \ @@ -249,8 +281,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: diff --git a/builder/index.mli b/builder/index.mli index ff5ec4a35..6202d636e 100644 --- a/builder/index.mli +++ b/builder/index.mli @@ -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. *) diff --git a/builder/index_parser.ml b/builder/index_parser.ml index c70909e44..c56c4b8f8 100644 --- a/builder/index_parser.ml +++ b/builder/index_parser.ml @@ -236,3 +236,57 @@ let get_index ~downloader ~sigchecker ~template in get_index () + +let write_entry chan (name, { Index.printable_name = printable_name; + file_uri = file_uri; + arch = arch; + osinfo = osinfo; + signature_uri = signature_uri; + checksums = checksums; + revision = revision; + format = format; + size = size; + compressed_size = compressed_size; + expand = expand; + lvexpand = lvexpand; + notes = notes; + aliases = aliases; + hidden = hidden }) = + let fp fs = fprintf chan fs in + fp "[%s]\n" name; + may (fp "name=%s\n") printable_name; + may (fp "osinfo=%s\n") osinfo; + fp "file=%s\n" file_uri; + fp "arch=%s\n" arch; + 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); + may (fp "format=%s\n") format; + fp "size=%Ld\n" size; + may (fp "compressed_size=%Ld\n") compressed_size; + may (fp "expand=%s\n") expand; + 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" diff --git a/builder/index_parser.mli b/builder/index_parser.mli index aa5f84730..ae757ad6f 100644 --- a/builder/index_parser.mli +++ b/builder/index_parser.mli @@ -19,3 +19,7 @@ val get_index : downloader:Downloader.t -> sigchecker:Sigchecker.t -> template:bool -> Sources.source -> Index.index (** [get_index download sigchecker source] will parse the source index file into an index entry list. *) + +val write_entry : out_channel -> (string * Index.entry) -> unit +(** [write_entry chan entry] writes the index entry to the chan output + stream.*) diff --git a/builder/index_parser_tests.ml b/builder/index_parser_tests.ml new file mode 100644 index 000000000..c4352d752 --- /dev/null +++ b/builder/index_parser_tests.ml @@ -0,0 +1,129 @@ +(* 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 OUnit2 +open Printf +open Unix_utils +open Common_utils + +let tmpdir = Mkdtemp.temp_dir "guestfs-tests." "";; +rmdir_on_exit 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 ( + fun (entry) -> + Index_parser.write_entry chan entry; + ) 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 + ~template:false + 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 -- 2.12.2 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs