├── .gitignore ├── LICENSE ├── Cargo.toml ├── .github └── workflows │ └── rust.yml ├── README.md ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Michael Diamond 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "task-mon" 3 | version = "0.3.2" 4 | authors = ["Michael Diamond "] 5 | description = "CLI to execute commands and log results to healthchecks.io" 6 | repository = "https://github.com/dimo414/task-mon" 7 | license = "MIT" 8 | keywords = ["cron", "healthcheck", "healthchecks", "heartbeat", "monitoring"] 9 | categories = ["command-line-utilities", "development-tools::debugging"] 10 | edition = "2024" 11 | include = [ 12 | "**/*.rs", 13 | "Cargo.*", 14 | "README.md", 15 | "LICENSE", 16 | ] 17 | 18 | [features] 19 | # If compiling on a system without OpenSSL installed, or cross-compiling for a different 20 | # architecture, enable this feature to compile OpenSSL as part of the build. 21 | # See https://docs.rs/openssl/#vendored 22 | static_ssl = ['openssl/vendored'] 23 | 24 | [dependencies] 25 | clap = { version = "~3.0", default-features = false, features = ["std", "derive", "env", "cargo"] } 26 | clap_derive = "~3.0" 27 | hostname = "0.3" 28 | subprocess = "0.2" 29 | ureq = "2.0" 30 | uuid = { version = "1.17", features = ["v4"] } 31 | 32 | [dependencies.openssl] 33 | optional = true 34 | version = '0.10' 35 | 36 | [dev-dependencies] 37 | mockito = "0.29.0" 38 | parameterized_test = "0.2" 39 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: [push] 4 | 5 | # See https://github.com/sharkdp/bat/blob/master/.github/workflows/CICD.yml for a more intricate CI/CD 6 | jobs: 7 | CI: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v1 11 | - uses: actions-rs/clippy-check@v1 12 | with: 13 | token: ${{ secrets.GITHUB_TOKEN }} 14 | args: --all-targets --all-features 15 | - name: Check 16 | run: cargo check --all-targets --verbose 17 | - name: Run tests 18 | run: cargo test --verbose 19 | 20 | CD: 21 | runs-on: ubuntu-latest 22 | needs: CI 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | arch: 27 | - { target: aarch64-unknown-linux-gnu , use-cross: true } 28 | - { target: arm-unknown-linux-gnueabihf , use-cross: true } 29 | - { target: i686-unknown-linux-gnu , use-cross: true } 30 | - { target: x86_64-unknown-linux-gnu } 31 | steps: 32 | - uses: actions/checkout@v2 33 | - name: Extract crate information 34 | shell: bash 35 | run: | 36 | echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml)" >> "$GITHUB_ENV" 37 | echo "PROJECT_VERSION=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> "$GITHUB_ENV" 38 | - name: Build 39 | uses: actions-rs/cargo@v1 40 | with: 41 | use-cross: ${{ matrix.arch.use-cross }} 42 | command: build 43 | args: --release --target=${{ matrix.arch.target }} 44 | 45 | - name: Upload package artifact 46 | uses: actions/upload-artifact@master 47 | with: 48 | name: '${{ env.PROJECT_NAME }}.v${{ env.PROJECT_VERSION }}.${{ matrix.arch.target }}' 49 | path: 'target/${{ matrix.arch.target }}/release/${{ env.PROJECT_NAME }}' 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Task Monitoring with Healthchecks.io 2 | 3 | [![github](https://img.shields.io/badge/github-dimo414/task--mon-green?logo=github)](https://github.com/dimo414/task-mon) 4 | [![crates.io](https://img.shields.io/crates/v/task-mon.svg?logo=rust)](https://crates.io/crates/task-mon) 5 | [![build status](https://img.shields.io/github/actions/workflow/status/dimo414/task-mon/rust.yml?branch=master)](https://github.com/dimo414/task-mon/actions) 6 | [![dependencies](https://img.shields.io/deps-rs/task-mon/latest)](https://deps.rs/crate/task-mon) 7 | [![issues](https://img.shields.io/github/issues/dimo414/task-mon)](https://github.com/dimo414/task-mon/issues) 8 | [![license](https://img.shields.io/github/license/dimo414/task-mon)](https://github.com/dimo414/task-mon/blob/master/LICENSE) 9 | 10 | 11 | `task-mon` is a small binary for notifying Healthchecks.io when a command runs. 12 | 13 | This serves a similar purpose to the `curl`-based patterns described in the Healthchecks 14 | documentation but provides more flexibility and ergonomics. Especially for shell scripts and 15 | [cron jobs](https://healthchecks.io/docs/monitoring_cron_jobs/), delegating health management to a 16 | separate binary allows you to focus on the task at hand. 17 | 18 | It supports Healthchecks' advanced optional features such as 19 | [reporting failures](https://healthchecks.io/docs/signaling_failures/), 20 | [attaching logs](https://healthchecks.io/docs/attaching_logs/), and 21 | [monitoring execution time](https://healthchecks.io/docs/measuring_script_run_time/). 22 | 23 | ## Usage 24 | 25 | To execute a task and ping Healthchecks.io when it completes simply invoke `task-mon` with the 26 | check's UUID and the command to run: 27 | 28 | ```shell 29 | $ task-mon --uuid 1234-abcd -- some_command --to --monitor 30 | ``` 31 | 32 | ```shell 33 | $ task-mon --ping-key abcd1234 --slug foo -- some_command --to --monitor 34 | ``` 35 | 36 | ```shell 37 | $ crontab -e 38 | # m h dom mon dow command 39 | 8 6 * * * /usr/local/cargo/bin/task-mon --uuid 1234-abcd -- /path/to/some_command --to --monitor 40 | ``` 41 | 42 | `task-mon` will run the command and ping Healthchecks.io when it completes, reporting the exit 43 | status and the last 10K of output from the process. 44 | 45 | ### Customization 46 | 47 | ```shell 48 | $ task-mon --help 49 | task-mon 0.3.2 50 | CLI to execute commands and log results to healthchecks.io 51 | 52 | USAGE: 53 | task-mon [OPTIONS] <--uuid |--slug > [--] ... 54 | 55 | ARGS: 56 | ... The command to run 57 | 58 | OPTIONS: 59 | -k, --uuid Check's UUID to ping 60 | -s, --slug Check's slug name to ping, requires also specifying --ping-key 61 | --ping-key Check's project ping key, required when using --slug [env: 62 | HEALTHCHECKS_PING_KEY=] 63 | -t, --time Ping when the program starts as well as completes 64 | --head POST the first 10k bytes instead of the last 65 | --ping-only Don't POST any output from the command 66 | --log Log the invocation without signaling success or failure; does 67 | not update the check's status 68 | --detailed Include execution details in the information POST-ed (by 69 | default just sends stdout/err) 70 | --env Also POSTs the process environment; requires --detailed 71 | --verbose Write debugging details to stderr 72 | --user-agent Customize the user-agent string sent to the Healthchecks.io 73 | server [env: HEALTHCHECKS_USER_AGENT=] 74 | --base-url Base URL of the Healthchecks.io server to ping [env: 75 | HEALTHCHECKS_BASE_URL=] [default: https://hc-ping.com] 76 | -h, --help Print help information 77 | -V, --version Print version information 78 | ``` 79 | 80 | ## Related projects 81 | 82 | There are, unsurprisingly, a number of similar projects out there, but I thought it'd be a fun opportunity to write a little 83 | Rust. And of course I like my API best :) 84 | 85 | * [Runitor](https://github.com/bdd/runitor) - linked from the 86 | [Healthchecks docs](https://healthchecks.io/docs/attaching_logs/) 87 | * [healthchecks-rs](https://github.com/msfjarvis/healthchecks-rs) - Rust library and CLI for pinging and 88 | monitoring Healthchecks 89 | * [hchk](https://github.com/healthchecks/hchk) - older CLI written by the Healthchecks.io maintainer 90 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate clap; 2 | 3 | #[cfg(test)] extern crate parameterized_test; 4 | 5 | use clap::{AppSettings, ArgGroup, Parser}; 6 | use std::borrow::Cow; 7 | use std::convert::TryFrom; 8 | use std::ffi::{OsStr, OsString}; 9 | use std::time::{Duration, Instant}; 10 | use subprocess::{Exec, Redirection, ExitStatus, CaptureData, PopenConfig}; 11 | use ureq::{Agent, AgentBuilder, Error, Response}; 12 | use uuid::Uuid; 13 | 14 | static MAX_BYTES_TO_POST: usize = 10000; // not 10KB, https://healthchecks.io/docs/attaching_logs/ 15 | static MAX_STRING_TO_LOG: usize = 1000; 16 | 17 | /// Truncates a string for display 18 | fn truncate_str(s: String, max_len: usize) -> String { 19 | if s.len() > max_len { 20 | format!("{}...", s.chars().take(max_len-3).collect::()) 21 | } else { s } 22 | } 23 | 24 | /// Constructs a User Agent string including the hostname and binary name. 25 | fn make_user_agent(custom: Option<&str>) -> String { 26 | let base = match hostname::get().ok() { 27 | Some(host) => format!("{} - {}", crate_name!(), host.to_string_lossy()), 28 | None => crate_name!().to_string(), 29 | }; 30 | 31 | match custom { 32 | Some(agent) => format!("{} ({})", agent, base), 33 | None => base, 34 | } 35 | } 36 | 37 | /// Executes a subprocess, distilling all situations (failures, etc.) to a string of output and an 38 | /// exit code. This is obviously lossy, but is sufficient for our purposes. Setting verbose=true 39 | /// will log lost details to stderr. 40 | fn execute(command: &[impl AsRef], capture_output: bool, verbose: bool) -> (String, u8, Duration) { 41 | let command = Exec::cmd(&command[0]).args(&command[1..]) 42 | .stdout(Redirection::Pipe) 43 | .stderr(Redirection::Merge); 44 | if verbose { eprintln!("About to run: {:?}", command); } 45 | 46 | let start = Instant::now(); 47 | // TODO consider discarding stdout instead of capturing it if !capture_output; 48 | // subprocess::Communicator::limit_size() can avoid unbounded memory allocation 49 | let capture = command.capture(); 50 | let elapsed = start.elapsed(); 51 | 52 | if verbose { 53 | match &capture { 54 | Ok(cap) => 55 | eprintln!("stdout+stderr:[{}] exit:{:?} runtime:{:?}", 56 | truncate_str(cap.stdout_str(), MAX_STRING_TO_LOG), 57 | cap.exit_status, 58 | elapsed), 59 | Err(e) => eprintln!("Failed! {:?} runtime:{:?}", e, elapsed), 60 | }; 61 | } 62 | 63 | let capture = match capture { 64 | Ok(cap) => cap, 65 | Err(e) => CaptureData { 66 | stdout: format!("{}: Command failed: {}", crate_name!(), e).bytes().collect(), 67 | stderr: Vec::new(), 68 | exit_status: ExitStatus::Undetermined, 69 | }, 70 | }; 71 | assert!(capture.stderr.is_empty(), "No data should have been written to stderr"); 72 | 73 | let code = match capture.exit_status { 74 | ExitStatus::Exited(code) => u8::try_from(code).unwrap_or(127), 75 | ExitStatus::Signaled(signal) => signal + 128, 76 | _ => 127, 77 | }; 78 | (if capture_output { capture.stdout_str() } else { String::new() }, code, elapsed) 79 | } 80 | 81 | struct HCAgent { 82 | agent: Agent, 83 | verbose: bool, 84 | url_prefix: String, 85 | } 86 | 87 | impl HCAgent { 88 | fn create(cli: &Cli) -> Self { 89 | // TODO support retries 90 | // TODO could potentially shrink the binary size further by manually constructing requests with 91 | // https://doc.rust-lang.org/std/net/struct.TcpStream.html and https://docs.rs/native-tls/ 92 | let agent = AgentBuilder::new() 93 | .timeout(Duration::from_secs(10)) // https://healthchecks.io/docs/reliability_tips/ 94 | .user_agent(&make_user_agent(cli.user_agent.as_deref())) 95 | .build(); 96 | 97 | HCAgent { agent, verbose: cli.verbose, url_prefix: cli.url_prefix() } 98 | } 99 | 100 | /// Pings the Healthchecks server to notify that the task denoted by the URL prefix is starting 101 | /// A run_id UUID is used to associate this event with its completion notification 102 | fn notify_start(&self, run_id: Uuid) -> Result { 103 | let url = format!("{}/start?rid={}", self.url_prefix, run_id); 104 | let req = self.agent.get(&url); 105 | if self.verbose { eprintln!("Sending request: {:?}", req); } 106 | req.call() 107 | } 108 | 109 | /// Pings the Healthchecks server to notify that the task denoted by the URL prefix is done. 110 | /// A run_id UUID is used to associated this event with its start notification, if one was sent 111 | /// If code is non-zero, the task will be considered failed. If code is None the task will be logged 112 | /// but not update the check. 113 | fn notify_complete(&self, run_id: Option, code: Option, output: &str) -> Result { 114 | let mut url = format!("{}/{}", self.url_prefix, code.map(|x| x.to_string()).unwrap_or_else(|| "log".to_string())); 115 | if let Some(run_id) = run_id { 116 | url = format!("{}?rid={}", url, run_id); 117 | } 118 | let req = self.agent.post(&url); 119 | if self.verbose { eprintln!("Sending request: {:?}", req); } 120 | if output.is_empty() { 121 | req.call() 122 | } else { 123 | req.send_string(output) 124 | } 125 | } 126 | } 127 | 128 | #[derive(Parser)] 129 | #[clap(about, version)] 130 | #[clap(setting = AppSettings::DeriveDisplayOrder)] 131 | #[clap(setting = AppSettings::ArgRequiredElseHelp)] 132 | #[clap(group(ArgGroup::new("label").required(true)))] 133 | struct Cli { 134 | /// Check's UUID to ping 135 | #[clap(long, short='k', value_name="UUID", group="label")] 136 | uuid: Option, 137 | 138 | /// Check's slug name to ping, requires also specifying --ping-key 139 | #[clap(long, short='s', value_name="SLUG", group="label", requires="ping-key")] 140 | slug: Option, 141 | 142 | /// Check's project ping key, required when using --slug 143 | #[clap(long, env="HEALTHCHECKS_PING_KEY", value_name="PING_KEY")] 144 | ping_key: Option, 145 | 146 | /// Ping when the program starts as well as completes 147 | #[clap(long, short='t')] 148 | time: bool, 149 | 150 | /// POST the first 10k bytes instead of the last 151 | #[clap(long)] 152 | head: bool, 153 | 154 | /// Don't POST any output from the command 155 | #[clap(long, conflicts_with_all=&["detailed", "env"])] 156 | ping_only: bool, 157 | 158 | /// Log the invocation without signaling success or failure; does not update the check's status 159 | #[clap(long, conflicts_with="time")] 160 | log: bool, 161 | 162 | /// Include execution details in the information POST-ed (by default just sends stdout/err) 163 | #[clap(long)] 164 | detailed: bool, 165 | 166 | /// Also POSTs the process environment; requires --detailed 167 | #[clap(long, requires="detailed")] 168 | env: bool, 169 | 170 | /// Write debugging details to stderr 171 | #[clap(long)] 172 | verbose: bool, 173 | 174 | /// Customize the user-agent string sent to the Healthchecks.io server 175 | #[clap(long, env="HEALTHCHECKS_USER_AGENT", value_name="USER_AGENT")] 176 | user_agent: Option, 177 | 178 | /// Base URL of the Healthchecks.io server to ping 179 | #[clap(long, env="HEALTHCHECKS_BASE_URL", default_value="https://hc-ping.com")] 180 | base_url: String, 181 | 182 | /// The command to run 183 | #[clap(required=true, last=true)] 184 | command: Vec, 185 | } 186 | 187 | impl Cli { 188 | fn url_prefix(&self) -> String { 189 | match &self.uuid { 190 | Some(uuid) => format!("{}/{}", self.base_url, uuid), 191 | None => { 192 | // These expect()s should never be hit in practice because clap enforces either 193 | // --uuid or --ping_key+--slug. 194 | let slug = self.slug.as_ref().expect("BUG: Must provide --uuid or --slug"); 195 | let ping_key = self.ping_key.as_ref().expect("BUG: Must provide --ping_key with --slug"); 196 | format!("{}/{}/{}", self.base_url, ping_key, slug) 197 | } 198 | } 199 | } 200 | } 201 | 202 | fn run(cli: Cli, agent: HCAgent) -> Result { 203 | let mut maybe_run_id = None; // Don't bother reporting a run ID unless we're sending a start ping 204 | if cli.time { 205 | let run_id = Uuid::new_v4(); 206 | maybe_run_id = Some(run_id); 207 | if let Err(e) = agent.notify_start(run_id) { 208 | eprintln!("Failed to send start request: {:?}", e); 209 | } 210 | } 211 | let (mut output, code, elapsed) = execute(&cli.command, !cli.ping_only, cli.verbose); 212 | 213 | if cli.detailed { 214 | // We could properly escape command, e.g. with https://crates.io/crates/shell-quote 215 | output = format!("$ {} 2>&1\n{}\n\nExit Code: {}\nDuration: {:?}", 216 | cli.command.join(OsStr::new(" ")).to_string_lossy(), output, code, elapsed); 217 | if cli.env { 218 | let env_str = PopenConfig::current_env().iter() 219 | .map(|(k, v)| format!("{}={}", k.to_string_lossy(), v.to_string_lossy())) 220 | .collect::>().join("\n"); 221 | output = format!("{}\n{}", env_str, output); 222 | } 223 | } 224 | 225 | // If we have too much output safely convert the last 10k bytes into UTF-8 226 | let output = 227 | if !cli.head && output.len() > MAX_BYTES_TO_POST { 228 | String::from_utf8_lossy(&output.as_bytes()[output.len() - MAX_BYTES_TO_POST..]) 229 | } else { Cow::Owned(output) }; 230 | 231 | // Trim replacement chars added by from_utf8_lossy since they are multi-byte and can actually 232 | // increase the length of the string. 233 | let code = if cli.log { None } else { Some(code) }; 234 | agent.notify_complete(maybe_run_id, code, output.trim_start_matches(|c| c=='�')) 235 | } 236 | 237 | fn main() { 238 | let cli = Cli::parse(); 239 | let agent = HCAgent::create(&cli); 240 | 241 | run(cli, agent).expect("Failed to reach Healthchecks.io"); 242 | } 243 | 244 | #[cfg(test)] 245 | mod tests { 246 | use super::*; 247 | 248 | #[test] 249 | fn verify_cli() { 250 | use clap::IntoApp; 251 | Cli::into_app().debug_assert() 252 | } 253 | 254 | // 255 | // NOTE: Mockito's state sometimes leaks across tests, so each test should use a separate 256 | // fake UUID to avoid flaky matches. See https://github.com/lipanski/mockito/issues/111 257 | // 258 | 259 | parameterized_test::create!{ truncate, (orig, expected), { 260 | assert_eq!(truncate_str(orig.into(), 10), expected); } 261 | } 262 | truncate! { 263 | short: ("short", "short"), 264 | barely: ("barely fit", "barely fit"), 265 | long: ("much too long", "much to..."), 266 | } 267 | 268 | #[test] 269 | fn agent() { 270 | // This is mostly a change-detector, but it's helpful to validate the expected format 271 | match hostname::get().ok() { 272 | Some(host) => { 273 | assert_eq!(make_user_agent(None), 274 | format!("{} - {}", crate_name!(), host.to_string_lossy())); 275 | assert_eq!(make_user_agent(Some("foo")), 276 | format!("foo ({} - {})", crate_name!(), host.to_string_lossy())); 277 | }, 278 | None => { 279 | assert_eq!(make_user_agent(None), crate_name!()); 280 | assert_eq!(make_user_agent(Some("foo")), format!("foo ({})", crate_name!())); 281 | }, 282 | } 283 | } 284 | 285 | #[test] 286 | fn ping() { 287 | let suc_m = mockito::mock("POST", "/ping/0").match_body("foo bar").with_status(200).create(); 288 | let fail_m = mockito::mock("POST", "/ping/10").match_body("bar baz").with_status(200).create(); 289 | let log_m = mockito::mock("POST", "/ping/log").match_body("bang boom").with_status(200).create(); 290 | let runid_m = mockito::mock("POST", "/ping/0") 291 | .match_query(mockito::Matcher::Regex("rid=.*".into())) 292 | .match_body("run id") 293 | .with_status(200).create(); 294 | let agent = HCAgent{ agent: Agent::new(), verbose: false, url_prefix: format!("{}/{}", mockito::server_url(), "ping") }; 295 | let suc_response = agent.notify_complete(None, Some(0), "foo bar"); 296 | let fail_response = agent.notify_complete(None, Some(10), "bar baz"); 297 | let log_response = agent.notify_complete(None, None, "bang boom"); 298 | let runid_response = agent.notify_complete(Some(Uuid::from_u128(1234)), Some(0), "run id"); 299 | suc_m.assert(); 300 | fail_m.assert(); 301 | log_m.assert(); 302 | runid_m.assert(); 303 | suc_response.unwrap(); 304 | fail_response.unwrap(); 305 | log_response.unwrap(); 306 | runid_response.unwrap(); 307 | } 308 | 309 | mod integ { 310 | use super::*; 311 | 312 | fn fake_cli(uuid: &str, command: &[&str]) -> Cli { 313 | Cli { 314 | uuid: Some(uuid.into()), 315 | slug: None, 316 | ping_key: None, 317 | time: false, 318 | head: false, 319 | ping_only: false, 320 | log: false, 321 | detailed: false, 322 | env: false, 323 | verbose: false, 324 | user_agent: None, 325 | base_url: mockito::server_url(), 326 | command: command.iter().map(OsString::from).collect(), 327 | } 328 | } 329 | 330 | #[test] 331 | fn success() { 332 | let m = mockito::mock("POST", "/success/0").match_body("hello\n").with_status(200).create(); 333 | 334 | let cli = fake_cli("success", &["echo", "hello"]); 335 | let agent = HCAgent::create(&cli); 336 | let res = run(cli, agent); 337 | m.assert(); 338 | res.unwrap(); 339 | } 340 | 341 | #[test] 342 | fn fail() { 343 | let m = mockito::mock("POST", "/fail/5") 344 | .match_body("failed\n").with_status(200).create(); 345 | 346 | let cli = fake_cli("fail", &["bash", "-c", "echo failed >&2; exit 5"]); 347 | let agent = HCAgent::create(&cli); 348 | 349 | let res = run(cli, agent); 350 | m.assert(); 351 | res.unwrap(); 352 | } 353 | 354 | #[test] 355 | fn start() { 356 | let m = mockito::mock("GET", "/start/start") 357 | .match_query(mockito::Matcher::Regex("rid=.*".into())) 358 | .with_status(200).create(); 359 | 360 | let cli = fake_cli("start", &[""]); 361 | 362 | let response = HCAgent::create(&cli).notify_start(Uuid::from_u128(1234)); 363 | m.assert(); 364 | response.unwrap(); 365 | } 366 | 367 | #[test] 368 | fn log() { 369 | let m = mockito::mock("POST", "/log/log") 370 | .match_body("hello\n").with_status(200).create(); 371 | 372 | let mut cli = fake_cli("log", &["echo", "hello"]); 373 | cli.log = true; 374 | let agent = HCAgent::create(&cli); 375 | 376 | let res = run(cli, agent); 377 | m.assert(); 378 | res.unwrap(); 379 | } 380 | 381 | #[test] 382 | fn slug() { 383 | let m = mockito::mock("POST", "/key/slug/0") 384 | .match_body("hello\n").with_status(200).create(); 385 | 386 | let mut cli = fake_cli("dont-use", &["echo", "hello"]); 387 | cli.uuid = None; 388 | cli.ping_key = Some("key".into()); 389 | cli.slug = Some("slug".into()); 390 | let agent = HCAgent::create(&cli); 391 | 392 | let res = run(cli, agent); 393 | m.assert(); 394 | res.unwrap(); 395 | } 396 | 397 | #[test] 398 | fn unreachable() { 399 | // Unused, but necessary to isolate separate tests, per lipanski/mockito#111 400 | let m = mockito::mock("GET", "/").with_status(500).create(); 401 | 402 | let cli = fake_cli("unreachable", &["true"]); 403 | let agent = HCAgent::create(&cli); 404 | 405 | run(cli, agent).expect_err("Should fail."); 406 | m.expect(0); 407 | } 408 | 409 | #[test] 410 | fn timed() { 411 | let start_m = mockito::mock("GET", "/timed/start") 412 | .match_query(mockito::Matcher::Regex("rid=.*".into())) 413 | .with_status(200).create(); 414 | let done_m = mockito::mock("POST", "/timed/0") 415 | .match_query(mockito::Matcher::Regex("rid=.*".into())) 416 | .match_body("hello\n") 417 | .with_status(200).create(); 418 | 419 | let mut cli = fake_cli("timed", &["echo", "hello"]); 420 | cli.time = true; 421 | let agent = HCAgent::create(&cli); 422 | 423 | let res = run(cli, agent); 424 | start_m.assert(); 425 | done_m.assert(); 426 | res.unwrap(); 427 | } 428 | 429 | #[test] 430 | fn long_output() { 431 | use mockito::Matcher; 432 | let part = "🇺🇸⚾ "; 433 | let msg = part.repeat(1000); 434 | assert!(msg.len() > MAX_BYTES_TO_POST); 435 | assert!(!msg.is_char_boundary(msg.len()-MAX_BYTES_TO_POST-1)); 436 | 437 | let m = mockito::mock("POST", "/long_output/0") 438 | .match_header("content-length", "9998") 439 | .match_body(Matcher::AllOf(vec!( 440 | Matcher::Regex(format!("^ {}", part)), 441 | Matcher::Regex(format!("{}\n$", part)) 442 | ))) 443 | .with_status(200).create(); 444 | 445 | let cli = fake_cli("long_output", &["echo", &msg]); 446 | let agent = HCAgent::create(&cli); 447 | 448 | let res = run(cli, agent); 449 | m.assert(); 450 | res.unwrap(); 451 | } 452 | 453 | #[test] 454 | fn quiet() { 455 | let m = mockito::mock("POST", "/quiet/0") 456 | .match_body(mockito::Matcher::Missing).with_status(200).create(); 457 | 458 | let mut cli = fake_cli("quiet", &["echo", "quiet!"]); 459 | cli.ping_only = true; 460 | let agent = HCAgent::create(&cli); 461 | 462 | let res = run(cli, agent); 463 | m.assert(); 464 | res.unwrap(); 465 | } 466 | 467 | #[test] fn detailed() { 468 | let m = mockito::mock("POST", "/detailed/0") 469 | .match_body(mockito::Matcher::Regex( 470 | "^\\$ echo hello 2>&1\nhello\n\n\nExit Code: 0\nDuration: .*$".to_string())) 471 | .with_status(200).create(); 472 | 473 | let mut cli = fake_cli("detailed", &["echo", "hello"]); 474 | cli.detailed = true; 475 | let agent = HCAgent::create(&cli); 476 | 477 | let res = run(cli, agent); 478 | m.assert(); 479 | res.unwrap(); 480 | } 481 | } 482 | } 483 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "adler2" 7 | version = "2.0.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 10 | 11 | [[package]] 12 | name = "aho-corasick" 13 | version = "1.1.3" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 16 | dependencies = [ 17 | "memchr", 18 | ] 19 | 20 | [[package]] 21 | name = "anyhow" 22 | version = "1.0.98" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 25 | 26 | [[package]] 27 | name = "assert-json-diff" 28 | version = "1.1.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "4259cbe96513d2f1073027a259fc2ca917feb3026a5a8d984e3628e490255cc0" 31 | dependencies = [ 32 | "extend", 33 | "serde", 34 | "serde_json", 35 | ] 36 | 37 | [[package]] 38 | name = "autocfg" 39 | version = "1.4.0" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 42 | 43 | [[package]] 44 | name = "base64" 45 | version = "0.22.1" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 48 | 49 | [[package]] 50 | name = "bitflags" 51 | version = "1.3.2" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 54 | 55 | [[package]] 56 | name = "bitflags" 57 | version = "2.9.1" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 60 | 61 | [[package]] 62 | name = "bumpalo" 63 | version = "3.18.1" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" 66 | 67 | [[package]] 68 | name = "cc" 69 | version = "1.2.26" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" 72 | dependencies = [ 73 | "shlex", 74 | ] 75 | 76 | [[package]] 77 | name = "cfg-if" 78 | version = "1.0.0" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 81 | 82 | [[package]] 83 | name = "clap" 84 | version = "3.0.14" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62" 87 | dependencies = [ 88 | "bitflags 1.3.2", 89 | "clap_derive", 90 | "indexmap", 91 | "lazy_static", 92 | "os_str_bytes", 93 | "textwrap", 94 | ] 95 | 96 | [[package]] 97 | name = "clap_derive" 98 | version = "3.0.14" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85" 101 | dependencies = [ 102 | "heck", 103 | "proc-macro-error", 104 | "proc-macro2", 105 | "quote", 106 | "syn 1.0.109", 107 | ] 108 | 109 | [[package]] 110 | name = "colored" 111 | version = "2.2.0" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" 114 | dependencies = [ 115 | "lazy_static", 116 | "windows-sys 0.59.0", 117 | ] 118 | 119 | [[package]] 120 | name = "crc32fast" 121 | version = "1.4.2" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 124 | dependencies = [ 125 | "cfg-if", 126 | ] 127 | 128 | [[package]] 129 | name = "difference" 130 | version = "2.0.0" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" 133 | 134 | [[package]] 135 | name = "displaydoc" 136 | version = "0.2.5" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 139 | dependencies = [ 140 | "proc-macro2", 141 | "quote", 142 | "syn 2.0.101", 143 | ] 144 | 145 | [[package]] 146 | name = "extend" 147 | version = "0.1.2" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "f47da3a72ec598d9c8937a7ebca8962a5c7a1f28444e38c2b33c771ba3f55f05" 150 | dependencies = [ 151 | "proc-macro-error", 152 | "proc-macro2", 153 | "quote", 154 | "syn 1.0.109", 155 | ] 156 | 157 | [[package]] 158 | name = "flate2" 159 | version = "1.1.2" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" 162 | dependencies = [ 163 | "crc32fast", 164 | "miniz_oxide", 165 | ] 166 | 167 | [[package]] 168 | name = "foreign-types" 169 | version = "0.3.2" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 172 | dependencies = [ 173 | "foreign-types-shared", 174 | ] 175 | 176 | [[package]] 177 | name = "foreign-types-shared" 178 | version = "0.1.1" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 181 | 182 | [[package]] 183 | name = "form_urlencoded" 184 | version = "1.2.1" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 187 | dependencies = [ 188 | "percent-encoding", 189 | ] 190 | 191 | [[package]] 192 | name = "getrandom" 193 | version = "0.2.16" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 196 | dependencies = [ 197 | "cfg-if", 198 | "libc", 199 | "wasi 0.11.0+wasi-snapshot-preview1", 200 | ] 201 | 202 | [[package]] 203 | name = "getrandom" 204 | version = "0.3.3" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 207 | dependencies = [ 208 | "cfg-if", 209 | "libc", 210 | "r-efi", 211 | "wasi 0.14.2+wasi-0.2.4", 212 | ] 213 | 214 | [[package]] 215 | name = "hashbrown" 216 | version = "0.12.3" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 219 | 220 | [[package]] 221 | name = "heck" 222 | version = "0.4.1" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 225 | 226 | [[package]] 227 | name = "hostname" 228 | version = "0.3.1" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" 231 | dependencies = [ 232 | "libc", 233 | "match_cfg", 234 | "winapi", 235 | ] 236 | 237 | [[package]] 238 | name = "httparse" 239 | version = "1.10.1" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 242 | 243 | [[package]] 244 | name = "icu_collections" 245 | version = "2.0.0" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 248 | dependencies = [ 249 | "displaydoc", 250 | "potential_utf", 251 | "yoke", 252 | "zerofrom", 253 | "zerovec", 254 | ] 255 | 256 | [[package]] 257 | name = "icu_locale_core" 258 | version = "2.0.0" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 261 | dependencies = [ 262 | "displaydoc", 263 | "litemap", 264 | "tinystr", 265 | "writeable", 266 | "zerovec", 267 | ] 268 | 269 | [[package]] 270 | name = "icu_normalizer" 271 | version = "2.0.0" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 274 | dependencies = [ 275 | "displaydoc", 276 | "icu_collections", 277 | "icu_normalizer_data", 278 | "icu_properties", 279 | "icu_provider", 280 | "smallvec", 281 | "zerovec", 282 | ] 283 | 284 | [[package]] 285 | name = "icu_normalizer_data" 286 | version = "2.0.0" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 289 | 290 | [[package]] 291 | name = "icu_properties" 292 | version = "2.0.1" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 295 | dependencies = [ 296 | "displaydoc", 297 | "icu_collections", 298 | "icu_locale_core", 299 | "icu_properties_data", 300 | "icu_provider", 301 | "potential_utf", 302 | "zerotrie", 303 | "zerovec", 304 | ] 305 | 306 | [[package]] 307 | name = "icu_properties_data" 308 | version = "2.0.1" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 311 | 312 | [[package]] 313 | name = "icu_provider" 314 | version = "2.0.0" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 317 | dependencies = [ 318 | "displaydoc", 319 | "icu_locale_core", 320 | "stable_deref_trait", 321 | "tinystr", 322 | "writeable", 323 | "yoke", 324 | "zerofrom", 325 | "zerotrie", 326 | "zerovec", 327 | ] 328 | 329 | [[package]] 330 | name = "idna" 331 | version = "1.0.3" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 334 | dependencies = [ 335 | "idna_adapter", 336 | "smallvec", 337 | "utf8_iter", 338 | ] 339 | 340 | [[package]] 341 | name = "idna_adapter" 342 | version = "1.2.1" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 345 | dependencies = [ 346 | "icu_normalizer", 347 | "icu_properties", 348 | ] 349 | 350 | [[package]] 351 | name = "indexmap" 352 | version = "1.9.3" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 355 | dependencies = [ 356 | "autocfg", 357 | "hashbrown", 358 | ] 359 | 360 | [[package]] 361 | name = "itoa" 362 | version = "1.0.15" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 365 | 366 | [[package]] 367 | name = "js-sys" 368 | version = "0.3.77" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 371 | dependencies = [ 372 | "once_cell", 373 | "wasm-bindgen", 374 | ] 375 | 376 | [[package]] 377 | name = "lazy_static" 378 | version = "1.5.0" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 381 | 382 | [[package]] 383 | name = "libc" 384 | version = "0.2.172" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 387 | 388 | [[package]] 389 | name = "litemap" 390 | version = "0.8.0" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 393 | 394 | [[package]] 395 | name = "log" 396 | version = "0.4.27" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 399 | 400 | [[package]] 401 | name = "match_cfg" 402 | version = "0.1.0" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" 405 | 406 | [[package]] 407 | name = "memchr" 408 | version = "2.7.4" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 411 | 412 | [[package]] 413 | name = "miniz_oxide" 414 | version = "0.8.8" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" 417 | dependencies = [ 418 | "adler2", 419 | ] 420 | 421 | [[package]] 422 | name = "mockito" 423 | version = "0.29.0" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "102f0986ade96028c3227fc14fcbbbee0358ca33b3fedc9a400a97a6f5ad4a6e" 426 | dependencies = [ 427 | "assert-json-diff", 428 | "colored", 429 | "difference", 430 | "httparse", 431 | "lazy_static", 432 | "log", 433 | "rand", 434 | "regex", 435 | "serde_json", 436 | "serde_urlencoded", 437 | ] 438 | 439 | [[package]] 440 | name = "once_cell" 441 | version = "1.21.3" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 444 | 445 | [[package]] 446 | name = "openssl" 447 | version = "0.10.73" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" 450 | dependencies = [ 451 | "bitflags 2.9.1", 452 | "cfg-if", 453 | "foreign-types", 454 | "libc", 455 | "once_cell", 456 | "openssl-macros", 457 | "openssl-sys", 458 | ] 459 | 460 | [[package]] 461 | name = "openssl-macros" 462 | version = "0.1.1" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 465 | dependencies = [ 466 | "proc-macro2", 467 | "quote", 468 | "syn 2.0.101", 469 | ] 470 | 471 | [[package]] 472 | name = "openssl-src" 473 | version = "300.5.0+3.5.0" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" 476 | dependencies = [ 477 | "cc", 478 | ] 479 | 480 | [[package]] 481 | name = "openssl-sys" 482 | version = "0.9.109" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" 485 | dependencies = [ 486 | "cc", 487 | "libc", 488 | "openssl-src", 489 | "pkg-config", 490 | "vcpkg", 491 | ] 492 | 493 | [[package]] 494 | name = "os_str_bytes" 495 | version = "6.6.1" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" 498 | dependencies = [ 499 | "memchr", 500 | ] 501 | 502 | [[package]] 503 | name = "parameterized_test" 504 | version = "0.2.1" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "718554e60527e39d1cad6aefd50ec410927e57b5b5ecefc21c4b1556e496333f" 507 | dependencies = [ 508 | "anyhow", 509 | ] 510 | 511 | [[package]] 512 | name = "percent-encoding" 513 | version = "2.3.1" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 516 | 517 | [[package]] 518 | name = "pkg-config" 519 | version = "0.3.32" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 522 | 523 | [[package]] 524 | name = "potential_utf" 525 | version = "0.1.2" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" 528 | dependencies = [ 529 | "zerovec", 530 | ] 531 | 532 | [[package]] 533 | name = "ppv-lite86" 534 | version = "0.2.21" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 537 | dependencies = [ 538 | "zerocopy", 539 | ] 540 | 541 | [[package]] 542 | name = "proc-macro-error" 543 | version = "1.0.4" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 546 | dependencies = [ 547 | "proc-macro-error-attr", 548 | "proc-macro2", 549 | "quote", 550 | "syn 1.0.109", 551 | "version_check", 552 | ] 553 | 554 | [[package]] 555 | name = "proc-macro-error-attr" 556 | version = "1.0.4" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 559 | dependencies = [ 560 | "proc-macro2", 561 | "quote", 562 | "version_check", 563 | ] 564 | 565 | [[package]] 566 | name = "proc-macro2" 567 | version = "1.0.95" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 570 | dependencies = [ 571 | "unicode-ident", 572 | ] 573 | 574 | [[package]] 575 | name = "quote" 576 | version = "1.0.40" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 579 | dependencies = [ 580 | "proc-macro2", 581 | ] 582 | 583 | [[package]] 584 | name = "r-efi" 585 | version = "5.2.0" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 588 | 589 | [[package]] 590 | name = "rand" 591 | version = "0.8.5" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 594 | dependencies = [ 595 | "libc", 596 | "rand_chacha", 597 | "rand_core", 598 | ] 599 | 600 | [[package]] 601 | name = "rand_chacha" 602 | version = "0.3.1" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 605 | dependencies = [ 606 | "ppv-lite86", 607 | "rand_core", 608 | ] 609 | 610 | [[package]] 611 | name = "rand_core" 612 | version = "0.6.4" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 615 | dependencies = [ 616 | "getrandom 0.2.16", 617 | ] 618 | 619 | [[package]] 620 | name = "regex" 621 | version = "1.11.1" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 624 | dependencies = [ 625 | "aho-corasick", 626 | "memchr", 627 | "regex-automata", 628 | "regex-syntax", 629 | ] 630 | 631 | [[package]] 632 | name = "regex-automata" 633 | version = "0.4.9" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 636 | dependencies = [ 637 | "aho-corasick", 638 | "memchr", 639 | "regex-syntax", 640 | ] 641 | 642 | [[package]] 643 | name = "regex-syntax" 644 | version = "0.8.5" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 647 | 648 | [[package]] 649 | name = "ring" 650 | version = "0.17.14" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 653 | dependencies = [ 654 | "cc", 655 | "cfg-if", 656 | "getrandom 0.2.16", 657 | "libc", 658 | "untrusted", 659 | "windows-sys 0.52.0", 660 | ] 661 | 662 | [[package]] 663 | name = "rustls" 664 | version = "0.23.27" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" 667 | dependencies = [ 668 | "log", 669 | "once_cell", 670 | "ring", 671 | "rustls-pki-types", 672 | "rustls-webpki", 673 | "subtle", 674 | "zeroize", 675 | ] 676 | 677 | [[package]] 678 | name = "rustls-pki-types" 679 | version = "1.12.0" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 682 | dependencies = [ 683 | "zeroize", 684 | ] 685 | 686 | [[package]] 687 | name = "rustls-webpki" 688 | version = "0.103.3" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" 691 | dependencies = [ 692 | "ring", 693 | "rustls-pki-types", 694 | "untrusted", 695 | ] 696 | 697 | [[package]] 698 | name = "rustversion" 699 | version = "1.0.21" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" 702 | 703 | [[package]] 704 | name = "ryu" 705 | version = "1.0.20" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 708 | 709 | [[package]] 710 | name = "serde" 711 | version = "1.0.219" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 714 | dependencies = [ 715 | "serde_derive", 716 | ] 717 | 718 | [[package]] 719 | name = "serde_derive" 720 | version = "1.0.219" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 723 | dependencies = [ 724 | "proc-macro2", 725 | "quote", 726 | "syn 2.0.101", 727 | ] 728 | 729 | [[package]] 730 | name = "serde_json" 731 | version = "1.0.140" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 734 | dependencies = [ 735 | "itoa", 736 | "memchr", 737 | "ryu", 738 | "serde", 739 | ] 740 | 741 | [[package]] 742 | name = "serde_urlencoded" 743 | version = "0.7.1" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 746 | dependencies = [ 747 | "form_urlencoded", 748 | "itoa", 749 | "ryu", 750 | "serde", 751 | ] 752 | 753 | [[package]] 754 | name = "shlex" 755 | version = "1.3.0" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 758 | 759 | [[package]] 760 | name = "smallvec" 761 | version = "1.15.1" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 764 | 765 | [[package]] 766 | name = "stable_deref_trait" 767 | version = "1.2.0" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 770 | 771 | [[package]] 772 | name = "subprocess" 773 | version = "0.2.9" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" 776 | dependencies = [ 777 | "libc", 778 | "winapi", 779 | ] 780 | 781 | [[package]] 782 | name = "subtle" 783 | version = "2.6.1" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 786 | 787 | [[package]] 788 | name = "syn" 789 | version = "1.0.109" 790 | source = "registry+https://github.com/rust-lang/crates.io-index" 791 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 792 | dependencies = [ 793 | "proc-macro2", 794 | "quote", 795 | "unicode-ident", 796 | ] 797 | 798 | [[package]] 799 | name = "syn" 800 | version = "2.0.101" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 803 | dependencies = [ 804 | "proc-macro2", 805 | "quote", 806 | "unicode-ident", 807 | ] 808 | 809 | [[package]] 810 | name = "synstructure" 811 | version = "0.13.2" 812 | source = "registry+https://github.com/rust-lang/crates.io-index" 813 | checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 814 | dependencies = [ 815 | "proc-macro2", 816 | "quote", 817 | "syn 2.0.101", 818 | ] 819 | 820 | [[package]] 821 | name = "task-mon" 822 | version = "0.3.2" 823 | dependencies = [ 824 | "clap", 825 | "clap_derive", 826 | "hostname", 827 | "mockito", 828 | "openssl", 829 | "parameterized_test", 830 | "subprocess", 831 | "ureq", 832 | "uuid", 833 | ] 834 | 835 | [[package]] 836 | name = "textwrap" 837 | version = "0.14.2" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" 840 | 841 | [[package]] 842 | name = "tinystr" 843 | version = "0.8.1" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 846 | dependencies = [ 847 | "displaydoc", 848 | "zerovec", 849 | ] 850 | 851 | [[package]] 852 | name = "unicode-ident" 853 | version = "1.0.18" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 856 | 857 | [[package]] 858 | name = "untrusted" 859 | version = "0.9.0" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 862 | 863 | [[package]] 864 | name = "ureq" 865 | version = "2.12.1" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" 868 | dependencies = [ 869 | "base64", 870 | "flate2", 871 | "log", 872 | "once_cell", 873 | "rustls", 874 | "rustls-pki-types", 875 | "url", 876 | "webpki-roots 0.26.11", 877 | ] 878 | 879 | [[package]] 880 | name = "url" 881 | version = "2.5.4" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 884 | dependencies = [ 885 | "form_urlencoded", 886 | "idna", 887 | "percent-encoding", 888 | ] 889 | 890 | [[package]] 891 | name = "utf8_iter" 892 | version = "1.0.4" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 895 | 896 | [[package]] 897 | name = "uuid" 898 | version = "1.17.0" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" 901 | dependencies = [ 902 | "getrandom 0.3.3", 903 | "js-sys", 904 | "wasm-bindgen", 905 | ] 906 | 907 | [[package]] 908 | name = "vcpkg" 909 | version = "0.2.15" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 912 | 913 | [[package]] 914 | name = "version_check" 915 | version = "0.9.5" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 918 | 919 | [[package]] 920 | name = "wasi" 921 | version = "0.11.0+wasi-snapshot-preview1" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 924 | 925 | [[package]] 926 | name = "wasi" 927 | version = "0.14.2+wasi-0.2.4" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 930 | dependencies = [ 931 | "wit-bindgen-rt", 932 | ] 933 | 934 | [[package]] 935 | name = "wasm-bindgen" 936 | version = "0.2.100" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 939 | dependencies = [ 940 | "cfg-if", 941 | "once_cell", 942 | "rustversion", 943 | "wasm-bindgen-macro", 944 | ] 945 | 946 | [[package]] 947 | name = "wasm-bindgen-backend" 948 | version = "0.2.100" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 951 | dependencies = [ 952 | "bumpalo", 953 | "log", 954 | "proc-macro2", 955 | "quote", 956 | "syn 2.0.101", 957 | "wasm-bindgen-shared", 958 | ] 959 | 960 | [[package]] 961 | name = "wasm-bindgen-macro" 962 | version = "0.2.100" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 965 | dependencies = [ 966 | "quote", 967 | "wasm-bindgen-macro-support", 968 | ] 969 | 970 | [[package]] 971 | name = "wasm-bindgen-macro-support" 972 | version = "0.2.100" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 975 | dependencies = [ 976 | "proc-macro2", 977 | "quote", 978 | "syn 2.0.101", 979 | "wasm-bindgen-backend", 980 | "wasm-bindgen-shared", 981 | ] 982 | 983 | [[package]] 984 | name = "wasm-bindgen-shared" 985 | version = "0.2.100" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 988 | dependencies = [ 989 | "unicode-ident", 990 | ] 991 | 992 | [[package]] 993 | name = "webpki-roots" 994 | version = "0.26.11" 995 | source = "registry+https://github.com/rust-lang/crates.io-index" 996 | checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" 997 | dependencies = [ 998 | "webpki-roots 1.0.0", 999 | ] 1000 | 1001 | [[package]] 1002 | name = "webpki-roots" 1003 | version = "1.0.0" 1004 | source = "registry+https://github.com/rust-lang/crates.io-index" 1005 | checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" 1006 | dependencies = [ 1007 | "rustls-pki-types", 1008 | ] 1009 | 1010 | [[package]] 1011 | name = "winapi" 1012 | version = "0.3.9" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1015 | dependencies = [ 1016 | "winapi-i686-pc-windows-gnu", 1017 | "winapi-x86_64-pc-windows-gnu", 1018 | ] 1019 | 1020 | [[package]] 1021 | name = "winapi-i686-pc-windows-gnu" 1022 | version = "0.4.0" 1023 | source = "registry+https://github.com/rust-lang/crates.io-index" 1024 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1025 | 1026 | [[package]] 1027 | name = "winapi-x86_64-pc-windows-gnu" 1028 | version = "0.4.0" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1031 | 1032 | [[package]] 1033 | name = "windows-sys" 1034 | version = "0.52.0" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1037 | dependencies = [ 1038 | "windows-targets", 1039 | ] 1040 | 1041 | [[package]] 1042 | name = "windows-sys" 1043 | version = "0.59.0" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1046 | dependencies = [ 1047 | "windows-targets", 1048 | ] 1049 | 1050 | [[package]] 1051 | name = "windows-targets" 1052 | version = "0.52.6" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1055 | dependencies = [ 1056 | "windows_aarch64_gnullvm", 1057 | "windows_aarch64_msvc", 1058 | "windows_i686_gnu", 1059 | "windows_i686_gnullvm", 1060 | "windows_i686_msvc", 1061 | "windows_x86_64_gnu", 1062 | "windows_x86_64_gnullvm", 1063 | "windows_x86_64_msvc", 1064 | ] 1065 | 1066 | [[package]] 1067 | name = "windows_aarch64_gnullvm" 1068 | version = "0.52.6" 1069 | source = "registry+https://github.com/rust-lang/crates.io-index" 1070 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1071 | 1072 | [[package]] 1073 | name = "windows_aarch64_msvc" 1074 | version = "0.52.6" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1077 | 1078 | [[package]] 1079 | name = "windows_i686_gnu" 1080 | version = "0.52.6" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1083 | 1084 | [[package]] 1085 | name = "windows_i686_gnullvm" 1086 | version = "0.52.6" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1089 | 1090 | [[package]] 1091 | name = "windows_i686_msvc" 1092 | version = "0.52.6" 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" 1094 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1095 | 1096 | [[package]] 1097 | name = "windows_x86_64_gnu" 1098 | version = "0.52.6" 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" 1100 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1101 | 1102 | [[package]] 1103 | name = "windows_x86_64_gnullvm" 1104 | version = "0.52.6" 1105 | source = "registry+https://github.com/rust-lang/crates.io-index" 1106 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1107 | 1108 | [[package]] 1109 | name = "windows_x86_64_msvc" 1110 | version = "0.52.6" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1113 | 1114 | [[package]] 1115 | name = "wit-bindgen-rt" 1116 | version = "0.39.0" 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" 1118 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 1119 | dependencies = [ 1120 | "bitflags 2.9.1", 1121 | ] 1122 | 1123 | [[package]] 1124 | name = "writeable" 1125 | version = "0.6.1" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 1128 | 1129 | [[package]] 1130 | name = "yoke" 1131 | version = "0.8.0" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 1134 | dependencies = [ 1135 | "serde", 1136 | "stable_deref_trait", 1137 | "yoke-derive", 1138 | "zerofrom", 1139 | ] 1140 | 1141 | [[package]] 1142 | name = "yoke-derive" 1143 | version = "0.8.0" 1144 | source = "registry+https://github.com/rust-lang/crates.io-index" 1145 | checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 1146 | dependencies = [ 1147 | "proc-macro2", 1148 | "quote", 1149 | "syn 2.0.101", 1150 | "synstructure", 1151 | ] 1152 | 1153 | [[package]] 1154 | name = "zerocopy" 1155 | version = "0.8.25" 1156 | source = "registry+https://github.com/rust-lang/crates.io-index" 1157 | checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" 1158 | dependencies = [ 1159 | "zerocopy-derive", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "zerocopy-derive" 1164 | version = "0.8.25" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" 1167 | dependencies = [ 1168 | "proc-macro2", 1169 | "quote", 1170 | "syn 2.0.101", 1171 | ] 1172 | 1173 | [[package]] 1174 | name = "zerofrom" 1175 | version = "0.1.6" 1176 | source = "registry+https://github.com/rust-lang/crates.io-index" 1177 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 1178 | dependencies = [ 1179 | "zerofrom-derive", 1180 | ] 1181 | 1182 | [[package]] 1183 | name = "zerofrom-derive" 1184 | version = "0.1.6" 1185 | source = "registry+https://github.com/rust-lang/crates.io-index" 1186 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 1187 | dependencies = [ 1188 | "proc-macro2", 1189 | "quote", 1190 | "syn 2.0.101", 1191 | "synstructure", 1192 | ] 1193 | 1194 | [[package]] 1195 | name = "zeroize" 1196 | version = "1.8.1" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 1199 | 1200 | [[package]] 1201 | name = "zerotrie" 1202 | version = "0.2.2" 1203 | source = "registry+https://github.com/rust-lang/crates.io-index" 1204 | checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 1205 | dependencies = [ 1206 | "displaydoc", 1207 | "yoke", 1208 | "zerofrom", 1209 | ] 1210 | 1211 | [[package]] 1212 | name = "zerovec" 1213 | version = "0.11.2" 1214 | source = "registry+https://github.com/rust-lang/crates.io-index" 1215 | checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" 1216 | dependencies = [ 1217 | "yoke", 1218 | "zerofrom", 1219 | "zerovec-derive", 1220 | ] 1221 | 1222 | [[package]] 1223 | name = "zerovec-derive" 1224 | version = "0.11.1" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 1227 | dependencies = [ 1228 | "proc-macro2", 1229 | "quote", 1230 | "syn 2.0.101", 1231 | ] 1232 | --------------------------------------------------------------------------------