Skip to content

Commit

Permalink
Change: adds a Lambda scanner for easier testing
Browse files Browse the repository at this point in the history
Instead of having to copy and paste the async traits over and over for
testing purposes a new Lambda scanner is created.

This allows us to easily build a scanner based on sync functions.

To use it you can use the LambdaBuilder:

```
use models::scanner::Error as ScanError;
use models::scanner::LambdaBuilder;
let builder = LambdaBuilder::default().with_start(|_|
Err(ScanError::Unexpected("meh".to_string())));
let scanner = builder.build();
```
  • Loading branch information
nichtsfrei committed Mar 4, 2024
1 parent c5b4321 commit 90ecc3a
Showing 1 changed file with 123 additions and 1 deletion.
124 changes: 123 additions & 1 deletion rust/models/src/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,135 @@ pub trait ScanResultFetcher {
I: AsRef<str> + Send + 'static;
}

/// Is a scanner implementation primarily for testing purposes.
///
/// It is holding call back functions so that it is easier to implement a scanner for testing
/// without having to copy and paste the async traits.
#[allow(clippy::complexity)]
pub struct Lambda {
start: Box<dyn Fn(Scan) -> Result<(), Error> + Sync + Send + 'static>,
stop: Box<dyn Fn(&str) -> Result<(), Error> + Sync + Send + 'static>,
delete: Box<dyn Fn(&str) -> Result<(), Error> + Sync + Send + 'static>,
fetch: Box<dyn Fn(&str) -> Result<ScanResults, Error> + Sync + Send + 'static>,
}

impl Default for Lambda {
fn default() -> Self {
Self {
start: Box::new(|_| Ok(())),
stop: Box::new(|_| Ok(())),
delete: Box::new(|_| Ok(())),
fetch: Box::new(|_| Ok(ScanResults::default())),
}
}
}

/// Builds a Lambda scanenr implementation.
///
/// Usage:
/// ```
/// use models::scanner::Error as ScanError;
/// use models::scanner::LambdaBuilder;
///
/// let builder = LambdaBuilder::default().with_start(|_|
/// Err(ScanError::Unexpected("meh".to_string())));
/// let scanner = builder.build();
/// ```
pub struct LambdaBuilder {
lambda: Lambda,
}

impl Default for LambdaBuilder {
fn default() -> Self {
Self::new()
}
}

impl LambdaBuilder {
pub fn new() -> Self {
Self {
lambda: Lambda::default(),
}
}
pub fn with_start<F>(mut self, f: F) -> Self
where
F: Fn(Scan) -> Result<(), Error> + Sync + Send + 'static,
{
self.lambda.start = Box::new(f);
self
}
pub fn with_stop<F>(mut self, f: F) -> Self
where
F: Fn(&str) -> Result<(), Error> + Sync + Send + 'static,
{
self.lambda.stop = Box::new(f);
self
}
pub fn with_delete<F>(mut self, f: F) -> Self
where
F: Fn(&str) -> Result<(), Error> + Sync + Send + 'static,
{
self.lambda.delete = Box::new(f);
self
}

pub fn with_fetch<F>(mut self, f: F) -> Self
where
F: Fn(&str) -> Result<ScanResults, Error> + Sync + Send + 'static,
{
self.lambda.fetch = Box::new(f);
self
}

pub fn build(self) -> Lambda {
self.lambda
}
}

#[async_trait]
impl ScanStarter for Lambda {
async fn start_scan(&self, scan: Scan) -> Result<(), Error> {
(self.start)(scan)
}
}

#[async_trait]
impl ScanStopper for Lambda {
async fn stop_scan<I>(&self, id: I) -> Result<(), Error>
where
I: AsRef<str> + Send + 'static,
{
(self.stop)(id.as_ref())
}
}

#[async_trait]
impl ScanDeleter for Lambda {
async fn delete_scan<I>(&self, id: I) -> Result<(), Error>
where
I: AsRef<str> + Send + 'static,
{
(self.delete)(id.as_ref())
}
}

#[async_trait]
impl ScanResultFetcher for Lambda {
async fn fetch_results<I>(&self, id: I) -> Result<ScanResults, Error>
where
I: AsRef<str> + Send + 'static,
{
(self.fetch)(id.as_ref())
}
}

/// Combines all traits needed for a scanner.
#[async_trait]
pub trait Scanner: ScanStarter + ScanStopper + ScanDeleter + ScanResultFetcher {}

impl<T> Scanner for T where T: ScanStarter + ScanStopper + ScanDeleter + ScanResultFetcher {}

#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
Unexpected(String),
Connection(String),
Expand Down

0 comments on commit 90ecc3a

Please sign in to comment.