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 {
|
const EXAMPLES: Actions = Actions {
|
||||||
actions: &[
|
actions: &[
|
||||||
Action::Setup(Setup {
|
Action::setup().command(&[
|
||||||
command: &[
|
"sq", "pki", "link", "add",
|
||||||
"sq", "pki", "link", "add",
|
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||||
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
"--userid=Alice <alice@example.org>",
|
||||||
"--userid=Alice <alice@example.org>",
|
]).build(),
|
||||||
],
|
|
||||||
}),
|
|
||||||
|
|
||||||
Action::Setup(Setup {
|
Action::setup().command(&[
|
||||||
command: &[
|
"sq", "pki", "link", "add",
|
||||||
"sq", "pki", "link", "add",
|
"--cert=511257EBBF077B7AEDAE5D093F68CB84CE537C9A",
|
||||||
"--cert=511257EBBF077B7AEDAE5D093F68CB84CE537C9A",
|
"--userid=Bob <bob@example.org>",
|
||||||
"--userid=Bob <bob@example.org>",
|
]).build(),
|
||||||
],
|
|
||||||
}),
|
|
||||||
|
|
||||||
Action::Example(Example {
|
Action::example().comment(
|
||||||
comment: "Export all certificates.",
|
"Export certificates with a User ID containing the \
|
||||||
command: &[
|
email address."
|
||||||
"sq", "cert", "export", "--all",
|
).command(&[
|
||||||
],
|
"sq", "cert", "export", "--cert-email=alice@example.org",
|
||||||
}),
|
]).build(),
|
||||||
Action::Example(Example {
|
|
||||||
comment: "\
|
Action::example().comment(
|
||||||
Export certificates with a matching User ID packet. The binding \
|
"Export certificates that contain a User ID with *either* \
|
||||||
signatures are checked, and the User IDs are authenticated. \
|
(not both!) email address."
|
||||||
Note: this check is case sensitive.",
|
).command(&[
|
||||||
command: &[
|
"sq", "cert", "export",
|
||||||
"sq", "cert", "export",
|
"--cert-email=alice@example.org",
|
||||||
"--cert-userid", "Alice <alice@example.org>",
|
"--cert-email=bob@example.org",
|
||||||
],
|
]).build(),
|
||||||
}),
|
|
||||||
Action::Example(Example {
|
Action::example().comment(
|
||||||
comment: "\
|
"Export all certificates."
|
||||||
Export certificates with a User ID containing the email address. \
|
).command(&[
|
||||||
The binding signatures are checked, and the User IDs are \
|
"sq", "cert", "export", "--all",
|
||||||
authenticated. Note: this check is case insensitive.",
|
]).build(),
|
||||||
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",
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,6 +14,37 @@ pub struct Setup<'a> {
|
|||||||
pub command: &'a [ &'a str ],
|
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
|
/// A command that is executed by the integration test, and shown in
|
||||||
/// the manual pages.
|
/// the manual pages.
|
||||||
pub struct Example<'a> {
|
pub struct Example<'a> {
|
||||||
@ -22,6 +53,61 @@ pub struct Example<'a> {
|
|||||||
pub command: &'a [ &'a str ],
|
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.
|
/// An action to execute.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum Action<'a> {
|
pub enum Action<'a> {
|
||||||
@ -39,6 +125,16 @@ pub enum Action<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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.
|
/// Return the action's command, if any.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn command(&self) -> Option<&'a [ &'a str ]> {
|
pub fn command(&self) -> Option<&'a [ &'a str ]> {
|
||||||
|
Loading…
Reference in New Issue
Block a user