dynamic_cli/plugin/builtin/
sysinfo.rs1use crate::context::ExecutionContext;
14use crate::executor::CommandHandler;
15use crate::parser::ParsedArgs;
16use crate::plugin::Plugin;
17use crate::Result;
18
19pub struct SysInfoPlugin;
50
51impl SysInfoPlugin {
52 pub fn new() -> Self {
63 Self
64 }
65}
66
67impl Default for SysInfoPlugin {
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl Plugin for SysInfoPlugin {
74 fn name(&self) -> &str {
75 "sysinfo"
76 }
77
78 fn version(&self) -> &str {
79 env!("CARGO_PKG_VERSION")
80 }
81
82 fn description(&self) -> &str {
83 "Runtime/OS introspection (std-only baseline, feature-gated, #45)"
84 }
85
86 fn handlers(&self) -> Vec<(String, Box<dyn CommandHandler>)> {
87 vec![("sysinfo_show".to_string(), Box::new(SysInfoShowHandler))]
88 }
89}
90
91struct SysInfoShowHandler;
94
95impl CommandHandler for SysInfoShowHandler {
96 fn execute(&self, _ctx: &mut dyn ExecutionContext, _args: &ParsedArgs) -> Result<()> {
97 let parallelism = std::thread::available_parallelism()
98 .map(|n| n.get())
99 .unwrap_or(1);
100
101 println!("OS: {}", std::env::consts::OS);
102 println!("Architecture: {}", std::env::consts::ARCH);
103 println!("Available parallelism: {}", parallelism);
104
105 Ok(())
106 }
107}
108
109#[cfg(test)]
114mod tests {
115 use super::*;
116 use std::any::Any;
117
118 #[derive(Default)]
119 struct TestContext;
120
121 impl ExecutionContext for TestContext {
122 fn as_any(&self) -> &dyn Any {
123 self
124 }
125 fn as_any_mut(&mut self) -> &mut dyn Any {
126 self
127 }
128 }
129
130 #[test]
131 fn test_sysinfo_plugin_metadata() {
132 let p = SysInfoPlugin::new();
133 assert_eq!(p.name(), "sysinfo");
134 assert!(!p.version().is_empty());
135 assert!(!p.description().is_empty());
136 }
137
138 #[test]
139 fn test_sysinfo_plugin_default() {
140 let p = SysInfoPlugin::default();
141 assert_eq!(p.name(), "sysinfo");
142 }
143
144 #[test]
145 fn test_sysinfo_plugin_handler_name() {
146 let handlers = SysInfoPlugin::new().handlers();
147 assert_eq!(handlers.len(), 1);
148 assert_eq!(handlers[0].0, "sysinfo_show");
149 }
150
151 #[test]
152 fn test_sysinfo_handler_executes() {
153 let handlers = SysInfoPlugin::new().handlers();
154 let (_, handler) = &handlers[0];
155 let mut ctx = TestContext;
156 assert!(handler
157 .execute(&mut ctx, &ParsedArgs::from_scalars(Default::default()))
158 .is_ok());
159 }
160
161 #[test]
162 fn test_sysinfo_plugin_is_send_sync() {
163 fn assert_send_sync<T: Send + Sync>(_: T) {}
164 assert_send_sync(SysInfoPlugin::new());
165 }
166}