Add detailed help to channel linter

dependabot/npm_and_yarn/Src/WebController/UI/websocket-extensions-0.1.4
Grzegorz Rychlik 2020-02-19 15:04:37 +01:00
parent e0b253f6aa
commit 471ea7cc7a
6 changed files with 106 additions and 21 deletions

View File

@ -13,8 +13,14 @@ namespace MWR::C3::Linter
return m_ChannelArguments || m_Command || m_TestChannelIO; return m_ChannelArguments || m_Command || m_TestChannelIO;
} }
/// Whether -h was set
bool m_ShowHelp = false;
/// Whether -l was set
bool m_ListChannels = false;
/// Channel name e.g. Slack /// Channel name e.g. Slack
std::string m_ChannelName; std::optional<std::string> m_ChannelName;
/// String representation of arguments passed to create a channel /// String representation of arguments passed to create a channel
std::optional<StringVector> m_ChannelArguments; std::optional<StringVector> m_ChannelArguments;

View File

@ -6,17 +6,22 @@ namespace MWR::C3::Linter
ArgumentParser::ArgumentParser(int argc, char** argv) : m_ArgParser() ArgumentParser::ArgumentParser(int argc, char** argv) : m_ArgParser()
{ {
ConfigureParser(); ConfigureParser();
m_AppName = argv[0];
m_ArgParser.parse(argc, argv); m_ArgParser.parse(argc, argv);
m_Config = CreateConfig(); FillConfig();
ValidateConfig();
} }
void ArgumentParser::ConfigureParser() void ArgumentParser::ConfigureParser()
{ {
m_ArgParser.addArgument("-n", "--name", 1, false); m_ArgParser.addArgument("-h", "--help");
m_ArgParser.addArgument("-l", "--list");
m_ArgParser.addArgument("-n", "--name", 1);
m_ArgParser.addArgument("-a", "--args", '*'); m_ArgParser.addArgument("-a", "--args", '*');
m_ArgParser.addArgument("-c", "--complementary", '*'); m_ArgParser.addArgument("-c", "--complementary", '*');
m_ArgParser.addArgument("-i", "--test-io"); m_ArgParser.addArgument("-i", "--test-io");
m_ArgParser.addArgument("-x", "--command", '+'); m_ArgParser.addArgument("-x", "--command", '+');
m_ArgParser.useExceptions(true);
} }
AppConfig const& ArgumentParser::GetConfig() const AppConfig const& ArgumentParser::GetConfig() const
@ -26,31 +31,57 @@ namespace MWR::C3::Linter
std::string ArgumentParser::GetUsage() const std::string ArgumentParser::GetUsage() const
{ {
return m_ArgParser.usage(); return "Usage: " + m_AppName.filename().string() + R"( {-h|-l|-n NAME [options]}
Mode:
-h, --help Show this message and exit.
-l, --list List registered Channels and exit.
-n <NAME>, --name <NAME>
Select channel with given <NAME> for further processing
Options:
-a [ARGS...], --args [ARGS...]
Create channel with given ARGS using the Capability/create/arguments.
-c [ARGS...], --complementary [ARGS...]
Create a complementary channel with given ARGS.
-i, --test-io Create a pair of channels and send packets through.
If this option is present -a [ARGS...] must be specified.
If -c is not present, complementary channel arguments are deduced by swapping
parameters from Capability/create/arguments arrays.
-x <ID> [ARGS... ], --command <ID> [ARGS... ]
Execute a command with a given <ID> and arguments [ARGS...]
)";
} }
MWR::C3::Linter::AppConfig ArgumentParser::CreateConfig() const void ArgumentParser::FillConfig()
{ {
AppConfig config; m_Config.m_ShowHelp = m_ArgParser.exists("help");
config.m_ChannelName = m_ArgParser.retrieve<std::string>("name"); m_Config.m_ListChannels = m_ArgParser.exists("list");
if (m_ArgParser.exists("name"))
m_Config.m_ChannelName = m_ArgParser.retrieve<std::string>("name");
if (m_ArgParser.exists("args")) if (m_ArgParser.exists("args"))
config.m_ChannelArguments = m_ArgParser.retrieve<std::vector<std::string>>("args"); m_Config.m_ChannelArguments = m_ArgParser.retrieve<std::vector<std::string>>("args");
if (m_ArgParser.exists("complementary")) if (m_ArgParser.exists("complementary"))
config.m_ComplementaryChannelArguments = m_ArgParser.retrieve<std::vector<std::string>>("complementary"); m_Config.m_ComplementaryChannelArguments = m_ArgParser.retrieve<std::vector<std::string>>("complementary");
config.m_TestChannelIO = m_ArgParser.exists("test-io"); m_Config.m_TestChannelIO = m_ArgParser.exists("test-io");
if (m_ArgParser.exists("command")) if (m_ArgParser.exists("command"))
config.m_Command = m_ArgParser.retrieve<StringVector>("command"); m_Config.m_Command = m_ArgParser.retrieve<StringVector>("command");
ValidateConfig();
return config;
} }
void ArgumentParser::ValidateConfig() const void ArgumentParser::ValidateConfig() const
{ {
if(!(m_Config.m_ShowHelp || m_Config.m_ListChannels || m_Config.m_ChannelName))
throw std::invalid_argument("Argument error: either -h (--help), -l (--list) or -n (--name) must be specified");
if (m_Config.m_TestChannelIO && !m_Config.m_ChannelArguments) if (m_Config.m_TestChannelIO && !m_Config.m_ChannelArguments)
throw std::invalid_argument("Argument error: specified -i (--test-io) without -a (--args)"); throw std::invalid_argument("Argument error: specified -i (--test-io) without -a (--args)");

View File

@ -23,12 +23,15 @@ namespace MWR::C3::Linter
void ConfigureParser(); void ConfigureParser();
/// Helper create AppConfig /// Helper create AppConfig
AppConfig CreateConfig() const; void FillConfig();
/// Validate created config, uses ArgumentParser options in messages /// Validate created config, uses ArgumentParser options in messages
/// @throws std::invalid_argument if config is not valid /// @throws std::invalid_argument if config is not valid
void ValidateConfig() const; void ValidateConfig() const;
/// place to store argv[0]
std::filesystem::path m_AppName;
/// Internal argument parser /// Internal argument parser
argparse::ArgumentParser m_ArgParser; argparse::ArgumentParser m_ArgParser;

View File

@ -70,7 +70,7 @@ namespace MWR::C3::Linter
ChannelLinter::ChannelLinter(AppConfig config) : ChannelLinter::ChannelLinter(AppConfig config) :
m_Config(std::move(config)), m_Config(std::move(config)),
m_ChannelData(GetChannelInfo(m_Config.m_ChannelName)), m_ChannelData(GetChannelInfo(*m_Config.m_ChannelName)),
m_ChannelCapability(GetChannelCapability(m_ChannelData)), m_ChannelCapability(GetChannelCapability(m_ChannelData)),
m_CreateForm{ [this] m_CreateForm{ [this]
{ {

View File

@ -11,9 +11,26 @@ try
using namespace MWR; using namespace MWR;
C3::Linter::ArgumentParser argParser(argc, argv); C3::Linter::ArgumentParser argParser(argc, argv);
auto const& config = argParser.GetConfig(); auto const& config = argParser.GetConfig();
std::cout << "Channel: " << config.m_ChannelName << std::endl; if (config.m_ShowHelp)
{
std::cout << argParser.GetUsage() << std::endl;
return 0;
}
if (config.m_ListChannels)
{
auto const& channels = C3::InterfaceFactory::Instance().GetMap<C3::AbstractChannel>();
std::cout << "Registered channels: \n";
for (auto [hash, channelData] : channels)
std::cout << channelData.m_Name << '\n';
std::cout << std::flush;
return 0;
}
assert(config.m_ChannelName);
std::cout << "Channel: " << *config.m_ChannelName << std::endl;
auto channelLinter = C3::Linter::ChannelLinter(config); auto channelLinter = C3::Linter::ChannelLinter(config);
std::cout << config.m_ChannelName << "'s Capability json verified OK." << std::endl; std::cout << *config.m_ChannelName << "'s Capability json verified OK." << std::endl;
channelLinter.Process(); channelLinter.Process();
return 0; return 0;

View File

@ -1,11 +1,39 @@
# C3 Channel Linter # C3 Channel Linter
Standalone tool to ease the development and debugging of channels. Tool to ease the development and debugging of channels.
Main goal is to provide a simple application to test channels without the need of spinning up the whole C3 network.
## Usage ## Usage
This tool provides console frontend for channel usage This tool provides console frontend for channel usage.
```
Usage: ChannelLinter.exe {-h|-l|-n NAME [options]}
Mode:
-h, --help Show this message and exit.
-l, --list List registered Channels and exit.
-n <NAME>, --name <NAME>
Select channel with given <NAME> for further processing
Options:
-a [ARGS...], --args [ARGS...]
Create channel with given ARGS using the Capability/create/arguments.
-c [ARGS...], --complementary [ARGS...]
Create a complementary channel with given ARGS.
-i, --test-io Create a pair of channels and send packets through.
If this option is present -a [ARGS...] must be specified.
If -c is not present, complementary channel arguments are deduced by swapping
parameters from Capability/create/arguments arrays.
-x <ID> [ARGS... ], --command <ID> [ARGS... ]
Execute a command with a given <ID> and arguments [ARGS...]
```
Example workflows:
1. Parse the json returned from `GetCapability()` and validate it against C3 rules: 1. Parse the json returned from `GetCapability()` and validate it against C3 rules:
`-n ChannelName` `-n ChannelName`
`--name ChannelName` `--name ChannelName`
@ -16,7 +44,7 @@ This tool provides console frontend for channel usage
`--args [Argument1 Argument2 ...]` `--args [Argument1 Argument2 ...]`
e.g. `ChannelLinter.exe -n UncShareFile --args inputId outputId C:\Temp\C3Store false` e.g. `ChannelLinter.exe -n UncShareFile --args inputId outputId C:\Temp\C3Store false`
Note: Messeges logged by calls to `this->Log()` will not be displayed if the channel constructor throws. Note: Messeges logged by calls to `this->Log()` will not be displayed if the channel constructor throws.
3. Test channel permeability - create a complemetary pair of channels and send message through. 3. Test channel permeability - create a complemetary pair of channels and send messages through.
`-i` `-i`
`--test-io` `--test-io`
e.g. `ChannelLinter.exe -n UncShareFile --args inputId outputId C:\Temp\C3Store false -i` e.g. `ChannelLinter.exe -n UncShareFile --args inputId outputId C:\Temp\C3Store false -i`