blob: bcc6fb1e98b2171e0f257e5fb9ab507875dac54e [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/storage/extractor/bin/parse.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <zircon/errors.h>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <vector>
#include <gtest/gtest.h>
namespace extractor {
namespace {
struct TestArguments {
static constexpr uint8_t kLength = 64;
// Common arguments for both extract and deflate.
char command[kLength] = "command";
char sub_command[kLength] = "extract";
char input_file[kLength] = "/tmp/extract-input.XXXXXX";
char output_file[kLength] = "/tmp/extract-output.XXXXXX";
char help[kLength] = "--help";
// Arguments applicable only for 'extract' subcommand.
char type[kLength] = "--type";
char type_arg[kLength] = "minfs";
char disk[kLength] = "--disk";
char image[kLength] = "--image";
char extra[kLength] = "--extra";
char pii_dump[kLength] = "--dump-pii";
// Arguments applicable only for 'deflate' subcommand.
char input[kLength] = "--input_file";
char output[kLength] = "--output_file";
char verbose[kLength] = "--verbose";
};
TestArguments setup(bool create_disk, bool create_image_file,
SubCommand sub_command = SubCommand::kExtract) {
TestArguments args;
if (sub_command == SubCommand::kDeflate) {
strcpy(args.sub_command, "deflate");
}
if (create_image_file) {
fbl::unique_fd input_fd(mkostemp(args.output_file, O_RDONLY | O_CREAT | O_EXCL));
EXPECT_TRUE(input_fd);
}
if (!create_disk) {
return args;
}
fbl::unique_fd output_fd(mkostemp(args.input_file, O_RDWR | O_CREAT | O_EXCL));
EXPECT_TRUE(output_fd);
return args;
}
TEST(Parse, NoArgument) {
auto args = setup(/*create_disk=*/false, /*create_image_file=*/false);
char* const argv[] = {args.command};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, ExtractAllArgument) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.type, args.type_arg,
args.disk, args.input_file, args.image, args.output_file,
args.pii_dump, args.help};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, ExtractMissingType) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.disk, args.input_file,
args.image, args.output_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, ExtractInvalidType) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
strncpy(args.type_arg, "njgenkgnaw", sizeof(args.type_arg));
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.type,
args.type_arg, args.disk, args.input_file,
args.image, args.output_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, ExtractMissingDisk) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.type, args.type_arg,
args.image, args.output_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, ExtractMissingImage) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/false);
char* const argv[] = {args.command, args.sub_command, args.type, args.type_arg,
args.disk, args.input_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, ExtractDiskDoesNotExists) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
EXPECT_EQ(remove(args.input_file), 0);
char* const argv[] = {args.command, args.sub_command, args.type,
args.type_arg, args.disk, args.input_file,
args.image, args.output_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(), ZX_ERR_IO);
}
TEST(Parse, ExtractImageFileAlreadyExists) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
char* const argv[] = {args.command, args.sub_command, args.type,
args.type_arg, args.disk, args.input_file,
args.image, args.output_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_ALREADY_EXISTS);
}
TEST(Parse, ExtractFailureToCreateImageFile) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
auto len = strlen(args.output_file);
args.output_file[len] = '/';
args.output_file[len + 1] = '\0';
char* const argv[] = {args.command, args.sub_command, args.type,
args.type_arg, args.disk, args.input_file,
args.image, args.output_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(), ZX_ERR_IO);
}
TEST(Parse, ExtractExtraArgument) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.type, args.type_arg,
args.disk, args.input_file, args.image, args.output_file,
args.pii_dump, args.extra};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, ExtractDumpPii) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.type,
args.type_arg, args.disk, args.input_file,
args.image, args.output_file, args.pii_dump};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).value().dump_pii, true);
}
TEST(Parse, ExtractDontDumpPii) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.type, args.type_arg,
args.disk, args.input_file, args.image, args.output_file};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).value().dump_pii, false);
}
TEST(Parse, DeflateOnlyOneArg) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true, SubCommand::kDeflate);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.output, args.output_file};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_INVALID_ARGS);
}
TEST(Parse, DeflateDiskDoesNotExists) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true, SubCommand::kDeflate);
EXPECT_EQ(remove(args.input_file), 0);
char* const argv[] = {args.command, args.sub_command, args.input,
args.input_file, args.output, args.output_file};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(), ZX_ERR_IO);
}
TEST(Parse, DeflateImageFileAlreadyExists) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true, SubCommand::kDeflate);
char* const argv[] = {args.command, args.sub_command, args.input,
args.input_file, args.output, args.output_file};
ASSERT_EQ(extractor::ParseCommandLineArguments(std::size(argv), argv).error_value(),
ZX_ERR_ALREADY_EXISTS);
}
TEST(Parse, DeflateValidArguments) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true, SubCommand::kDeflate);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.input,
args.input_file, args.output, args.output_file};
auto opts = extractor::ParseCommandLineArguments(std::size(argv), argv).value();
ASSERT_EQ(opts.sub_command, SubCommand::kDeflate);
ASSERT_EQ(opts.verbose, false);
}
TEST(Parse, DeflateValidArgumentsWithVerbose) {
auto args = setup(/*create_disk=*/true, /*create_image_file=*/true, SubCommand::kDeflate);
EXPECT_EQ(remove(args.output_file), 0);
char* const argv[] = {args.command, args.sub_command, args.input, args.input_file,
args.output, args.output_file, args.verbose};
auto opts = extractor::ParseCommandLineArguments(std::size(argv), argv).value();
ASSERT_EQ(opts.sub_command, SubCommand::kDeflate);
ASSERT_EQ(opts.verbose, true);
}
} // namespace
} // namespace extractor