Skip to content

Commit

Permalink
feat: add churn plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
j-lanson committed Oct 23, 2024
1 parent 2e4302e commit 8d55ac6
Show file tree
Hide file tree
Showing 12 changed files with 1,092 additions and 9 deletions.
31 changes: 23 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ members = [
"plugins/fuzz",
"plugins/entropy",
"plugins/linguist",
"plugins/review"
"plugins/review",
"plugins/churn"
]

# Make sure Hipcheck is run with `cargo run`.
Expand Down
18 changes: 18 additions & 0 deletions plugins/churn/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "churn"
version = "0.1.0"
edition = "2021"

[dependencies]
clap = { version = "4.5.20", features = ["derive"] }
hipcheck-sdk = { version = "0.1.0", path = "../../sdk/rust", features = ["macros"] }
log = "0.4.22"
salsa = "0.16.1"
schemars = "0.8.21"
serde = "1.0.213"
serde_json = "1.0.132"
tokio = { version = "1.41.0", features = ["rt"] }
toml = "0.8.19"

[dev-dependencies]
hipcheck-sdk = { path = "../../sdk/rust", features = ["mock_engine"] }
14 changes: 14 additions & 0 deletions plugins/churn/plugin.kdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
publisher "mitre"
name "churn"
version "0.1.0"
license "Apache-2.0"
entrypoint {
on arch="aarch64-apple-darwin" "./churn"
on arch="x86_64-apple-darwin" "./churn"
on arch="x86_64-unknown-linux-gnu" "./churn"
on arch="x86_64-pc-windows-msvc" "./churn"
}

dependencies {
plugin "mitre/git" version="0.1.0" manifest="./plugins/git/plugin.kdl"
}
160 changes: 160 additions & 0 deletions plugins/churn/src/error/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// SPDX-License-Identifier: Apache-2.0

//! A duplicate of the `anyhow::Context` extension trait intended to
//! make error propagation less verbose.

use crate::error::{Error, Introspect};
use std::error::Error as StdError;

/// Functions for adding context to an error result
///
/// The `Context` trait is based around the `Error` type defined in
/// this crate. Aside from the changed method names (collision
/// avoidance), it is a duplicate of the `anyhow::Context` trait.
/// Like its `anyhow` counterpart, this trait is sealed.
pub trait Context<T>: sealed::Sealed {
/// Add context to an error
fn context<C>(self, context: C) -> Result<T, Error>
where
C: Introspect + 'static;

/// Lazily add context to an error
fn with_context<C, F>(self, context_fn: F) -> Result<T, Error>
where
C: Introspect + 'static,
F: FnOnce() -> C;
}

// `Context` is implemented only for those result types encountered
// when entering or traversing the query system: `Result<T, Error>`
// and `Result<T, E>` for dynamic error types `E`.

impl<T> Context<T> for Result<T, Error> {
fn context<C>(self, context: C) -> Result<T, Error>
where
C: Introspect + 'static,
{
self.map_err(|err| err.context(context))
}

fn with_context<C, F>(self, context_fn: F) -> Result<T, Error>
where
C: Introspect + 'static,
F: FnOnce() -> C,
{
self.map_err(|err| err.context(context_fn()))
}
}

impl<T, E> Context<T> for Result<T, E>
where
E: StdError + Send + Sync + 'static,
{
fn context<C>(self, context: C) -> Result<T, Error>
where
C: Introspect + 'static,
{
self.map_err(|err| Error::from(err).context(context))
}

fn with_context<C, F>(self, context_fn: F) -> Result<T, Error>
where
C: Introspect + 'static,
F: FnOnce() -> C,
{
self.map_err(|err| Error::from(err).context(context_fn()))
}
}

// Restricts implementations of `Context` only to those contained in
// this module
mod sealed {
use super::{Error, StdError};

pub trait Sealed {}

impl<T> Sealed for Result<T, Error> {}

impl<T, E> Sealed for Result<T, E> where E: StdError + 'static {}
}

#[cfg(test)]
mod tests {
//! Tests to ensure `Context` produces output correctly.

use crate::error::Error;
use std::{io, io::ErrorKind};

// Message source root error with no context
#[test]
fn debug_behavior_msg_no_context() {
let error = Error::msg("error message");
let debug = format!("{:?}", error);
let expected = "error message".to_string();
assert_eq!(expected, debug);
}

// Message source root error with a single context message
#[test]
fn debug_behavior_msg_single_context() {
let error = Error::msg("error message").context("context");
let debug = format!("{:?}", error);
let expected = "context\n\nCaused by: \n 0: error message".to_string();
assert_eq!(expected, debug);
}

// Message source root error with multiple context messages
#[test]
fn debug_behavior_msg_multiple_context() {
let error = Error::msg("error message")
.context("context 1")
.context("context 2");
let debug = format!("{:?}", error);
let expected =
"context 2\n\nCaused by: \n 0: context 1\n 1: error message".to_string();
assert_eq!(expected, debug);
}

// Dynamic error source with no context
#[test]
fn debug_behavior_std_no_context() {
let error = Error::from(io::Error::new(
ErrorKind::ConnectionRefused,
"connection refused",
));

let debug = format!("{:?}", error);
let expected = "connection refused".to_string();
assert_eq!(expected, debug);
}

// Dynamic error source with a single context message
#[test]
fn debug_behavior_std_single_context() {
let error = Error::from(io::Error::new(
ErrorKind::ConnectionRefused,
"connection refused",
))
.context("context");

let debug = format!("{:?}", error);
let expected = "context\n\nCaused by: \n 0: connection refused".to_string();
assert_eq!(expected, debug);
}

// Dynamic error source with multiple context messages
#[test]
fn debug_behavior_std_multiple_context() {
let error = Error::from(io::Error::new(
ErrorKind::ConnectionRefused,
"connection refused",
))
.context("context 1")
.context("context 2");

let debug = format!("{:?}", error);
let expected =
"context 2\n\nCaused by: \n 0: context 1\n 1: connection refused".to_string();
assert_eq!(expected, debug);
}
}
Loading

0 comments on commit 8d55ac6

Please sign in to comment.