Improve code coverage of MultiCommand class

This change introduces ULTs for untested
parts of MultiCommand class. Furthermore,
it contains MockMultiCommand class, which
allows white-box testing.

Related-To: NEO-6834
Signed-off-by: Patryk Wrobel <patryk.wrobel@intel.com>
This commit is contained in:
Patryk Wrobel
2022-03-31 15:11:55 +00:00
committed by Compute-Runtime-Automation
parent f2a18370e8
commit 9cba46e5bf
7 changed files with 208 additions and 4 deletions

View File

@@ -19,6 +19,7 @@ set(IGDRCL_SRCS_offline_compiler_mock
${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_encoder.h
${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_iga_wrapper.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_argument_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_multi_command.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_compiler.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_linker.h
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_sip_ocloc_tests.cpp

View File

@@ -31,6 +31,8 @@ class MockOclocArgHelper : public OclocArgHelper {
bool callBaseReadBinaryFile = false;
bool callBaseLoadDataFromFile = false;
bool callBaseSaveOutput = false;
bool callBaseReadFileToVectorOfStrings = false;
bool shouldReturnEmptyVectorOfStrings = false;
MockOclocArgHelper(FilesMap &filesMap) : OclocArgHelper(0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr),
filesMap(filesMap){};
@@ -44,6 +46,7 @@ class MockOclocArgHelper : public OclocArgHelper {
callBaseReadBinaryFile = value;
callBaseLoadDataFromFile = value;
callBaseSaveOutput = value;
callBaseReadFileToVectorOfStrings = value;
}
protected:
@@ -54,6 +57,16 @@ class MockOclocArgHelper : public OclocArgHelper {
return filesMap.find(filename) != filesMap.end();
}
void readFileToVectorOfStrings(const std::string &filename, std::vector<std::string> &lines) override {
if (callBaseReadFileToVectorOfStrings) {
return OclocArgHelper::readFileToVectorOfStrings(filename, lines);
}
if (shouldReturnEmptyVectorOfStrings) {
lines.clear();
}
}
std::vector<char> readBinaryFile(const std::string &filename) override {
if (callBaseReadBinaryFile) {
return OclocArgHelper::readBinaryFile(filename);

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/offline_compiler/source/multi_command.h"
#include "opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h"
#include <optional>
#include <string>
namespace NEO {
class MockMultiCommand : public MultiCommand {
public:
using MultiCommand::argHelper;
using MultiCommand::quiet;
using MultiCommand::retValues;
using MultiCommand::addAdditionalOptionsToSingleCommandLine;
using MultiCommand::initialize;
using MultiCommand::printHelp;
using MultiCommand::runBuilds;
using MultiCommand::showResults;
using MultiCommand::singleBuild;
using MultiCommand::splitLineInSeparateArgs;
MockMultiCommand() : MultiCommand{} {
uniqueHelper = std::make_unique<MockOclocArgHelper>(filesMap);
uniqueHelper->setAllCallBase(true);
argHelper = uniqueHelper.get();
}
~MockMultiCommand() override = default;
std::map<std::string, std::string> filesMap{};
std::unique_ptr<MockOclocArgHelper> uniqueHelper{};
};
} // namespace NEO

View File

@@ -27,6 +27,7 @@
#include "gtest/gtest.h"
#include "hw_cmds.h"
#include "mock/mock_argument_helper.h"
#include "mock/mock_multi_command.h"
#include "mock/mock_offline_compiler.h"
#include <algorithm>
@@ -315,6 +316,148 @@ TEST_F(MultiCommandTests, GivenOutputFileListFlagWhenBuildingMultiCommandThenSuc
delete pMultiCommand;
}
TEST(MultiCommandWhiteboxTest, GivenVerboseModeWhenShowingResultsThenLogsArePrintedForEachBuild) {
MockMultiCommand mockMultiCommand{};
mockMultiCommand.retValues = {OclocErrorCode::SUCCESS, OclocErrorCode::INVALID_FILE};
mockMultiCommand.quiet = false;
::testing::internal::CaptureStdout();
const auto result = mockMultiCommand.showResults();
const auto output = testing::internal::GetCapturedStdout();
const auto maskedResult = result | OclocErrorCode::INVALID_FILE;
EXPECT_NE(OclocErrorCode::SUCCESS, result);
EXPECT_EQ(OclocErrorCode::INVALID_FILE, maskedResult);
const auto expectedOutput{"Build command 0: successful\n"
"Build command 1: failed. Error code: -5151\n"};
EXPECT_EQ(expectedOutput, output);
}
TEST(MultiCommandWhiteboxTest, GivenVerboseModeAndDefinedOutputFilenameAndDirectoryWhenAddingAdditionalOptionsToSingleCommandLineThenNothingIsDone) {
MockMultiCommand mockMultiCommand{};
mockMultiCommand.quiet = false;
std::vector<std::string> singleArgs = {
"-file",
"test_files/copybuffer.cl",
"-output",
"SpecialOutputFilename",
"-out_dir",
"SomeOutputDirectory",
"-device",
gEnvironment->devicePrefix.c_str()};
const auto singleArgsCopy{singleArgs};
const size_t buildId{0};
::testing::internal::CaptureStdout();
mockMultiCommand.addAdditionalOptionsToSingleCommandLine(singleArgs, buildId);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(singleArgsCopy, singleArgs);
}
TEST(MultiCommandWhiteboxTest, GivenHelpArgumentsWhenInitializingThenHelpIsPrinted) {
MockMultiCommand mockMultiCommand{};
mockMultiCommand.quiet = false;
std::vector<std::string> singleArgs = {
"--help"};
const auto args{singleArgs};
::testing::internal::CaptureStdout();
const auto result = mockMultiCommand.initialize(args);
const auto output = testing::internal::GetCapturedStdout();
const auto expectedOutput = R"===(Compiles multiple files using a config file.
Usage: ocloc multi <file_name>
<file_name> Input file containing a list of arguments for subsequent
ocloc invocations.
Expected format of each line inside such file is:
'-file <filename> -device <device_type> [compile_options]'.
See 'ocloc compile --help' for available compile_options.
Results of subsequent compilations will be dumped into
a directory with name indentical file_name's base name.
-output_file_list Name of optional file containing
paths to outputs .bin files
)===";
EXPECT_EQ(expectedOutput, output);
EXPECT_EQ(-1, result);
}
TEST(MultiCommandWhiteboxTest, GivenCommandLineWithApostrophesWhenSplittingLineInSeparateArgsThenTextBetweenApostrophesIsReadAsSingleArg) {
MockMultiCommand mockMultiCommand{};
mockMultiCommand.quiet = false;
const std::string commandLine{" -out_dir \"Some Directory\" -output \'Some Filename\'"};
std::vector<std::string> outputArgs{};
const std::size_t numberOfBuild{0};
::testing::internal::CaptureStdout();
const auto result = mockMultiCommand.splitLineInSeparateArgs(outputArgs, commandLine, numberOfBuild);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(OclocErrorCode::SUCCESS, result);
EXPECT_TRUE(output.empty()) << output;
ASSERT_EQ(4u, outputArgs.size());
EXPECT_EQ("-out_dir", outputArgs[0]);
EXPECT_EQ("Some Directory", outputArgs[1]);
EXPECT_EQ("-output", outputArgs[2]);
EXPECT_EQ("Some Filename", outputArgs[3]);
}
TEST(MultiCommandWhiteboxTest, GivenCommandLineWithMissingApostropheWhenSplittingLineInSeparateArgsThenErrorIsReturned) {
MockMultiCommand mockMultiCommand{};
mockMultiCommand.quiet = false;
const std::string commandLine{"-out_dir \"Some Directory"};
std::vector<std::string> outputArgs{};
const std::size_t numberOfBuild{0};
::testing::internal::CaptureStdout();
const auto result = mockMultiCommand.splitLineInSeparateArgs(outputArgs, commandLine, numberOfBuild);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(OclocErrorCode::INVALID_FILE, result);
const auto expectedOutput = "One of the quotes is open in build number 1\n";
EXPECT_EQ(expectedOutput, output);
}
TEST(MultiCommandWhiteboxTest, GivenArgsWithQuietModeAndEmptyMulticomandFileWhenInitializingThenQuietFlagIsSetAndErrorIsReturned) {
MockMultiCommand mockMultiCommand{};
mockMultiCommand.quiet = false;
mockMultiCommand.uniqueHelper->callBaseFileExists = false;
mockMultiCommand.uniqueHelper->callBaseReadFileToVectorOfStrings = false;
mockMultiCommand.uniqueHelper->shouldReturnEmptyVectorOfStrings = true;
mockMultiCommand.filesMap["commands.txt"] = "";
const std::vector<std::string> args = {
"ocloc",
"multi",
"commands.txt",
"-q"};
::testing::internal::CaptureStdout();
const auto result = mockMultiCommand.initialize(args);
const auto output = testing::internal::GetCapturedStdout();
EXPECT_EQ(OclocErrorCode::INVALID_FILE, result);
const auto expectedOutput = "Command file was empty.\n";
EXPECT_EQ(expectedOutput, output);
}
TEST(MockOfflineCompilerTests, givenProductConfigValueWhenInitHwInfoThenResetGtSystemInfo) {
MockOfflineCompiler mockOfflineCompiler;
auto allEnabledDeviceConfigs = mockOfflineCompiler.argHelper->getAllSupportedDeviceConfigs();

View File

@@ -159,7 +159,7 @@ Usage: ocloc multi <file_name>
<file_name> Input file containing a list of arguments for subsequent
ocloc invocations.
Expected format of each line inside such file is:
'-file <filename> -device <device_type> [compile_options].
'-file <filename> -device <device_type> [compile_options]'.
See 'ocloc compile --help' for available compile_options.
Results of subsequent compilations will be dumped into
a directory with name indentical file_name's base name.

View File

@@ -1,10 +1,12 @@
/*
* Copyright (C) 2020-2021 Intel Corporation
* Copyright (C) 2020-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/offline_compiler/source/decoder/binary_decoder.h"
#include "shared/offline_compiler/source/decoder/binary_encoder.h"
#include "shared/offline_compiler/source/offline_compiler.h"
@@ -23,7 +25,7 @@ class MultiCommand {
public:
MultiCommand &operator=(const MultiCommand &) = delete;
MultiCommand(const MultiCommand &) = delete;
~MultiCommand() = default;
MOCKABLE_VIRTUAL ~MultiCommand() = default;
static MultiCommand *create(const std::vector<std::string> &args, int &retVal, OclocArgHelper *helper);

View File

@@ -118,7 +118,7 @@ class OclocArgHelper {
PRODUCT_CONFIG findConfigMatch(const std::string &device, bool firstAppearance);
void insertGenNames(GFXCORE_FAMILY family);
std::vector<std::string> headersToVectorOfStrings();
void readFileToVectorOfStrings(const std::string &filename, std::vector<std::string> &lines);
MOCKABLE_VIRTUAL void readFileToVectorOfStrings(const std::string &filename, std::vector<std::string> &lines);
MOCKABLE_VIRTUAL std::vector<char> readBinaryFile(const std::string &filename);
MOCKABLE_VIRTUAL std::unique_ptr<char[]> loadDataFromFile(const std::string &filename, size_t &retSize);