1use crate::opts::{Anvil, AnvilSubcommand};
2use clap::CommandFactory;
3use eyre::Result;
4use foundry_cli::utils;
5
6pub fn run() -> Result<()> {
8 foundry_cli::machine::check_machine();
11 foundry_cli::opts::GlobalArgs::check_introspect::<Anvil>();
12 foundry_cli::opts::GlobalArgs::check_markdown_help::<Anvil>();
13
14 setup()?;
15
16 let mut args = foundry_cli::parse_or_exit::<Anvil>();
17 args.global.init()?;
18 args.node.evm.resolve_rpc_alias();
19
20 run_command(args)
21}
22
23pub fn setup() -> Result<()> {
25 utils::common_setup();
26
27 Ok(())
28}
29
30pub fn run_command(args: Anvil) -> Result<()> {
32 if let Some(cmd) = &args.cmd {
33 match cmd {
34 AnvilSubcommand::Completions { shell } => {
35 clap_complete::generate(
36 *shell,
37 &mut Anvil::command(),
38 "anvil",
39 &mut std::io::stdout(),
40 );
41 }
42 }
43 return Ok(());
44 }
45
46 let _ = fdlimit::raise_fd_limit();
47 args.global.tokio_runtime().block_on(args.node.run())
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use clap::Parser;
54
55 #[test]
56 fn verify_cli() {
57 Anvil::command().debug_assert();
58 }
59
60 #[test]
61 fn can_parse_help() {
62 let _: Anvil = Anvil::parse_from(["anvil", "--help"]);
63 }
64
65 #[test]
66 fn can_parse_short_version() {
67 let _: Anvil = Anvil::parse_from(["anvil", "-V"]);
68 }
69
70 #[test]
71 fn can_parse_long_version() {
72 let _: Anvil = Anvil::parse_from(["anvil", "--version"]);
73 }
74
75 #[test]
76 fn can_parse_completions() {
77 let args: Anvil = Anvil::parse_from(["anvil", "completions", "bash"]);
78 assert!(matches!(
79 args.cmd,
80 Some(AnvilSubcommand::Completions {
81 shell: foundry_cli::clap::Shell::ClapCompleteShell(clap_complete::Shell::Bash)
82 })
83 ));
84 }
85
86 #[test]
88 fn introspect_command_ids_are_unique() {
89 use foundry_cli::introspect::{CommandRegistry, build_document, duplicate_command_ids};
90 let cmd = Anvil::command();
91 let doc = build_document(&cmd, &CommandRegistry::EMPTY);
92 let dups = duplicate_command_ids(&doc);
93 assert!(dups.is_empty(), "duplicate anvil command_ids: {dups:?}");
94 }
95
96 #[test]
99 fn introspect_document_is_valid_json() {
100 use foundry_cli::introspect::{
101 CommandRegistry, INTROSPECT_SCHEMA_ID, IntrospectDocument, render_introspect_document,
102 };
103 let cmd = Anvil::command();
104 let json = render_introspect_document(&cmd, &CommandRegistry::EMPTY);
105 let doc: IntrospectDocument = serde_json::from_str(&json).expect("valid JSON");
106 assert_eq!(doc.schema_id, INTROSPECT_SCHEMA_ID);
107 assert_eq!(doc.binary.name, "anvil");
108 }
109
110 #[test]
112 fn introspect_capabilities_are_consistent() {
113 use foundry_cli::introspect::{CommandRegistry, build_document, capability_violations};
114 let cmd = Anvil::command();
115 let doc = build_document(&cmd, &CommandRegistry::EMPTY);
116 let v = capability_violations(&doc);
117 assert!(v.is_empty(), "anvil capability violations: {v:?}");
118 }
119}