diff options
author | 2019-02-07 02:21:56 +0100 | |
---|---|---|
committer | 2019-03-19 14:26:38 -0700 | |
commit | 0c6ff1da4f20da59b6bb8649429142390c636743 (patch) | |
tree | e56e9111d6f7c37c9d106e010f78268e4d7a7bc0 | |
parent | 09eb96c4c7874f06bc71d084b7d51eac26779b52 (diff) |
idmap2: move commands to Result<Unit>
Change the signature of the idmap2 commands (Create, Dump, ...) to
return Result<Unit> instead of bool. This removes the need to pass in an
ostream for error messages: instead, those messages are part of the
returned Result.
Consolidate error messages: texts in Error objects should not be
prefixed with "error:", that is the responsibility of the outer-most
caller (i.e. main()).
Test: make idmap2_tests
Change-Id: I074881b3d1982ea8f4be5752161ac74b14fcba95
-rw-r--r-- | cmds/idmap2/idmap2/Commands.h | 12 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Create.cpp | 36 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Dump.cpp | 19 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Lookup.cpp | 41 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Main.cpp | 12 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Scan.cpp | 38 | ||||
-rw-r--r-- | cmds/idmap2/idmap2/Verify.cpp | 22 | ||||
-rw-r--r-- | cmds/idmap2/idmap2d/Idmap2Service.cpp | 3 | ||||
-rw-r--r-- | cmds/idmap2/include/idmap2/CommandLineOptions.h | 4 | ||||
-rw-r--r-- | cmds/idmap2/include/idmap2/Idmap.h | 2 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/CommandLineOptions.cpp | 36 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/Idmap.cpp | 40 | ||||
-rw-r--r-- | cmds/idmap2/tests/CommandLineOptionsTests.cpp | 48 | ||||
-rw-r--r-- | cmds/idmap2/tests/IdmapTests.cpp | 14 |
14 files changed, 166 insertions, 161 deletions
diff --git a/cmds/idmap2/idmap2/Commands.h b/cmds/idmap2/idmap2/Commands.h index dcc69b30743d..718e361b38ab 100644 --- a/cmds/idmap2/idmap2/Commands.h +++ b/cmds/idmap2/idmap2/Commands.h @@ -20,10 +20,12 @@ #include <string> #include <vector> -bool Create(const std::vector<std::string>& args, std::ostream& out_error); -bool Dump(const std::vector<std::string>& args, std::ostream& out_error); -bool Lookup(const std::vector<std::string>& args, std::ostream& out_error); -bool Scan(const std::vector<std::string>& args, std::ostream& out_error); -bool Verify(const std::vector<std::string>& args, std::ostream& out_error); +#include "idmap2/Result.h" + +android::idmap2::Result<android::idmap2::Unit> Create(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Dump(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Lookup(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Scan(const std::vector<std::string>& args); +android::idmap2::Result<android::idmap2::Unit> Verify(const std::vector<std::string>& args); #endif // IDMAP2_IDMAP2_COMMANDS_H_ diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp index c416fa123b73..fdbb21044176 100644 --- a/cmds/idmap2/idmap2/Create.cpp +++ b/cmds/idmap2/idmap2/Create.cpp @@ -33,14 +33,17 @@ using android::ApkAssets; using android::idmap2::BinaryStreamVisitor; using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::Idmap; using android::idmap2::PoliciesToBitmask; using android::idmap2::PolicyBitmask; using android::idmap2::PolicyFlags; +using android::idmap2::Result; +using android::idmap2::Unit; using android::idmap2::utils::kIdmapFilePermissionMask; using android::idmap2::utils::UidHasWriteAccessToPath; -bool Create(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Create(const std::vector<std::string>& args) { SYSTRACE << "Create " << args; std::string target_apk_path; std::string overlay_apk_path; @@ -63,15 +66,14 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { &policies) .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks", &ignore_overlayable); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } const uid_t uid = getuid(); if (!UidHasWriteAccessToPath(uid, idmap_path)) { - out_error << "error: uid " << uid << " does not have write access to " << idmap_path - << std::endl; - return false; + return Error("uid %d does not have write access to %s", uid, idmap_path.c_str()); } PolicyBitmask fulfilled_policies = 0; @@ -79,8 +81,7 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { if (conv_result) { fulfilled_policies |= *conv_result; } else { - out_error << "error: " << conv_result.GetErrorMessage() << std::endl; - return false; + return conv_result.GetError(); } if (fulfilled_policies == 0) { @@ -89,36 +90,33 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path); if (!target_apk) { - out_error << "error: failed to load apk " << target_apk_path << std::endl; - return false; + return Error("failed to load apk %s", target_apk_path.c_str()); } const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); if (!overlay_apk) { - out_error << "error: failed to load apk " << overlay_apk_path << std::endl; - return false; + return Error("failed to load apk %s", overlay_apk_path.c_str()); } + std::stringstream stream; const std::unique_ptr<const Idmap> idmap = Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, - fulfilled_policies, !ignore_overlayable, out_error); + fulfilled_policies, !ignore_overlayable, stream); if (!idmap) { - return false; + return Error("failed to create idmap: %s", stream.str().c_str()); } umask(kIdmapFilePermissionMask); std::ofstream fout(idmap_path); if (fout.fail()) { - out_error << "failed to open idmap path " << idmap_path << std::endl; - return false; + return Error("failed to open idmap path %s", idmap_path.c_str()); } BinaryStreamVisitor visitor(fout); idmap->accept(&visitor); fout.close(); if (fout.fail()) { - out_error << "failed to write to idmap path " << idmap_path << std::endl; - return false; + return Error("failed to write to idmap path %s", idmap_path.c_str()); } - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Dump.cpp b/cmds/idmap2/idmap2/Dump.cpp index 3947703fe8da..fd5822251188 100644 --- a/cmds/idmap2/idmap2/Dump.cpp +++ b/cmds/idmap2/idmap2/Dump.cpp @@ -17,6 +17,7 @@ #include <fstream> #include <iostream> #include <memory> +#include <sstream> #include <string> #include <vector> @@ -24,14 +25,18 @@ #include "idmap2/Idmap.h" #include "idmap2/PrettyPrintVisitor.h" #include "idmap2/RawPrintVisitor.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::Idmap; using android::idmap2::PrettyPrintVisitor; using android::idmap2::RawPrintVisitor; +using android::idmap2::Result; +using android::idmap2::Unit; -bool Dump(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Dump(const std::vector<std::string>& args) { SYSTRACE << "Dump " << args; std::string idmap_path; bool verbose; @@ -40,14 +45,16 @@ bool Dump(const std::vector<std::string>& args, std::ostream& out_error) { CommandLineOptions("idmap2 dump") .MandatoryOption("--idmap-path", "input: path to idmap file to pretty-print", &idmap_path) .OptionalFlag("--verbose", "annotate every byte of the idmap", &verbose); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } + std::stringstream stream; std::ifstream fin(idmap_path); - const std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, out_error); + const std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, stream); fin.close(); if (!idmap) { - return false; + return Error("failed to load idmap: %s", stream.str().c_str()); } if (verbose) { @@ -58,5 +65,5 @@ bool Dump(const std::vector<std::string>& args, std::ostream& out_error) { idmap->accept(&visitor); } - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index 83a40efee3f3..677c6fa155dd 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -57,6 +57,7 @@ using android::idmap2::Error; using android::idmap2::IdmapHeader; using android::idmap2::ResourceId; using android::idmap2::Result; +using android::idmap2::Unit; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; @@ -157,7 +158,7 @@ Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path } } // namespace -bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Lookup(const std::vector<std::string>& args) { SYSTRACE << "Lookup " << args; std::vector<std::string> idmap_paths; std::string config_str; @@ -172,14 +173,14 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { "'[package:]type/name') to look up", &resid_str); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } ConfigDescription config; if (!ConfigDescription::Parse(config_str, &config)) { - out_error << "error: failed to parse config" << std::endl; - return false; + return Error("failed to parse config"); } std::vector<std::unique_ptr<const ApkAssets>> apk_assets; @@ -191,39 +192,33 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { auto idmap_header = IdmapHeader::FromBinaryStream(fin); fin.close(); if (!idmap_header) { - out_error << "error: failed to read idmap from " << idmap_path << std::endl; - return false; + return Error("failed to read idmap from %s", idmap_path.c_str()); } if (i == 0) { target_path = idmap_header->GetTargetPath().to_string(); auto target_apk = ApkAssets::Load(target_path); if (!target_apk) { - out_error << "error: failed to read target apk from " << target_path << std::endl; - return false; + return Error("failed to read target apk from %s", target_path.c_str()); } apk_assets.push_back(std::move(target_apk)); const Result<std::string> package_name = GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string()); if (!package_name) { - out_error << "error: failed to parse android:targetPackage from overlay manifest" - << std::endl; - return false; + return Error("failed to parse android:targetPackage from overlay manifest"); } target_package_name = *package_name; } else if (target_path != idmap_header->GetTargetPath()) { - out_error << "error: different target APKs (expected target APK " << target_path << " but " - << idmap_path << " has target APK " << idmap_header->GetTargetPath() << ")" - << std::endl; - return false; + return Error("different target APKs (expected target APK %s but %s has target APK %s)", + target_path.c_str(), idmap_path.c_str(), + idmap_header->GetTargetPath().to_string().c_str()); } auto overlay_apk = ApkAssets::LoadOverlay(idmap_path); if (!overlay_apk) { - out_error << "error: failed to read overlay apk from " << idmap_header->GetOverlayPath() - << std::endl; - return false; + return Error("failed to read overlay apk from %s", + idmap_header->GetOverlayPath().to_string().c_str()); } apk_assets.push_back(std::move(overlay_apk)); } @@ -238,16 +233,14 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name); if (!resid) { - out_error << "error: failed to parse resource ID" << std::endl; - return false; + return Error(resid.GetError(), "failed to parse resource ID"); } const Result<std::string> value = GetValue(am, *resid); if (!value) { - out_error << StringPrintf("error: resource 0x%08x not found", *resid) << std::endl; - return false; + return Error(value.GetError(), "resource 0x%08x not found", *resid); } std::cout << *value << std::endl; - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp index a0ffccb26dfe..d8867fe8f497 100644 --- a/cmds/idmap2/idmap2/Main.cpp +++ b/cmds/idmap2/idmap2/Main.cpp @@ -24,14 +24,17 @@ #include <vector> #include "idmap2/CommandLineOptions.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" #include "Commands.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Result; +using android::idmap2::Unit; using NameToFunctionMap = - std::map<std::string, std::function<bool(const std::vector<std::string>&, std::ostream&)>>; + std::map<std::string, std::function<Result<Unit>(const std::vector<std::string>&)>>; namespace { @@ -69,5 +72,10 @@ int main(int argc, char** argv) { PrintUsage(commands, std::cerr); return EXIT_FAILURE; } - return iter->second(*args, std::cerr) ? EXIT_SUCCESS : EXIT_FAILURE; + const auto result = iter->second(*args); + if (!result) { + std::cerr << "error: " << result.GetErrorMessage() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp index e85f132c6072..24331af9fd6d 100644 --- a/cmds/idmap2/idmap2/Scan.cpp +++ b/cmds/idmap2/idmap2/Scan.cpp @@ -30,6 +30,7 @@ #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" #include "idmap2/ResourceUtils.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" @@ -37,6 +38,7 @@ #include "Commands.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::Idmap; using android::idmap2::kPolicyProduct; using android::idmap2::kPolicyPublic; @@ -45,6 +47,7 @@ using android::idmap2::kPolicyVendor; using android::idmap2::PolicyBitmask; using android::idmap2::PolicyFlags; using android::idmap2::Result; +using android::idmap2::Unit; using android::idmap2::utils::ExtractOverlayManifestInfo; using android::idmap2::utils::FindFiles; using android::idmap2::utils::OverlayManifestInfo; @@ -69,8 +72,8 @@ bool VendorIsQOrLater() { return version == "Q" || version == "q"; } -std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs, - bool recursive, std::ostream& out_error) { +Result<std::unique_ptr<std::vector<std::string>>> FindApkFiles(const std::vector<std::string>& dirs, + bool recursive) { SYSTRACE << "FindApkFiles " << dirs << " " << recursive; const auto predicate = [](unsigned char type, const std::string& path) -> bool { static constexpr size_t kExtLen = 4; // strlen(".apk") @@ -82,8 +85,7 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st for (const auto& dir : dirs) { const auto apk_paths = FindFiles(dir, recursive, predicate); if (!apk_paths) { - out_error << "error: failed to open directory " << dir << std::endl; - return nullptr; + return Error("failed to open directory %s", dir.c_str()); } paths.insert(apk_paths->cbegin(), apk_paths->cend()); } @@ -110,7 +112,7 @@ std::vector<std::string> PoliciesForPath(const std::string& apk_path) { } // namespace -bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Scan(const std::vector<std::string>& args) { SYSTRACE << "Scan " << args; std::vector<std::string> input_directories; std::string target_package_name; @@ -135,22 +137,22 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { "input: an overlayable policy this overlay fulfills " "(if none or supplied, the overlays will not have their policies overriden", &override_policies); - if (!opts.Parse(args, out_error)) { - return false; + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } - const auto apk_paths = FindApkFiles(input_directories, recursive, out_error); + const auto apk_paths = FindApkFiles(input_directories, recursive); if (!apk_paths) { - return false; + return Error(apk_paths.GetError(), "failed to find apk files"); } std::vector<InputOverlay> interesting_apks; - for (const std::string& path : *apk_paths) { + for (const std::string& path : **apk_paths) { Result<OverlayManifestInfo> overlay_info = ExtractOverlayManifestInfo(path, /* assert_overlay */ false); if (!overlay_info) { - out_error << "error: " << overlay_info.GetErrorMessage() << std::endl; - return false; + return overlay_info.GetError(); } if (!overlay_info->is_static) { @@ -194,16 +196,13 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::stringstream stream; for (const auto& overlay : interesting_apks) { - // Create the idmap for the overlay if it currently does not exist or if it is not up to date. - std::stringstream dev_null; - std::vector<std::string> verify_args = {"--idmap-path", overlay.idmap_path}; for (const std::string& policy : overlay.policies) { verify_args.emplace_back("--policy"); verify_args.emplace_back(policy); } - if (!Verify(std::vector<std::string>(verify_args), dev_null)) { + if (!Verify(std::vector<std::string>(verify_args))) { std::vector<std::string> create_args = {"--target-apk-path", target_apk_path, "--overlay-apk-path", overlay.apk_path, "--idmap-path", overlay.idmap_path}; @@ -216,8 +215,9 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { create_args.emplace_back(policy); } - if (!Create(create_args, out_error)) { - return false; + const auto create_ok = Create(create_args); + if (!create_ok) { + return Error(create_ok.GetError(), "failed to create idmap"); } } @@ -226,5 +226,5 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::cout << stream.str(); - return true; + return Unit{}; } diff --git a/cmds/idmap2/idmap2/Verify.cpp b/cmds/idmap2/idmap2/Verify.cpp index d8fe7aa0ed99..9cb67b33e6cf 100644 --- a/cmds/idmap2/idmap2/Verify.cpp +++ b/cmds/idmap2/idmap2/Verify.cpp @@ -21,29 +21,39 @@ #include "idmap2/CommandLineOptions.h" #include "idmap2/Idmap.h" +#include "idmap2/Result.h" #include "idmap2/SysTrace.h" using android::idmap2::CommandLineOptions; +using android::idmap2::Error; using android::idmap2::IdmapHeader; +using android::idmap2::Result; +using android::idmap2::Unit; -bool Verify(const std::vector<std::string>& args, std::ostream& out_error) { +Result<Unit> Verify(const std::vector<std::string>& args) { SYSTRACE << "Verify " << args; std::string idmap_path; const CommandLineOptions opts = CommandLineOptions("idmap2 verify") .MandatoryOption("--idmap-path", "input: path to idmap file to verify", &idmap_path); - if (!opts.Parse(args, out_error)) { - return false; + + const auto opts_ok = opts.Parse(args); + if (!opts_ok) { + return opts_ok.GetError(); } std::ifstream fin(idmap_path); const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin); fin.close(); if (!header) { - out_error << "error: failed to parse idmap header" << std::endl; - return false; + return Error("failed to parse idmap header"); + } + + const auto header_ok = header->IsUpToDate(); + if (!header_ok) { + return Error(header_ok.GetError(), "idmap not up to date"); } - return header->IsUpToDate(out_error); + return Unit{}; } diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index fa944143e408..e03a9cc1032e 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -104,8 +104,7 @@ Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path, std::ifstream fin(idmap_path); const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin); fin.close(); - std::stringstream dev_null; - *_aidl_return = header && header->IsUpToDate(dev_null); + *_aidl_return = header && header->IsUpToDate(); // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed diff --git a/cmds/idmap2/include/idmap2/CommandLineOptions.h b/cmds/idmap2/include/idmap2/CommandLineOptions.h index 6db6bf9ea8ad..52ac8181da02 100644 --- a/cmds/idmap2/include/idmap2/CommandLineOptions.h +++ b/cmds/idmap2/include/idmap2/CommandLineOptions.h @@ -23,6 +23,8 @@ #include <string> #include <vector> +#include "idmap2/Result.h" + namespace android::idmap2 { /* @@ -46,7 +48,7 @@ class CommandLineOptions { std::string* value); CommandLineOptions& OptionalOption(const std::string& name, const std::string& description, std::vector<std::string>* value); - bool Parse(const std::vector<std::string>& argv, std::ostream& outError) const; + Result<Unit> Parse(const std::vector<std::string>& argv) const; void Usage(std::ostream& out) const; private: diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index 1666dc8a3bbd..673d18d25907 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -115,7 +115,7 @@ class IdmapHeader { // Invariant: anytime the idmap data encoding is changed, the idmap version // field *must* be incremented. Because of this, we know that if the idmap // header is up-to-date the entire file is up-to-date. - bool IsUpToDate(std::ostream& out_error) const; + Result<Unit> IsUpToDate() const; void accept(Visitor* v) const; diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp index a49a607091a4..d5fd2ce38b11 100644 --- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp +++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp @@ -19,12 +19,14 @@ #include <iostream> #include <memory> #include <set> +#include <sstream> #include <string> #include <vector> #include "android-base/macros.h" #include "idmap2/CommandLineOptions.h" +#include "idmap2/Result.h" namespace android::idmap2 { @@ -77,7 +79,7 @@ CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name, return *this; } -bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostream& outError) const { +Result<Unit> CommandLineOptions::Parse(const std::vector<std::string>& argv) const { const auto pivot = std::partition(options_.begin(), options_.end(), [](const Option& opt) { return opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE; }); @@ -89,8 +91,9 @@ bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostrea for (size_t i = 0; i < argv_size; i++) { const std::string arg = argv[i]; if ("--help" == arg || "-h" == arg) { - Usage(outError); - return false; + std::stringstream stream; + Usage(stream); + return Error("%s", stream.str().c_str()); } bool match = false; for (const Option& opt : options_) { @@ -100,9 +103,9 @@ bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostrea if (opt.argument) { i++; if (i >= argv_size) { - outError << "error: " << opt.name << ": missing argument" << std::endl; - Usage(outError); - return false; + std::stringstream stream; + Usage(stream); + return Error("%s: missing argument\n%s", opt.name.c_str(), stream.str().c_str()); } } opt.action(argv[i]); @@ -111,20 +114,27 @@ bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostrea } } if (!match) { - outError << "error: " << arg << ": unknown option" << std::endl; - Usage(outError); - return false; + std::stringstream stream; + Usage(stream); + return Error("%s: unknown option\n%s", arg.c_str(), stream.str().c_str()); } } if (!mandatory_opts.empty()) { + std::stringstream stream; + bool separator = false; for (const auto& opt : mandatory_opts) { - outError << "error: " << opt << ": missing mandatory option" << std::endl; + if (separator) { + stream << ", "; + } + separator = true; + stream << opt << ": missing mandatory option"; } - Usage(outError); - return false; + stream << std::endl; + Usage(stream); + return Error("%s", stream.str().c_str()); } - return true; + return Unit{}; } void CommandLineOptions::Usage(std::ostream& out) const { diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index a7d180c90307..2a39c2fd4f59 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -142,62 +142,46 @@ std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& s return std::move(idmap_header); } -bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { +Result<Unit> IdmapHeader::IsUpToDate() const { if (magic_ != kIdmapMagic) { - out_error << base::StringPrintf("error: bad magic: actual 0x%08x, expected 0x%08x", magic_, - kIdmapMagic) - << std::endl; - return false; + return Error("bad magic: actual 0x%08x, expected 0x%08x", magic_, kIdmapMagic); } if (version_ != kIdmapCurrentVersion) { - out_error << base::StringPrintf("error: bad version: actual 0x%08x, expected 0x%08x", version_, - kIdmapCurrentVersion) - << std::endl; - return false; + return Error("bad version: actual 0x%08x, expected 0x%08x", version_, kIdmapCurrentVersion); } const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path_); if (!target_zip) { - out_error << "error: failed to open target " << target_path_ << std::endl; - return false; + return Error("failed to open target %s", GetTargetPath().to_string().c_str()); } Result<uint32_t> target_crc = GetCrc(*target_zip); if (!target_crc) { - out_error << "error: failed to get target crc" << std::endl; - return false; + return Error("failed to get target crc"); } if (target_crc_ != *target_crc) { - out_error << base::StringPrintf( - "error: bad target crc: idmap version 0x%08x, file system version 0x%08x", - target_crc_, *target_crc) - << std::endl; - return false; + return Error("bad target crc: idmap version 0x%08x, file system version 0x%08x", target_crc_, + *target_crc); } const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path_); if (!overlay_zip) { - out_error << "error: failed to open overlay " << overlay_path_ << std::endl; - return false; + return Error("failed to open overlay %s", GetOverlayPath().to_string().c_str()); } Result<uint32_t> overlay_crc = GetCrc(*overlay_zip); if (!overlay_crc) { - out_error << "error: failed to get overlay crc" << std::endl; - return false; + return Error("failed to get overlay crc"); } if (overlay_crc_ != *overlay_crc) { - out_error << base::StringPrintf( - "error: bad overlay crc: idmap version 0x%08x, file system version 0x%08x", - overlay_crc_, *overlay_crc) - << std::endl; - return false; + return Error("bad overlay crc: idmap version 0x%08x, file system version 0x%08x", overlay_crc_, + *overlay_crc); } - return true; + return Unit{}; } std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) { diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp index 39f18d3336af..d567af64b16a 100644 --- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp +++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp @@ -46,14 +46,13 @@ TEST(CommandLineOptionsTests, Flag) { CommandLineOptions opts = CommandLineOptions("test").OptionalFlag("--foo", "", &foo).OptionalFlag("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "--bar"}, fakeStdErr); + auto success = opts.Parse({"--foo", "--bar"}); ASSERT_TRUE(success); ASSERT_TRUE(foo); ASSERT_TRUE(bar); foo = bar = false; - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_TRUE(success); ASSERT_TRUE(foo); ASSERT_FALSE(bar); @@ -65,21 +64,19 @@ TEST(CommandLineOptionsTests, MandatoryOption) { CommandLineOptions opts = CommandLineOptions("test") .MandatoryOption("--foo", "", &foo) .MandatoryOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "FOO"); ASSERT_EQ(bar, "BAR"); - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_FALSE(success); } TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) { std::string foo; CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &foo); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "SECOND"); } @@ -87,8 +84,7 @@ TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) { TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsAndExpectedOnceOrMore) { std::vector<std::string> args; CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &args); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(args.size(), 2U); ASSERT_EQ(args[0], "FOO"); @@ -101,23 +97,22 @@ TEST(CommandLineOptionsTests, OptionalOption) { CommandLineOptions opts = CommandLineOptions("test") .OptionalOption("--foo", "", &foo) .OptionalOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "FOO"); ASSERT_EQ(bar, "BAR"); - success = opts.Parse({"--foo", "BAZ"}, fakeStdErr); + success = opts.Parse({"--foo", "BAZ"}); ASSERT_TRUE(success); ASSERT_EQ(foo, "BAZ"); - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_FALSE(success); - success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr); + success = opts.Parse({"--foo", "--bar", "BAR"}); ASSERT_FALSE(success); - success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr); + success = opts.Parse({"--foo", "FOO", "--bar"}); ASSERT_FALSE(success); } @@ -127,8 +122,7 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { CommandLineOptions opts = CommandLineOptions("test") .OptionalOption("--foo", "", &foo) .OptionalOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr); + auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); ASSERT_TRUE(success); ASSERT_EQ(foo.size(), 1U); ASSERT_EQ(foo[0], "FOO"); @@ -137,7 +131,7 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { foo.clear(); bar.clear(); - success = opts.Parse({"--foo", "BAZ"}, fakeStdErr); + success = opts.Parse({"--foo", "BAZ"}); ASSERT_TRUE(success); ASSERT_EQ(foo.size(), 1U); ASSERT_EQ(foo[0], "BAZ"); @@ -145,8 +139,7 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { foo.clear(); bar.clear(); - success = - opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}, fakeStdErr); + success = opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}); ASSERT_TRUE(success); ASSERT_EQ(foo.size(), 2U); ASSERT_EQ(foo[0], "BAZ"); @@ -157,17 +150,17 @@ TEST(CommandLineOptionsTests, OptionalOptionList) { foo.clear(); bar.clear(); - success = opts.Parse({"--foo"}, fakeStdErr); + success = opts.Parse({"--foo"}); ASSERT_FALSE(success); foo.clear(); bar.clear(); - success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr); + success = opts.Parse({"--foo", "--bar", "BAR"}); ASSERT_FALSE(success); foo.clear(); bar.clear(); - success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr); + success = opts.Parse({"--foo", "FOO", "--bar"}); ASSERT_FALSE(success); } @@ -179,14 +172,13 @@ TEST(CommandLineOptionsTests, CornerCases) { .MandatoryOption("--foo", "", &foo) .OptionalFlag("--baz", "", &baz) .OptionalOption("--bar", "", &bar); - std::ostream fakeStdErr(nullptr); - bool success = opts.Parse({"--unexpected"}, fakeStdErr); + auto success = opts.Parse({"--unexpected"}); ASSERT_FALSE(success); - success = opts.Parse({"--bar", "BAR"}, fakeStdErr); + success = opts.Parse({"--bar", "BAR"}); ASSERT_FALSE(success); - success = opts.Parse({"--baz", "--foo", "FOO"}, fakeStdErr); + success = opts.Parse({"--baz", "--foo", "FOO"}); ASSERT_TRUE(success); ASSERT_TRUE(baz); ASSERT_EQ(foo, "FOO"); diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 8d65428f134e..c20ae7b798a3 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -501,7 +501,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream); ASSERT_THAT(header, NotNull()); - ASSERT_TRUE(header->IsUpToDate(error)) << error.str(); + ASSERT_TRUE(header->IsUpToDate()); // magic: bytes (0x0, 0x03) std::string bad_magic_string(stream.str()); @@ -514,7 +514,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_magic_stream); ASSERT_THAT(bad_magic_header, NotNull()); ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic()); - ASSERT_FALSE(bad_magic_header->IsUpToDate(error)); + ASSERT_FALSE(bad_magic_header->IsUpToDate()); // version: bytes (0x4, 0x07) std::string bad_version_string(stream.str()); @@ -527,7 +527,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_version_stream); ASSERT_THAT(bad_version_header, NotNull()); ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion()); - ASSERT_FALSE(bad_version_header->IsUpToDate(error)); + ASSERT_FALSE(bad_version_header->IsUpToDate()); // target crc: bytes (0x8, 0xb) std::string bad_target_crc_string(stream.str()); @@ -540,7 +540,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_target_crc_stream); ASSERT_THAT(bad_target_crc_header, NotNull()); ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc()); - ASSERT_FALSE(bad_target_crc_header->IsUpToDate(error)); + ASSERT_FALSE(bad_target_crc_header->IsUpToDate()); // overlay crc: bytes (0xc, 0xf) std::string bad_overlay_crc_string(stream.str()); @@ -553,7 +553,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_overlay_crc_stream); ASSERT_THAT(bad_overlay_crc_header, NotNull()); ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc()); - ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate(error)); + ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate()); // target path: bytes (0x10, 0x10f) std::string bad_target_path_string(stream.str()); @@ -563,7 +563,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_target_path_stream); ASSERT_THAT(bad_target_path_header, NotNull()); ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath()); - ASSERT_FALSE(bad_target_path_header->IsUpToDate(error)); + ASSERT_FALSE(bad_target_path_header->IsUpToDate()); // overlay path: bytes (0x110, 0x20f) std::string bad_overlay_path_string(stream.str()); @@ -573,7 +573,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { IdmapHeader::FromBinaryStream(bad_overlay_path_stream); ASSERT_THAT(bad_overlay_path_header, NotNull()); ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath()); - ASSERT_FALSE(bad_overlay_path_header->IsUpToDate(error)); + ASSERT_FALSE(bad_overlay_path_header->IsUpToDate()); } class TestVisitor : public Visitor { |