Add a builder-style interface to the example framework.
- Also, port the examples for `sq cert export` over, and thin them out a little (see #451).
This commit is contained in:
parent
797ab7a003
commit
356781e535
@ -9,65 +9,39 @@ use crate::cli::examples::*;
|
||||
|
||||
const EXAMPLES: Actions = Actions {
|
||||
actions: &[
|
||||
Action::Setup(Setup {
|
||||
command: &[
|
||||
"sq", "pki", "link", "add",
|
||||
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--userid=Alice <alice@example.org>",
|
||||
],
|
||||
}),
|
||||
Action::setup().command(&[
|
||||
"sq", "pki", "link", "add",
|
||||
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--userid=Alice <alice@example.org>",
|
||||
]).build(),
|
||||
|
||||
Action::Setup(Setup {
|
||||
command: &[
|
||||
"sq", "pki", "link", "add",
|
||||
"--cert=511257EBBF077B7AEDAE5D093F68CB84CE537C9A",
|
||||
"--userid=Bob <bob@example.org>",
|
||||
],
|
||||
}),
|
||||
Action::setup().command(&[
|
||||
"sq", "pki", "link", "add",
|
||||
"--cert=511257EBBF077B7AEDAE5D093F68CB84CE537C9A",
|
||||
"--userid=Bob <bob@example.org>",
|
||||
]).build(),
|
||||
|
||||
Action::Example(Example {
|
||||
comment: "Export all certificates.",
|
||||
command: &[
|
||||
"sq", "cert", "export", "--all",
|
||||
],
|
||||
}),
|
||||
Action::Example(Example {
|
||||
comment: "\
|
||||
Export certificates with a matching User ID packet. The binding \
|
||||
signatures are checked, and the User IDs are authenticated. \
|
||||
Note: this check is case sensitive.",
|
||||
command: &[
|
||||
"sq", "cert", "export",
|
||||
"--cert-userid", "Alice <alice@example.org>",
|
||||
],
|
||||
}),
|
||||
Action::Example(Example {
|
||||
comment: "\
|
||||
Export certificates with a User ID containing the email address. \
|
||||
The binding signatures are checked, and the User IDs are \
|
||||
authenticated. Note: this check is case insensitive.",
|
||||
command: &[
|
||||
"sq", "cert", "export", "--cert-email", "alice@example.org",
|
||||
],
|
||||
}),
|
||||
Action::Example(Example {
|
||||
comment: "\
|
||||
Export certificates where a certificate's primary key or a subkey \
|
||||
has the specified Key ID.",
|
||||
command: &[
|
||||
"sq", "cert", "export", "--cert", "6F0073F60FD0CBF0",
|
||||
],
|
||||
}),
|
||||
Action::Example(Example {
|
||||
comment: "\
|
||||
Export certificates that contain a User ID with *either* (not both!) \
|
||||
email address. Note: this check is case insensitive.",
|
||||
command: &[
|
||||
"sq", "cert", "export",
|
||||
"--cert-email", "alice@example.org",
|
||||
"--cert-email", "bob@example.org",
|
||||
],
|
||||
}),
|
||||
Action::example().comment(
|
||||
"Export certificates with a User ID containing the \
|
||||
email address."
|
||||
).command(&[
|
||||
"sq", "cert", "export", "--cert-email=alice@example.org",
|
||||
]).build(),
|
||||
|
||||
Action::example().comment(
|
||||
"Export certificates that contain a User ID with *either* \
|
||||
(not both!) email address."
|
||||
).command(&[
|
||||
"sq", "cert", "export",
|
||||
"--cert-email=alice@example.org",
|
||||
"--cert-email=bob@example.org",
|
||||
]).build(),
|
||||
|
||||
Action::example().comment(
|
||||
"Export all certificates."
|
||||
).command(&[
|
||||
"sq", "cert", "export", "--all",
|
||||
]).build(),
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -14,6 +14,37 @@ pub struct Setup<'a> {
|
||||
pub command: &'a [ &'a str ],
|
||||
}
|
||||
|
||||
/// Builds up setup actions in an extensible way.
|
||||
pub struct SetupBuilder<'a> {
|
||||
setup: Setup<'a>,
|
||||
}
|
||||
|
||||
impl<'a> SetupBuilder<'a> {
|
||||
/// Returns a new setup builder.
|
||||
const fn new() -> Self {
|
||||
SetupBuilder {
|
||||
setup: Setup {
|
||||
command: &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the command as slice.
|
||||
///
|
||||
/// It'd be nice to provide a per-argument interface, but that
|
||||
/// requires some ingenuity for it to stay const.
|
||||
pub const fn command(mut self, command: &'a [&'a str]) -> Self {
|
||||
self.setup.command = command;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes building the setup action.
|
||||
pub const fn build(self) -> Action<'a> {
|
||||
assert!(! self.setup.command.is_empty());
|
||||
Action::Setup(self.setup)
|
||||
}
|
||||
}
|
||||
|
||||
/// A command that is executed by the integration test, and shown in
|
||||
/// the manual pages.
|
||||
pub struct Example<'a> {
|
||||
@ -22,6 +53,61 @@ pub struct Example<'a> {
|
||||
pub command: &'a [ &'a str ],
|
||||
}
|
||||
|
||||
/// Builds up example actions in an extensible way.
|
||||
pub struct ExampleBuilder<'a> {
|
||||
example: Example<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ExampleBuilder<'a> {
|
||||
/// Returns a new example builder.
|
||||
const fn new() -> Self {
|
||||
ExampleBuilder {
|
||||
example: Example {
|
||||
comment: "",
|
||||
command: &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the comment.
|
||||
///
|
||||
/// It'd be nice to provide a per-argument interface, but that
|
||||
/// requires some ingenuity for it to stay const.
|
||||
pub const fn comment(mut self, comment: &'a str) -> Self {
|
||||
self.example.comment = comment;
|
||||
self
|
||||
}
|
||||
|
||||
/// Provides the command as slice.
|
||||
///
|
||||
/// It'd be nice to provide a per-argument interface, but that
|
||||
/// requires some ingenuity for it to stay const.
|
||||
pub const fn command(mut self, command: &'a [&'a str]) -> Self {
|
||||
self.example.command = command;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes building the example action.
|
||||
///
|
||||
/// The example will be executed by the test.
|
||||
pub const fn build(self) -> Action<'a> {
|
||||
assert!(! self.example.comment.is_empty());
|
||||
assert!(! self.example.command.is_empty());
|
||||
Action::Example(self.example)
|
||||
}
|
||||
|
||||
/// Finishes building the example action, marking it for syntax
|
||||
/// checking only.
|
||||
///
|
||||
/// The example will not be executed by the test, but the syntax
|
||||
/// will be checked using our command line parser.
|
||||
pub const fn syntax_check(self) -> Action<'a> {
|
||||
assert!(! self.example.comment.is_empty());
|
||||
assert!(! self.example.command.is_empty());
|
||||
Action::SyntaxCheck(self.example)
|
||||
}
|
||||
}
|
||||
|
||||
/// An action to execute.
|
||||
#[allow(dead_code)]
|
||||
pub enum Action<'a> {
|
||||
@ -39,6 +125,16 @@ pub enum Action<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Action<'a> {
|
||||
/// Creates a setup action.
|
||||
pub const fn setup() -> SetupBuilder<'a> {
|
||||
SetupBuilder::new()
|
||||
}
|
||||
|
||||
/// Creates an example action.
|
||||
pub const fn example() -> ExampleBuilder<'a> {
|
||||
ExampleBuilder::new()
|
||||
}
|
||||
|
||||
/// Return the action's command, if any.
|
||||
#[allow(dead_code)]
|
||||
pub fn command(&self) -> Option<&'a [ &'a str ]> {
|
||||
|
Loading…
Reference in New Issue
Block a user