diff --git a/Makefile.am b/Makefile.am index 6fe89aa5..33750a50 100644 --- a/Makefile.am +++ b/Makefile.am @@ -181,6 +181,7 @@ BATS = \ test/functional/bundlelist/list-has-dep-nested-not-installed.bats \ test/functional/bundlelist/list-has-dep-nested-server.bats \ test/functional/bundlelist/list-installed.bats \ + test/functional/bundlelist/list-json.bats \ test/functional/bundlelist/list-no-deps.bats \ test/functional/bundlelist/list-no-disk-space.bats \ test/functional/bundlelist/list-none-has-deps.bats \ @@ -189,11 +190,13 @@ BATS = \ test/functional/bundleremove/remove-client-certificate.bats \ test/functional/bundleremove/remove-include.bats \ test/functional/bundleremove/remove-include-nested.bats \ + test/functional/bundleremove/remove-json.bats \ test/functional/bundleremove/remove-no-disk-space.bats \ test/functional/bundleremove/remove-os-core.bats \ test/functional/bundleremove/remove-parse-args.bats \ test/functional/bundleremove/remove-with-dependency.bats \ test/functional/checkupdate/chk-update-client-certificate.bats \ + test/functional/checkupdate/chk-update-json.bats \ test/functional/checkupdate/chk-update-new-version.bats \ test/functional/checkupdate/chk-update-no-server-content.bats \ test/functional/checkupdate/chk-update-no-target-content.bats \ @@ -202,10 +205,12 @@ BATS = \ test/functional/hashdump/hashdump-file-hash.bats \ test/functional/mirror/mirror-createdir.bats \ test/functional/mirror/mirror-createdir-negative.bats \ + test/functional/mirror/mirror-json.bats \ test/functional/search/search-content-check-negative.bats \ test/functional/search/search-content-check-positive.bats \ test/functional/search/search-client-certificate.bats \ test/functional/search/search-experimental.bats \ + test/functional/search/search-json.bats \ test/functional/search/search-no-disk-space.bats \ test/functional/search/search-sort.bats \ test/functional/update/update-boot-file.bats \ @@ -217,6 +222,7 @@ BATS = \ test/functional/update/update-include.bats \ test/functional/update/update-include-old-bundle.bats \ test/functional/update/update-include-old-bundle-with-tracked-file.bats \ + test/functional/update/update-json.bats \ test/functional/update/update-manifest-delta.bats \ test/functional/update/update-minversion.bats \ test/functional/update/update-missing-os-core.bats \ @@ -272,6 +278,7 @@ BATS = \ test/functional/verify/verify-install-multiple.bats \ test/functional/verify/verify-install-no-fullfile-fallbacks.bats \ test/functional/verify/verify-install-no-zero-packs.bats \ + test/functional/verify/verify-json.bats \ test/functional/verify/verify-latest-missing.bats \ test/functional/verify/verify-missing-file.bats \ test/functional/verify/verify-no-disk-space.bats \ diff --git a/src/bundle.c b/src/bundle.c index c0fade4b..505f6d66 100644 --- a/src/bundle.c +++ b/src/bundle.c @@ -762,7 +762,7 @@ static enum swupd_code install_bundles(struct list *bundles, struct list **subs, /* step 1: check bundle args are valid if so populate subs struct */ timelist_timer_start(global_times, "Add bundles and recurse"); - progress_set_step(1, "download_bundle_manifests"); + progress_set_step(1, "load_manifests"); ret = add_subscriptions(bundles, subs, mom, false, 0); /* print a message if any of the requested bundles is already installed */ @@ -891,7 +891,7 @@ static enum swupd_code install_bundles(struct list *bundles, struct list **subs, /* step 6: Install all bundle(s) files into the fs */ timelist_timer_start(global_times, "Installing bundle(s) files onto filesystem"); info("Installing bundle(s) files...\n"); - progress_set_step(6, "installing_files"); + progress_set_step(6, "install_files"); /* Do an initial check to * 1. make sure the file actually downloaded, if not continue on to the diff --git a/src/check_update.c b/src/check_update.c index 3f774055..781c8200 100644 --- a/src/check_update.c +++ b/src/check_update.c @@ -103,14 +103,19 @@ static bool parse_options(int argc, char **argv) enum swupd_code check_update_main(int argc, char **argv) { int ret; + const int steps_in_checkupdate = 1; + + /* there is no need to report in progress for check-update at this time */ if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } + progress_init_steps("check-update", steps_in_checkupdate); ret = check_update(); free_globals(); + progress_finish_steps("check-update", ret); return ret; } diff --git a/src/clean.c b/src/clean.c index ecb6741e..a283147d 100644 --- a/src/clean.c +++ b/src/clean.c @@ -379,16 +379,19 @@ static void clean_deinit(void) enum swupd_code clean_main(int argc, char **argv) { + int ret = SWUPD_OK; + const int steps_in_clean = 1; + if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } + progress_init_steps("clean", steps_in_clean); - int ret = SWUPD_OK; ret = clean_init(); if (ret != 0) { error("Failed swupd initialization, exiting now.\n"); - return ret; + goto exit; } if (!options.all) { @@ -418,6 +421,9 @@ enum swupd_code clean_main(int argc, char **argv) end: clean_deinit(); + +exit: + progress_finish_steps("clean", ret); return ret; } diff --git a/src/clr_bundle_add.c b/src/clr_bundle_add.c index 55497c8e..9cf4d064 100644 --- a/src/clr_bundle_add.c +++ b/src/clr_bundle_add.c @@ -48,14 +48,12 @@ static void print_help(void) print("Options:\n"); print(" --skip-diskspace-check Do not check free disk space before adding bundle\n"); - print(" -j, --json-output Print all output as a JSON stream\n"); print("\n"); } static const struct option prog_opts[] = { { "list", no_argument, 0, 'l' }, { "skip-diskspace-check", no_argument, &skip_diskspace_check, 1 }, - { "json-output", no_argument, 0, 'j' }, }; static bool parse_opt(int opt, UNUSED_PARAM char *optarg) @@ -65,9 +63,6 @@ static bool parse_opt(int opt, UNUSED_PARAM char *optarg) error("[-l, --list] option is deprecated, use\n" "bundle-list [-a|--all] sub-command instead.\n\n"); exit(EXIT_FAILURE); - case 'j': - set_json_format(); - return true; default: return false; } @@ -104,13 +99,26 @@ enum swupd_code bundle_add_main(int argc, char **argv) int ret; const int steps_in_bundleadd = 7; + /* + * Steps for bundle-add: + * + * 1) load_manifests + * 2) consolidate_files + * 3) check_disk_space_availability + * 4) download_packs + * 5) download_fullfiles + * 6) install_files + * 7) progress_set_step + */ + if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } - progress_init_steps("bundle-add", steps_in_bundleadd); + ret = install_bundles_frontend(bundles); + progress_finish_steps("bundle-add", ret); return ret; } diff --git a/src/clr_bundle_ls.c b/src/clr_bundle_ls.c index 8f0be564..f13a0f7e 100644 --- a/src/clr_bundle_ls.c +++ b/src/clr_bundle_ls.c @@ -114,11 +114,15 @@ static bool parse_options(int argc, char **argv) enum swupd_code bundle_list_main(int argc, char **argv) { int ret; + const int steps_in_bundlelist = 1; + + /* there is no need to report in progress for bundle-list at this time */ if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } + progress_init_steps("bundle-list", steps_in_bundlelist); ret = swupd_init(); /* if swupd fails to initialize, the only list command we can still attempt is @@ -126,7 +130,7 @@ enum swupd_code bundle_list_main(int argc, char **argv) * bundles are experimental) */ if (ret != 0 && !cmdline_local) { error("Failed updater initialization. Exiting now\n"); - return ret; + goto finish; } if (cmdline_local) { @@ -141,5 +145,7 @@ enum swupd_code bundle_list_main(int argc, char **argv) swupd_deinit(); +finish: + progress_finish_steps("bundle-list", ret); return ret; } diff --git a/src/clr_bundle_rm.c b/src/clr_bundle_rm.c index b78ab7f7..af4ba8d5 100644 --- a/src/clr_bundle_rm.c +++ b/src/clr_bundle_rm.c @@ -78,10 +78,19 @@ static bool parse_options(int argc, char **argv) enum swupd_code bundle_remove_main(int argc, char **argv) { + int ret; + const int steps_in_bundleremove = 1; + + /* there is no need to report in progress for bundle-remove at this time */ + if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } + progress_init_steps("bundle-remove", steps_in_bundleremove); - return remove_bundles(bundles); + ret = remove_bundles(bundles); + + progress_finish_steps("bundle-remove", ret); + return ret; } diff --git a/src/globals.c b/src/globals.c index 2c2d2d88..6088fccd 100644 --- a/src/globals.c +++ b/src/globals.c @@ -575,6 +575,7 @@ static const struct option global_opts[] = { { "", required_argument, 0, 'D' }, { "max-retries", required_argument, 0, 'r' }, { "retry-delay", required_argument, 0, 'd' }, + { "json-output", no_argument, 0, 'j' }, { 0, 0, 0, 0 } }; @@ -660,6 +661,9 @@ static bool global_parse_opt(int opt, char *optarg) return false; } return true; + case 'j': + set_json_format(); + return true; default: return false; } @@ -721,6 +725,7 @@ void global_print_help(void) print(" -W, --max-parallel-downloads=[n] Set the maximum number of parallel downloads\n"); print(" -r, --max-retries Maximum number of retries for download failures\n"); print(" -d, --retry-delay Initial delay between download retries, this will be doubled for each retry\n"); + print(" -j, --json-output Print all output as a JSON stream\n"); print(" --quiet Quiet output. Print only important information and errors\n"); print(" --debug Print extra information to help debugging problems\n"); print("\n"); diff --git a/src/info.c b/src/info.c index efb71858..4b883aff 100644 --- a/src/info.c +++ b/src/info.c @@ -64,17 +64,27 @@ static bool parse_options(int argc, char **argv) enum swupd_code info_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) { + int ret = SWUPD_OK; + const int steps_in_info = 1; + + /* there is no need to report in progress for init at this time */ + if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } + progress_init_steps("info", steps_in_info); if (!init_globals()) { - return SWUPD_INIT_GLOBALS_FAILED; + ret = SWUPD_INIT_GLOBALS_FAILED; + goto finish; } print_update_conf_info(); free_globals(); - return 0; + +finish: + progress_finish_steps("info", ret); + return ret; } diff --git a/src/lib/progress.c b/src/lib/progress.c index 35b3d726..f6a514a0 100644 --- a/src/lib/progress.c +++ b/src/lib/progress.c @@ -69,14 +69,14 @@ void progress_set_step(unsigned int current_step, char *desc) step.description = desc; } -struct step *progress_get_step(void) +void progress_set_next_step(char *desc) { - struct step *current_step = NULL; + progress_set_step((step.current) + 1, desc); +} - if (step.total != 0 && step.description != NULL) { - *current_step = step; - } - return current_step; +struct step progress_get_step(void) +{ + return step; } void progress_complete_step(void) diff --git a/src/lib/progress.h b/src/lib/progress.h index 46fbf3ed..2009c392 100644 --- a/src/lib/progress.h +++ b/src/lib/progress.h @@ -40,10 +40,16 @@ void progress_finish_steps(char *, int status); */ void progress_set_step(unsigned int, char *); +/* + * Increases the current step by one and assigns the provided description to it. + * Useful when you don't know the number of the current step. + */ +void progress_set_next_step(char *); + /* * Gets the current step defined. */ -struct step *progress_get_step(void); +struct step progress_get_step(void); /* * Marks the current step as completed (progress = 100%). diff --git a/src/mirror.c b/src/mirror.c index 6f325e46..677fa8b8 100644 --- a/src/mirror.c +++ b/src/mirror.c @@ -259,10 +259,15 @@ out: enum swupd_code mirror_main(int argc, char **argv) { int ret = SWUPD_OK; + const int steps_in_mirror = 1; + + /* there is no need to report in progress for mirror at this time */ + if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } + progress_init_steps("mirror", steps_in_mirror); if (set != NULL) { ret = set_mirror_url(set); @@ -286,11 +291,15 @@ enum swupd_code mirror_main(int argc, char **argv) /* init globals here after the new URL is configured */ if (!init_globals()) { - return SWUPD_INIT_GLOBALS_FAILED; + ret = SWUPD_INIT_GLOBALS_FAILED; + goto finish; } /* print new configuration */ print_update_conf_info(); free_globals(); + +finish: + progress_finish_steps("mirror", ret); return ret; } diff --git a/src/search.c b/src/search.c index 1fe03123..bc992850 100644 --- a/src/search.c +++ b/src/search.c @@ -579,28 +579,50 @@ static bool parse_options(int argc, char **argv) return true; } + enum swupd_code search_main(int argc, char **argv) { + int ret = SWUPD_OK, search_ret = SWUPD_OK; struct manifest *mom = NULL; int current_version; + int steps_in_search = 3; + + /* there is no need to report in progress for search at this time */ + /* + * Steps for search: + * + * 1) get_versions + * 2) load_manifests + * (Finishes here on --init) + * 3) search_term + */ if (!parse_options(argc, argv)) { return SWUPD_INVALID_OPTION; } + if (init) { + /* if user selected the --init option the number of steps in the + * search process are just 2 */ + steps_in_search = 2; + } + progress_init_steps("search", steps_in_search); ret = swupd_init(); if (ret != 0) { error("Failed swupd initialization, exiting now.\n"); - return ret; + goto exit; } + progress_set_step(1, "get_versions"); current_version = get_current_version(path_prefix); if (current_version < 0) { error("Unable to determine current OS version\n"); return SWUPD_CURRENT_VERSION_UNKNOWN; } + progress_complete_step(); + progress_set_step(2, "load_manifests"); // will be closed within download_all_manifests mom = load_mom(current_version, false, false, NULL); if (!mom) { error("Cannot load official manifest MoM for version %i\n", current_version); @@ -619,9 +641,10 @@ enum swupd_code search_main(int argc, char **argv) goto clean_exit; } + progress_set_step(3, "search_term"); info("Searching for '%s'\n", search_string); - search_ret = do_search(mom, search_string); + progress_complete_step(); // Keep any ret error code if search is successful if (ret == SWUPD_OK && search_ret == 0) { @@ -635,5 +658,8 @@ clean_exit: list_free_list_and_data(manifest_header_cache, free_manifest_data); swupd_deinit(); + +exit: + progress_finish_steps("search", ret); return ret; } diff --git a/src/update.c b/src/update.c index ee023fa3..0406e80a 100644 --- a/src/update.c +++ b/src/update.c @@ -76,7 +76,10 @@ static int update_loop(struct list *updates, struct manifest *server_manifest) int ret; struct file *file; struct list *iter; + struct step step; + step = progress_get_step(); + progress_set_step(step.current, "download_fullfiles"); ret = download_fullfiles(updates, &nonpack); if (ret) { error("Could not download all files, aborting update\n"); @@ -124,6 +127,7 @@ static int update_loop(struct list *updates, struct manifest *server_manifest) sync(); /* rename to apply update */ + progress_set_step((step.current) + 1, "update_files"); info("Applying update\n"); ret = rename_all_files_to_final(updates); if (ret != 0) { @@ -250,8 +254,9 @@ static enum swupd_code main_update() /* start the timer used to report the total time to telemetry */ clock_gettime(CLOCK_MONOTONIC_RAW, &ts_start); - /* Preparation steps */ + /* Step 1: Preparation steps */ timelist_timer_start(global_times, "Prepare for update"); + progress_set_step(1, "prepare_for_update"); info("Update started.\n"); mix_exists = check_mix_exists(); @@ -259,10 +264,12 @@ static enum swupd_code main_update() read_subscriptions(¤t_subs); handle_mirror_if_stale(); + progress_complete_step(); timelist_timer_stop(global_times); // closing: Prepare for update - /* Step 1: get versions */ + /* Step 2: get versions */ timelist_timer_start(global_times, "Get versions"); + progress_set_step(2, "get_versions"); version_check: ret = check_versions(¤t_version, &server_version, requested_version, path_prefix); if (ret != SWUPD_OK) { @@ -326,19 +333,23 @@ version_check: } info("Preparing to update from %i to %i\n", current_version, server_version); + progress_complete_step(); timelist_timer_stop(global_times); // closing: Get versions - /* Step 2: housekeeping */ + /* Step 3: housekeeping */ timelist_timer_start(global_times, "Clean up download directory"); + progress_set_step(3, "cleanup_download_dir"); if (rm_staging_dir_contents("download")) { error("There was a problem cleaning download directory\n"); ret = SWUPD_COULDNT_REMOVE_FILE; goto clean_curl; } + progress_complete_step(); timelist_timer_stop(global_times); // closing: Clean up download directory - /* Step 3: setup manifests */ + /* Step 4: setup manifests */ timelist_timer_start(global_times, "Load manifests"); + progress_set_step(4, "load_manifests"); timelist_timer_start(global_times, "Load MoM manifests"); int manifest_err; @@ -414,34 +425,47 @@ version_check: /* prepare for an update process based on comparing two in memory manifests */ link_manifests(current_manifest, server_manifest); timelist_timer_stop(global_times); // closing: Recurse and consolidate bundle manifests + progress_complete_step(); timelist_timer_stop(global_times); // closing: Load manifests - /* Step 4: check disk state before attempting update */ + /* Step 5: check disk state before attempting update */ timelist_timer_start(global_times, "Run pre-update scripts"); + progress_set_step(5, "run_preupdate_scripts"); run_preupdate_scripts(server_manifest); + progress_complete_step(); timelist_timer_stop(global_times); // closing: Run pre-update scripts - /* Step 5: get the packs and untar */ + /* Step 6: get the packs and untar */ timelist_timer_start(global_times, "Download packs"); + progress_set_step(6, "download_packs"); download_subscribed_packs(latest_subs, server_manifest, false); timelist_timer_stop(global_times); // closing: Download packs + /* Step 7: apply deltas */ timelist_timer_start(global_times, "Apply deltas"); + progress_set_step(7, "apply_deltas"); apply_deltas(current_manifest); + progress_complete_step(); timelist_timer_stop(global_times); // closing: Apply deltas - /* Step 6: some more housekeeping */ + /* Step 8: some more housekeeping */ /* TODO: consider trying to do less sorting of manifests */ timelist_timer_start(global_times, "Create update list"); + progress_set_step(8, "create_update_list"); updates = create_update_list(server_manifest); print_statistics(current_version, server_version); + progress_complete_step(); timelist_timer_stop(global_times); // closing: Create update list - /* Step 7: apply the update */ + /* Steps 9 & 10: downloading and applying updates */ /* need update list in filename order to insure directories are * created before their contents */ timelist_timer_start(global_times, "Update loop"); + /* two steps are part of this stage, so only pass the + * initial step number and we will update the description + * from within the update_loop function */ + progress_set_step(9, ""); updates = list_sort(updates, file_sort_filename); ret = update_loop(updates, server_manifest); @@ -459,8 +483,9 @@ version_check: delete_motd(); timelist_timer_stop(global_times); // closing: Update loop - /* Run any scripts that are needed to complete update */ + /* Step 11: Run any scripts that are needed to complete update */ timelist_timer_start(global_times, "Run post-update scripts"); + progress_set_step(11, "run_postupdate_scripts"); /* Determine if another update is needed so the scripts block */ int new_current_version = get_current_version(path_prefix); @@ -468,6 +493,7 @@ version_check: re_update = true; } run_scripts(re_update); + progress_complete_step(); timelist_timer_stop(global_times); // closing: Run post-update scripts /* Create the state file that will tell swupd it's on a mix on future runs */ @@ -685,16 +711,36 @@ static enum swupd_code print_versions() enum swupd_code update_main(int argc, char **argv) { int ret = SWUPD_OK; + const int steps_in_update = 11; + + /* + * Steps for update: + * + * 1) prepare_for_update + * 2) get_versions + * 3) cleanup_download_dir + * 4) load_manifests + * 5) run_preupdate_scripts + * 6) download_packs + * 7) apply_deltas + * 8) create_update_list + * 9) download_fullfiles + * 10) update_files + * 11) run_postupdate_scripts + */ if (!parse_options(argc, argv)) { print_help(); return SWUPD_INVALID_OPTION; } + progress_init_steps("update", steps_in_update); if (cmd_line_status) { ret = print_versions(); } else { ret = main_update(); } + + progress_finish_steps("update", ret); return ret; } diff --git a/src/verify.c b/src/verify.c index 95c1c441..5d3afe9c 100644 --- a/src/verify.c +++ b/src/verify.c @@ -189,13 +189,16 @@ static int get_required_files(struct manifest *official_manifest, struct list *s int ret; if (cmdline_option_install) { + progress_set_next_step("download_packs"); get_all_files(official_manifest, subs); } + progress_set_next_step("check_files_hash"); if (check_files_hash(official_manifest->files)) { return 0; } + progress_set_next_step("download_fullfiles"); ret = download_fullfiles(official_manifest->files, NULL); if (ret) { error("Unable to download necessary files for this OS release\n"); @@ -609,12 +612,38 @@ enum swupd_code verify_main(int argc, char **argv) struct manifest *official_manifest = NULL; int ret; struct list *subs = NULL; + int steps_in_verify = 6; + + /* + * Steps for verify: + * + * 1) get_versions + * 2) cleanup_download_dir + * 3) load_manifests + * 4) consolidate_files + * 5) download_packs (applies only with --install) + * 6) check_files_hash (applies only with --install or --fix) + * 7) download_fullfiles (applies only with --install or --fix) + * 8) add_missing_files + * (Finishes here on --quick or --install) + * 9) fix_files + */ if (!parse_options(argc, argv)) { ret = SWUPD_INVALID_OPTION; print_help(); goto clean_args_and_exit; } + /* calculate the number of steps in the process so we can report progress */ + if (cmdline_option_install) { + steps_in_verify += 3; + } else if (cmdline_option_fix) { + steps_in_verify += 2; + } + if (cmdline_option_quick) { + steps_in_verify -= 1; + } + progress_init_steps("verify", steps_in_verify); /* parse command line options */ assert(argc >= 0); @@ -627,6 +656,8 @@ enum swupd_code verify_main(int argc, char **argv) } /* Get the current system version and the version to verify against */ + timelist_timer_start(global_times, "Get versions"); + progress_set_step(1, "get_versions"); int sys_version = get_current_version(path_prefix); if (!version) { if (sys_version < 0) { @@ -646,6 +677,8 @@ enum swupd_code verify_main(int argc, char **argv) goto clean_and_exit; } } + progress_complete_step(); + timelist_timer_stop(global_times); // closing: Get versions info("Verifying version %i\n", version); @@ -662,14 +695,18 @@ enum swupd_code verify_main(int argc, char **argv) * FIXME: We need a command line option to override this in case the * certificate is hosed and the admin knows it and wants to recover. */ - + timelist_timer_start(global_times, "Clean up download directory"); + progress_set_step(2, "cleanup_download_dir"); ret = rm_staging_dir_contents("download"); if (ret != 0) { ret = SWUPD_COULDNT_REMOVE_FILE; warn("Failed to remove prior downloads, carrying on anyway\n"); } + progress_complete_step(); + timelist_timer_stop(global_times); // closing: Clean up download directory - timelist_timer_start(global_times, "Load and recurse Manifests"); + timelist_timer_start(global_times, "Load manifests"); + progress_set_step(3, "load_manifests"); /* Gather current manifests */ /* When the version we are verifying against does not match our system version @@ -764,11 +801,17 @@ enum swupd_code verify_main(int argc, char **argv) ret = SWUPD_RECURSE_MANIFEST; goto clean_and_exit; } - timelist_timer_stop(global_times); + progress_complete_step(); + timelist_timer_stop(global_times); // closing: Load manifests + timelist_timer_start(global_times, "Consolidate files from bundles"); + progress_set_step(4, "consolidate_files"); official_manifest->files = files_from_bundles(official_manifest->submanifests); official_manifest->files = consolidate_files(official_manifest->files); + progress_complete_step(); timelist_timer_stop(global_times); + + /* steps 5, 6 & 7 are executed within the get_required_files function */ timelist_timer_start(global_times, "Get required files"); /* get the initial number of files to be inspected */ @@ -809,6 +852,7 @@ enum swupd_code verify_main(int argc, char **argv) bool repair = true; timelist_timer_start(global_times, "Add missing files"); + progress_set_next_step("add_missing_files"); info("Adding any missing files\n"); add_missing_files(official_manifest, repair); timelist_timer_stop(global_times); @@ -823,6 +867,7 @@ enum swupd_code verify_main(int argc, char **argv) bool repair = true; timelist_timer_start(global_times, "Fixing modified files"); + progress_set_next_step("fix_files"); info("Fixing modified files\n"); deal_with_hash_mismatches(official_manifest, repair); @@ -846,10 +891,12 @@ enum swupd_code verify_main(int argc, char **argv) } else { bool repair = false; + progress_set_next_step("add_missing_files"); info("Verifying files\n"); add_missing_files(official_manifest, repair); /* quick only checks for missing files, so it is done here */ if (!cmdline_option_quick) { + progress_set_next_step("fix_files"); deal_with_hash_mismatches(official_manifest, repair); remove_orphaned_files(official_manifest, repair); } @@ -985,5 +1032,6 @@ clean_args_and_exit: picky_whitelist = NULL; } + progress_finish_steps("verify", ret); return ret; } diff --git a/swupd.bash b/swupd.bash index 6d87803c..39ea24c4 100644 --- a/swupd.bash +++ b/swupd.bash @@ -36,37 +36,37 @@ _swupd() opts="--help --url --contenturl --versionurl --port --path --format --force --nosigcheck --ignore-time --statedir --certpath --time --no-scripts --no-boot-update --max-parallel-downloads --json-output --debug --quiet" break;; ("bundle-remove") - opts="--help --path --url --contenturl --versionurl --port --format --force --nosigcheck --ignore-time --statedir --certpath --debug --quiet " + opts="--help --path --url --contenturl --versionurl --port --format --force --nosigcheck --ignore-time --statedir --certpath --debug --quiet --json-output " break;; ("bundle-list") - opts="--help --all --url --contenturl --versionurl --path --format --nosigcheck --ignore-time --statedir --certpath --deps --has-dep --debug --quiet " + opts="--help --all --url --contenturl --versionurl --path --format --nosigcheck --ignore-time --statedir --certpath --deps --has-dep --debug --quiet --json-output " break;; ("hashdump") opts="--help --no-xattrs --path --debug --quiet " break;; ("update") - opts="--help --download --url --port --contenturl --versionurl --status --format --path --force --nosigcheck --ignore-time --statedir --certpath --time --no-scripts --no-boot-update --migrate --allow-mix-collisions --max-parallel-downloads --keepcache --debug --quiet " + opts="--help --download --url --port --contenturl --versionurl --status --format --path --force --nosigcheck --ignore-time --statedir --certpath --time --no-scripts --no-boot-update --migrate --allow-mix-collisions --max-parallel-downloads --keepcache --debug --quiet --json-output " break;; ("verify") - opts="--help --manifest --path --url --port --contenturl --versionurl --fix --picky --picky-tree --picky-whitelist --install --format --quick --force --nosigcheck --ignore-time --statedir --certpath --time --no-scripts --no-boot-update --max-parallel-downloads --debug --quiet " + opts="--help --manifest --path --url --port --contenturl --versionurl --fix --picky --picky-tree --picky-whitelist --install --format --quick --force --nosigcheck --ignore-time --statedir --certpath --time --no-scripts --no-boot-update --max-parallel-downloads --debug --quiet --json-output " break;; ("check-update") - opts="--help --url --versionurl --port --format --force --nosigcheck --path --statedir --debug --quiet " + opts="--help --url --versionurl --port --format --force --nosigcheck --path --statedir --debug --quiet --json-output " break;; ("search") opts="--help" break;; ("search-file") - opts="--help --library --binary --top --csv --init --ignore-time --url --contenturl --versionurl --port --path --format --statedir --certpath --regexp --debug --quiet " + opts="--help --library --binary --top --csv --init --ignore-time --url --contenturl --versionurl --port --path --format --statedir --certpath --regexp --debug --quiet --json-output " break;; ("info") - opts="--debug --quiet " + opts="--debug --quiet --json-output " break;; ("clean") - opts="--all --dry-run --statedir --help --debug --quiet " + opts="--all --dry-run --statedir --help --debug --quiet --json-output " break;; ("mirror") - opts="--help --set --unset --path --debug --quiet " + opts="--help --set --unset --path --debug --quiet --json-output " break;; esac done diff --git a/test/functional/bundleadd/add-json.bats b/test/functional/bundleadd/add-json.bats index ccd3d9a1..53e116aa 100755 --- a/test/functional/bundleadd/add-json.bats +++ b/test/functional/bundleadd/add-json.bats @@ -24,60 +24,61 @@ test_setup() { assert_status_is 0 expected_output=$(cat <<-EOM - [ - { "type" : "start", "section" : "bundle-add" }, - { "type" : "progress", "currentStep" : 1, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "download_bundle_manifests" }, - { "type" : "progress", "currentStep" : 2, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "consolidate_files" }, - { "type" : "progress", "currentStep" : 3, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "check_disk_space_availability" }, - { "type" : "info", "msg" : "Downloading packs... " }, - { "type" : "progress", "currentStep" : 4, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "download_packs" }, - { "type" : "info", "msg" : " Extracting test-bundle pack for version 10 " }, - { "type" : "info", "msg" : "Starting download of remaining update content. This may take a while... " }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 8, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 16, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 25, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 33, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 41, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 50, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 58, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 66, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 75, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 83, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 91, "stepDescription" : "download_fullfiles" }, - { "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "download_fullfiles" }, - { "type" : "info", "msg" : "Finishing download of update content... " }, - { "type" : "info", "msg" : "Installing bundle(s) files... " }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 4, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 8, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 12, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 16, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 20, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 25, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 29, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 33, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 37, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 41, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 45, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 50, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 54, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 58, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 62, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 66, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 70, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 75, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 79, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 83, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 87, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 91, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 95, "stepDescription" : "installing_files" }, - { "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "installing_files" }, - { "type" : "info", "msg" : "Calling post-update helper scripts. " }, - { "type" : "progress", "currentStep" : 7, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "run_scripts" }, - { "type" : "info", "msg" : "Successfully installed 1 bundle " }, - { "type" : "end", "section" : "bundle-add", "status" : 0 } - ] + \[ + \{ "type" : "start", "section" : "bundle-add" \\}, + \{ "type" : "progress", "currentStep" : 1, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "load_manifests" \\}, + \{ "type" : "progress", "currentStep" : 2, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "consolidate_files" \\}, + \{ "type" : "progress", "currentStep" : 3, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "check_disk_space_availability" \}, + \{ "type" : "info", "msg" : "Downloading packs... " \}, + .* + .* + \{ "type" : "info", "msg" : "Starting download of remaining update content. This may take a while... " \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 8, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 16, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 25, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 33, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 41, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 50, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 58, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 66, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 75, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 83, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 91, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "info", "msg" : "Finishing download of update content... " \}, + \{ "type" : "info", "msg" : "Installing bundle\\(s\\) files... " \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 4, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 8, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 12, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 16, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 20, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 25, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 29, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 33, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 37, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 41, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 45, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 50, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 54, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 58, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 62, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 66, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 70, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 75, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 79, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 83, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 87, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 91, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 95, "stepDescription" : "install_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "install_files" \}, + \{ "type" : "info", "msg" : "Calling post-update helper scripts. " \}, + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 7, "stepCompletion" : 100, "stepDescription" : "run_scripts" \}, + \{ "type" : "info", "msg" : "Successfully installed 1 bundle " \}, + \{ "type" : "end", "section" : "bundle-add", "status" : 0 \} + \] EOM ) - assert_is_output "$expected_output" + assert_regex_is_output "$expected_output" + assert_in_output "{ \"type\" : \"progress\", \"currentStep\" : 4, \"totalSteps\" : 7, \"stepCompletion\" : 100, \"stepDescription\" : \"download_packs\" }," } diff --git a/test/functional/bundlelist/list-json.bats b/test/functional/bundlelist/list-json.bats new file mode 100755 index 00000000..f49b50b4 --- /dev/null +++ b/test/functional/bundlelist/list-json.bats @@ -0,0 +1,35 @@ +#!/usr/bin/env bats + +# Author: Castulo Martinez +# Email: castulo.martinez@intel.com + +load "../testlib" + +test_setup() { + + create_test_environment "$TEST_NAME" + create_bundle -L -n test-bundle -f /file_1 "$TEST_NAME" + +} + +@test "LST019: Listing bundles using machine readable output" { + + # the --json-output flag can be used so all the output of the bundle-list + # command is created as a JSON stream that can be read and parsed by other + # applications interested into knowing real time status of the command + + run sudo sh -c "$SWUPD bundle-list --json-output $SWUPD_OPTS" + + assert_status_is 0 + expected_output=$(cat <<-EOM + [ + { "type" : "start", "section" : "bundle-list" }, + { "type" : "info", "msg" : "os-core " }, + { "type" : "info", "msg" : "test-bundle " }, + { "type" : "end", "section" : "bundle-list", "status" : 0 } + ] + EOM + ) + assert_is_output "$expected_output" + +} diff --git a/test/functional/bundleremove/remove-json.bats b/test/functional/bundleremove/remove-json.bats new file mode 100755 index 00000000..d0640cb7 --- /dev/null +++ b/test/functional/bundleremove/remove-json.bats @@ -0,0 +1,36 @@ +#!/usr/bin/env bats + +# Author: Castulo Martinez +# Email: castulo.martinez@intel.com + +load "../testlib" + +test_setup() { + + create_test_environment "$TEST_NAME" + create_bundle -L -n test-bundle -f /file_1 "$TEST_NAME" + +} + +@test "REM020: Removing a bundle using machine readable output" { + + # the --json-output flag can be used so all the output of the bundle-remove + # command is created as a JSON stream that can be read and parsed by other + # applications interested into knowing real time status of the command + + run sudo sh -c "$SWUPD bundle-remove --json-output $SWUPD_OPTS test-bundle" + + assert_status_is 0 + expected_output=$(cat <<-EOM + [ + { "type" : "start", "section" : "bundle-remove" }, + { "type" : "info", "msg" : "Deleting bundle files... " }, + { "type" : "info", "msg" : "Total deleted files: 2 " }, + { "type" : "info", "msg" : "Successfully removed 1 bundle " }, + { "type" : "end", "section" : "bundle-remove", "status" : 0 } + ] + EOM + ) + assert_is_output "$expected_output" + +} diff --git a/test/functional/checkupdate/chk-update-json.bats b/test/functional/checkupdate/chk-update-json.bats new file mode 100755 index 00000000..e93933da --- /dev/null +++ b/test/functional/checkupdate/chk-update-json.bats @@ -0,0 +1,35 @@ +#!/usr/bin/env bats + +# Author: Castulo Martinez +# Email: castulo.martinez@intel.com + +load "../testlib" + +test_setup() { + + create_test_environment "$TEST_NAME" + create_version "$TEST_NAME" 20 10 + +} + +@test "CHK009: Check for updates using machine readable output" { + + # the --json-output flag can be used so all the output of the check-update + # command is created as a JSON stream that can be read and parsed by other + # applications interested into knowing real time status of the command + + run sudo sh -c "$SWUPD check-update --json-outpu $SWUPD_OPTS" + + assert_status_is 0 + expected_output=$(cat <<-EOM + [ + { "type" : "start", "section" : "check-update" }, + { "type" : "info", "msg" : "Current OS version: 10 " }, + { "type" : "info", "msg" : "There is a new OS version available: 20 " }, + { "type" : "end", "section" : "check-update", "status" : 0 } + ] + EOM + ) + assert_is_output "$expected_output" + +} diff --git a/test/functional/mirror/mirror-json.bats b/test/functional/mirror/mirror-json.bats new file mode 100755 index 00000000..7d37edbe --- /dev/null +++ b/test/functional/mirror/mirror-json.bats @@ -0,0 +1,36 @@ +#!/usr/bin/env bats + +# Author: Castulo Martinez +# Email: castulo.martinez@intel.com + +load "../testlib" + +test_setup() { + + create_test_environment "$TEST_NAME" + +} + +@test "MIR006: Set a mirror using machine readable output" { + + # the --json-output flag can be used so all the output of the mirror + # command is created as a JSON stream that can be read and parsed by other + # applications interested into knowing real time status of the command + + run sudo sh -c "$SWUPD mirror --json-output -s http://example.com/swupd-file $SWUPD_OPTS" + + assert_status_is 0 + expected_output=$(cat <<-EOM + [ + { "type" : "start", "section" : "mirror" }, + { "type" : "info", "msg" : "Set upstream mirror to http://example.com/swupd-file " }, + { "type" : "info", "msg" : "Installed version: 10 " }, + { "type" : "info", "msg" : "Version URL: http://example.com/swupd-file " }, + { "type" : "info", "msg" : "Content URL: http://example.com/swupd-file " }, + { "type" : "end", "section" : "mirror", "status" : 0 } + ] + EOM + ) + assert_is_output "$expected_output" + +} diff --git a/test/functional/search/search-json.bats b/test/functional/search/search-json.bats new file mode 100755 index 00000000..a304370f --- /dev/null +++ b/test/functional/search/search-json.bats @@ -0,0 +1,44 @@ +#!/usr/bin/env bats + +# Author: Castulo Martinez +# Email: castulo.martinez@intel.com + +load "../testlib" + +test_setup() { + + create_test_environment "$TEST_NAME" + create_bundle -n test-bundle -f /file_1,/file_2 "$TEST_NAME" + +} + +@test "SRH027: Search for a file using machine readable output" { + + sudo sh -c "$SWUPD search-file --init $SWUPD_OPTS" + + # the --json-output flag can be used so all the output of the search + # command is created as a JSON stream that can be read and parsed by other + # applications interested into knowing real time status of the command + + run sudo sh -c "$SWUPD search-file --json-output $SWUPD_OPTS file_1" + + assert_status_is 0 + expected_output=$(cat <<-EOM + [ + { "type" : "start", "section" : "search" }, + { "type" : "progress", "currentStep" : 1, "totalSteps" : 3, "stepCompletion" : 100, "stepDescription" : "get_versions" }, + { "type" : "progress", "currentStep" : 2, "totalSteps" : 3, "stepCompletion" : 0, "stepDescription" : "load_manifests" }, + { "type" : "progress", "currentStep" : 2, "totalSteps" : 3, "stepCompletion" : 50, "stepDescription" : "load_manifests" }, + { "type" : "progress", "currentStep" : 2, "totalSteps" : 3, "stepCompletion" : 100, "stepDescription" : "load_manifests" }, + { "type" : "info", "msg" : "Searching for 'file_1' " }, + { "type" : "info", "msg" : " Bundle test-bundle " }, + { "type" : "info", "msg" : "(0 MB to install)" }, + { "type" : "info", "msg" : " /file_1 " }, + { "type" : "progress", "currentStep" : 3, "totalSteps" : 3, "stepCompletion" : 100, "stepDescription" : "search_term" }, + { "type" : "end", "section" : "search", "status" : 0 } + ] + EOM + ) + assert_is_output "$expected_output" + +} diff --git a/test/functional/update/update-json.bats b/test/functional/update/update-json.bats new file mode 100755 index 00000000..5df48ccf --- /dev/null +++ b/test/functional/update/update-json.bats @@ -0,0 +1,72 @@ +#!/usr/bin/env bats + +# Author: Castulo Martinez +# Email: castulo.martinez@intel.com + +load "../testlib" + +test_setup() { + + create_test_environment "$TEST_NAME" + create_bundle -L -n test-bundle -f /file1,/file2,/file3 "$TEST_NAME" + create_version "$TEST_NAME" 20 10 + update_bundle "$TEST_NAME" test-bundle --update /file1 + update_bundle "$TEST_NAME" test-bundle --update /file2 + update_bundle "$TEST_NAME" test-bundle --add /file4 + +} + +@test "UPD056: Updating a system using machine readable output" { + + # the --json-output flag can be used so all the output of the update + # command is created as a JSON stream that can be read and parsed by other + # applications interested into knowing real time status of the command + + run sudo sh -c "$SWUPD update --json-output $SWUPD_OPTS" + + assert_status_is 0 + expected_output=$(cat <<-EOM + \[ + \{ "type" : "start", "section" : "update" \}, + \{ "type" : "info", "msg" : "Update started. " \}, + \{ "type" : "progress", "currentStep" : 1, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "prepare_for_update" \}, + \{ "type" : "info", "msg" : "Preparing to update from 10 to 20 " \}, + \{ "type" : "progress", "currentStep" : 2, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "get_versions" \}, + \{ "type" : "progress", "currentStep" : 3, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "cleanup_download_dir" \}, + \{ "type" : "progress", "currentStep" : 4, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "load_manifests" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "run_preupdate_scripts" \}, + \{ "type" : "info", "msg" : "Downloading packs... " \}, + .* + .* + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "apply_deltas" \}, + \{ "type" : "info", "msg" : "Statistics for going from version 10 to version 20: " \}, + \{ "type" : "info", "msg" : " changed bundles : 1 " \}, + \{ "type" : "info", "msg" : " new bundles : 0 " \}, + \{ "type" : "info", "msg" : " deleted bundles : 0 " \}, + \{ "type" : "info", "msg" : " changed files : 2 " \}, + \{ "type" : "info", "msg" : " new files : 1 " \}, + \{ "type" : "info", "msg" : " deleted files : 0 " \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "create_update_list" \}, + \{ "type" : "info", "msg" : "Starting download of remaining update content. This may take a while... " \}, + \{ "type" : "progress", "currentStep" : 9, "totalSteps" : 11, "stepCompletion" : 33, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 9, "totalSteps" : 11, "stepCompletion" : 66, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 9, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "info", "msg" : "Finishing download of update content... " \}, + \{ "type" : "info", "msg" : "Staging file content " \}, + \{ "type" : "info", "msg" : "Applying update " \}, + \{ "type" : "progress", "currentStep" : 10, "totalSteps" : 11, "stepCompletion" : 33, "stepDescription" : "update_files" \}, + \{ "type" : "progress", "currentStep" : 10, "totalSteps" : 11, "stepCompletion" : 66, "stepDescription" : "update_files" \}, + \{ "type" : "progress", "currentStep" : 10, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "update_files" \}, + \{ "type" : "info", "msg" : "Update was applied. " \}, + \{ "type" : "info", "msg" : "Calling post-update helper scripts. " \}, + \{ "type" : "progress", "currentStep" : 11, "totalSteps" : 11, "stepCompletion" : 100, "stepDescription" : "run_postupdate_scripts" \}, + \{ "type" : "info", "msg" : "Update took 0.0 seconds, 0 MB transferred " \}, + \{ "type" : "info", "msg" : "Update successful. System updated from version 10 to version 20 " \}, + \{ "type" : "end", "section" : "update", "status" : 0 \} + \] + EOM + ) + assert_regex_is_output "$expected_output" + assert_in_output "{ \"type\" : \"progress\", \"currentStep\" : 6, \"totalSteps\" : 11, \"stepCompletion\" : 100, \"stepDescription\" : \"download_packs\" }," + +} diff --git a/test/functional/verify/verify-json.bats b/test/functional/verify/verify-json.bats new file mode 100755 index 00000000..a5698978 --- /dev/null +++ b/test/functional/verify/verify-json.bats @@ -0,0 +1,216 @@ +#!/usr/bin/env bats + +# Author: Castulo Martinez +# Email: castulo.martinez@intel.com + +load "../testlib" + +test_setup() { + + create_test_environment -r "$TEST_NAME" + create_bundle -L -n test-bundle1 -f /foo/test-file1,/bar/test-file2,/baz "$TEST_NAME" + create_bundle -n test-bundle2 -f /test-file3,/test-file4 "$TEST_NAME" + sudo rm -f "$TARGETDIR"/foo/test-file1 + sudo rm -f "$TARGETDIR"/baz + sudo touch "$TARGETDIR"/usr/extraneous-file + +} + +@test "VER049: Install a system using machine readable output" { + + # the --json-output flag can be used so all the output of the verify + # command is created as a JSON stream that can be read and parsed by other + # applications interested into knowing real time status of the command + + run sudo sh -c "$SWUPD verify --json-output --install -m 10 $SWUPD_OPTS" + + assert_status_is 0 + expected_output=$(cat <<-EOM + \[ + \{ "type" : "start", "section" : "verify" \}, + \{ "type" : "progress", "currentStep" : 1, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "get_versions" \}, + \{ "type" : "info", "msg" : "Verifying version 10 " \}, + \{ "type" : "progress", "currentStep" : 2, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "cleanup_download_dir" \}, + \{ "type" : "progress", "currentStep" : 3, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "load_manifests" \}, + \{ "type" : "progress", "currentStep" : 4, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "consolidate_files" \}, + \{ "type" : "info", "msg" : "Downloading packs... " \}, + .* + .* + .* + \{ "type" : "info", "msg" : " Extracting test-bundle1 pack for version 10 " \}, + \{ "type" : "info", "msg" : "Verifying files " \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 0, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 5, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 11, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 17, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 23, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 29, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 35, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 41, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 47, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 52, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 58, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 64, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 70, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 76, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 82, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 88, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 94, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "check_files_hash" \}, + \{ "type" : "info", "msg" : "Starting download of remaining update content. This may take a while... " \}, + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 8, "stepCompletion" : 17, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 8, "stepCompletion" : 35, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "info", "msg" : "Finishing download of update content... " \}, + \{ "type" : "info", "msg" : "Adding any missing files " \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 17, "stepDescription" : "add_missing_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 35, "stepDescription" : "add_missing_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "add_missing_files" \}, + \{ "type" : "info", "msg" : "Inspected 17 files " \}, + \{ "type" : "info", "msg" : " 2 files were missing " \}, + \{ "type" : "info", "msg" : " 2 of 2 missing files were replaced " \}, + \{ "type" : "info", "msg" : " 0 of 2 missing files were not replaced " \}, + \{ "type" : "info", "msg" : "Calling post-update helper scripts. " \}, + \{ "type" : "warning", "msg" : "post-update helper script \\(.*/usr/bin/clr-boot-manager\\) not found, it will be skipped " \}, + \{ "type" : "info", "msg" : "Fix successful " \}, + \{ "type" : "end", "section" : "verify", "status" : 0 \} + \] + EOM + ) + + assert_regex_is_output "$expected_output" + assert_in_output "{ \"type\" : \"progress\", \"currentStep\" : 5, \"totalSteps\" : 8, \"stepCompletion\" : 50, \"stepDescription\" : \"download_packs\" }," + +} + +@test "VER050: Fix a system using machine readable output" { + + run sudo sh -c "$SWUPD verify --json-output --fix --picky $SWUPD_OPTS" + + assert_status_is 0 + expected_output=$(cat <<-EOM + \[ + \{ "type" : "start", "section" : "verify" \}, + \{ "type" : "progress", "currentStep" : 1, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "get_versions" \}, + \{ "type" : "info", "msg" : "Verifying version 10 " \}, + \{ "type" : "progress", "currentStep" : 2, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "cleanup_download_dir" \}, + \{ "type" : "progress", "currentStep" : 3, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "load_manifests" \}, + \{ "type" : "progress", "currentStep" : 4, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "consolidate_files" \}, + \{ "type" : "info", "msg" : "Verifying files " \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 0, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 5, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 11, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 17, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 23, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 29, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 35, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 41, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 47, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 52, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 58, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 64, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 70, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 76, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 82, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 88, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 94, "stepDescription" : "check_files_hash" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "check_files_hash" \}, + \{ "type" : "info", "msg" : "Starting download of remaining update content. This may take a while... " \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 17, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 35, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "download_fullfiles" \}, + \{ "type" : "info", "msg" : "Finishing download of update content... " \}, + \{ "type" : "info", "msg" : "Adding any missing files " \}, + \{ "type" : "info", "msg" : " Missing file: .*/baz " \}, + \{ "type" : "info", "msg" : " fixed " \}, + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 8, "stepCompletion" : 17, "stepDescription" : "add_missing_files" \}, + \{ "type" : "info", "msg" : " Missing file: .*/foo/test-file1 " \}, + \{ "type" : "info", "msg" : " fixed " \}, + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 8, "stepCompletion" : 35, "stepDescription" : "add_missing_files" \}, + \{ "type" : "progress", "currentStep" : 7, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "add_missing_files" \}, + \{ "type" : "info", "msg" : "Fixing modified files " \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 5, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 11, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 17, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 23, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 29, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 35, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 41, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 47, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 52, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 58, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 64, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 70, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 76, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 82, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 88, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 94, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 8, "totalSteps" : 8, "stepCompletion" : 100, "stepDescription" : "fix_files" \}, + \{ "type" : "info", "msg" : "--picky removing extra files under .*/usr " \}, + \{ "type" : "info", "msg" : "REMOVING /usr/share/defaults/swupd/versionurl " \}, + \{ "type" : "info", "msg" : "REMOVING /usr/share/defaults/swupd/contenturl " \}, + \{ "type" : "info", "msg" : "REMOVING /usr/extraneous-file " \}, + \{ "type" : "info", "msg" : "Inspected 20 files " \}, + \{ "type" : "info", "msg" : " 2 files were missing " \}, + \{ "type" : "info", "msg" : " 2 of 2 missing files were replaced " \}, + \{ "type" : "info", "msg" : " 0 of 2 missing files were not replaced " \}, + \{ "type" : "info", "msg" : " 3 files found which should be deleted " \}, + \{ "type" : "info", "msg" : " 3 of 3 files were deleted " \}, + \{ "type" : "info", "msg" : " 0 of 3 files were not deleted " \}, + \{ "type" : "info", "msg" : "Calling post-update helper scripts. " \}, + \{ "type" : "warning", "msg" : "post-update helper script \\(.*/usr/bin/clr-boot-manager\\) not found, it will be skipped " \}, + \{ "type" : "info", "msg" : "Fix successful " \}, + \{ "type" : "end", "section" : "verify", "status" : 0 \} + \] + EOM + ) + assert_regex_is_output "$expected_output" + +} + +@test "VER051: Verify a system using machine readable output" { + + run sudo sh -c "$SWUPD verify --json-output $SWUPD_OPTS" + + assert_status_is "$SWUPD_NO" + expected_output=$(cat <<-EOM + \[ + \{ "type" : "start", "section" : "verify" \}, + \{ "type" : "progress", "currentStep" : 1, "totalSteps" : 6, "stepCompletion" : 100, "stepDescription" : "get_versions" \}, + \{ "type" : "info", "msg" : "Verifying version 10 " \}, + \{ "type" : "progress", "currentStep" : 2, "totalSteps" : 6, "stepCompletion" : 100, "stepDescription" : "cleanup_download_dir" \}, + \{ "type" : "progress", "currentStep" : 3, "totalSteps" : 6, "stepCompletion" : 100, "stepDescription" : "load_manifests" \}, + \{ "type" : "progress", "currentStep" : 4, "totalSteps" : 6, "stepCompletion" : 100, "stepDescription" : "consolidate_files" \}, + \{ "type" : "info", "msg" : "Verifying files " \}, + \{ "type" : "info", "msg" : " Missing file: .*/baz " \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 6, "stepCompletion" : 17, "stepDescription" : "add_missing_files" \}, + \{ "type" : "info", "msg" : " Missing file: .*/foo/test-file1 " \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 6, "stepCompletion" : 35, "stepDescription" : "add_missing_files" \}, + \{ "type" : "progress", "currentStep" : 5, "totalSteps" : 6, "stepCompletion" : 100, "stepDescription" : "add_missing_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 5, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 11, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 17, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 23, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 29, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 35, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 41, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 47, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 52, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 58, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 64, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 70, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 76, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 82, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 88, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 94, "stepDescription" : "fix_files" \}, + \{ "type" : "progress", "currentStep" : 6, "totalSteps" : 6, "stepCompletion" : 100, "stepDescription" : "fix_files" \}, + \{ "type" : "info", "msg" : "Inspected 17 files " \}, + \{ "type" : "info", "msg" : " 2 files were missing " \}, + \{ "type" : "info", "msg" : "Verify successful " \}, + \{ "type" : "end", "section" : "verify", "status" : 1 \} + \] + EOM + ) + assert_regex_is_output "$expected_output" + +}