Compare commits

..

No commits in common. "23e3e29e5629e9b072dd59fb44021d6f83b56d3a" and "23322924163010db993253dc0ac368c6331a465e" have entirely different histories.

14 changed files with 191 additions and 223 deletions

2
.gitignore vendored
View file

@ -25,5 +25,3 @@ Cargo.lock
# Added by cargo # Added by cargo
/target /target
/mutants.out/
/mutants.out.old/

View file

@ -9,10 +9,7 @@ anyhow = "1.0"
bon = "3.0" bon = "3.0"
ignore = "0.4" ignore = "0.4"
file-format = { version = "0.26", features = ["reader-txt"] } file-format = { version = "0.26", features = ["reader-txt"] }
kxio = "1.2"
kxio = "2.1"
regex = "1.10" regex = "1.10"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.37", features = ["full"] } tokio = { version = "1.37", features = ["full"] }

View file

@ -1,15 +1,3 @@
build:
#!/usr/bin/env bash
set -e
cargo fmt
cargo fmt --check
cargo hack clippy
cargo hack build
cargo hack test
cargo doc
# cargo test --example get
cargo mutants --jobs 4
self-test: self-test:
just test $PWD forgejo-todo-checker just test $PWD forgejo-todo-checker

View file

@ -3,16 +3,17 @@ use crate::model::Config;
use crate::patterns::issue_pattern; use crate::patterns::issue_pattern;
use crate::printer::Printer; use crate::printer::Printer;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use kxio::{fs::FileSystem, net::Net}; use kxio::fs;
use kxio::network::Network;
pub fn init_config<'net, 'fs>( pub fn init_config(printer: &impl Printer, net: Network) -> Result<Config> {
printer: &impl Printer,
fs: &'fs FileSystem,
net: &'net Net,
) -> Result<Config<'net, 'fs>> {
let config = Config::builder() let config = Config::builder()
.net(net) .net(net)
.fs(fs) .fs(fs::new(
std::env::var("GITHUB_WORKSPACE")
.context("GITHUB_WORKSPACE")?
.into(),
))
.repo(std::env::var("GITHUB_REPOSITORY").context("GITHUB_REPOSITORY")?) .repo(std::env::var("GITHUB_REPOSITORY").context("GITHUB_REPOSITORY")?)
.server(std::env::var("GITHUB_SERVER_URL").context("GITHUB_SERVER_URL")?) .server(std::env::var("GITHUB_SERVER_URL").context("GITHUB_SERVER_URL")?)
.issue_pattern(issue_pattern()?) .issue_pattern(issue_pattern()?)

View file

@ -1,28 +1,33 @@
//
use std::collections::HashSet; use std::collections::HashSet;
//
use crate::model::Config; use crate::model::Config;
use anyhow::Result; use anyhow::Result;
use kxio::network::{NetRequest, NetUrl};
use super::Issue; use super::Issue;
pub async fn fetch_open_issues<'net, 'fs>(config: &Config<'net, 'fs>) -> Result<HashSet<Issue>> { pub async fn fetch_open_issues(config: &Config) -> Result<HashSet<Issue>> {
let server_url = config.server(); let server_url = config.server();
let repo = config.repo(); let repo = config.repo();
let url = format!("{server_url}/api/v1/repos/{repo}/issues?state=open"); let url = format!("{server_url}/api/v1/repos/{repo}/issues?state=open");
let net = config.net(); let request_builder = NetRequest::get(NetUrl::new(url));
let client = net.client();
let request = client.get(url);
let request = if let Some(auth_token) = config.auth_token() { let request = if let Some(auth_token) = config.auth_token() {
request.header("Authorization", auth_token) request_builder.header("Authorization", auth_token)
} else { } else {
request request_builder
}; }
// .build(); .build();
let response = net.send(request).await?; let issues: HashSet<Issue> = config
let issues: HashSet<Issue> = response.json().await?; .net()
.get::<Vec<Issue>>(request)
.await? // tarpaulin uncovered okay
.response_body()
.unwrap_or_default()
.into_iter()
.collect();
Ok(issues) Ok(issues)
} }

View file

@ -1,6 +1,3 @@
//
use super::*;
use std::collections::HashSet; use std::collections::HashSet;
use crate::tests::a_config; use crate::tests::a_config;
@ -10,39 +7,26 @@ use super::*;
use anyhow::Result; use anyhow::Result;
use kxio::network::StatusCode; use kxio::network::StatusCode;
use std::collections::HashSet;
use crate::tests::a_config;
use kxio::net::{Method, Net, Url};
#[tokio::test] #[tokio::test]
async fn fetch_lists_issues() { async fn fetch_lists_issues() -> Result<()> {
//given //given
let mock_net = kxio::net::mock(); let mut net = kxio::network::MockNetwork::new();
mock_net net.add_get_response(
.on(Method::GET) "https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open",
.url( StatusCode::OK,
Url::parse("https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open") r#"[{"number":13},{"number":64}]"#,
.expect("parse url"), );
) let config = a_config(net.into(), kxio::fs::temp()?)?;
.respond(
mock_net
.response()
.status(200)
.body(r#"[{"number":13},{"number":64}]"#)
.expect("response body"),
);
let fs = kxio::fs::temp().expect("temp fs");
let net = Net::from(mock_net);
let config = a_config(&net, &fs).expect("config");
//when //when
let result = fetch_open_issues(&config).await.expect("when"); let result = fetch_open_issues(&config).await?;
//then //then
assert_eq!( assert_eq!(
result, result,
HashSet::from_iter(vec![Issue::new(13), Issue::new(64)]) HashSet::from_iter(vec![Issue::new(13), Issue::new(64)])
); );
Ok(())
} }

View file

@ -1,8 +1,9 @@
// //
use anyhow::{bail, Context as _, Result}; use anyhow::{bail, Result};
use init::init_config; use init::init_config;
use issues::fetch_open_issues; use issues::fetch_open_issues;
use printer::{Printer, StandardPrinter}; use kxio::network::Network;
use printer::Printer;
use scanner::{find_markers, DefaultFileScanner}; use scanner::{find_markers, DefaultFileScanner};
mod init; mod init;
@ -18,23 +19,15 @@ mod tests;
#[tokio::main] #[tokio::main]
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> { async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
use printer::StandardPrinter;
Ok(run(&StandardPrinter, Network::new_real()).await?) Ok(run(&StandardPrinter, Network::new_real()).await?)
let github_workspace = std::env::var("GITHUB_WORKSPACE").context("GITHUB_WORKSPACE")?;
let fs = kxio::fs::new(github_workspace);
let net = kxio::net::new();
Ok(run(&StandardPrinter, &fs, &net).await?)
} }
async fn run( async fn run(printer: &impl Printer, net: Network) -> Result<()> {
printer: &impl Printer,
fs: &kxio::fs::FileSystem,
net: &kxio::net::Net,
) -> Result<()> {
printer.println("Forgejo TODO Checker!"); printer.println("Forgejo TODO Checker!");
let config = init_config(printer, fs, net)?; let config = init_config(printer, net)?;
let issues = fetch_open_issues(&config).await?; let issues = fetch_open_issues(&config).await?;
let errors = find_markers(printer, &config, issues, &DefaultFileScanner)?; let errors = find_markers(printer, &config, issues, &DefaultFileScanner)?;

View file

@ -2,21 +2,21 @@
use bon::Builder; use bon::Builder;
use regex::Regex; use regex::Regex;
#[derive(Builder)] #[derive(Debug, Builder)]
pub struct Config<'net, 'fs> { pub struct Config {
net: &'net kxio::net::Net, net: kxio::network::Network,
fs: &'fs kxio::fs::FileSystem, fs: kxio::fs::FileSystem,
repo: String, repo: String,
server: String, server: String,
auth_token: Option<String>, auth_token: Option<String>,
issue_pattern: Regex, issue_pattern: Regex,
} }
impl<'net, 'fs> Config<'net, 'fs> { impl Config {
pub fn net(&self) -> &kxio::net::Net { pub fn net(&self) -> &kxio::network::Network {
self.net &self.net
} }
pub fn fs(&self) -> &kxio::fs::FileSystem { pub fn fs(&self) -> &kxio::fs::FileSystem {
self.fs &self.fs
} }
pub fn repo(&self) -> &str { pub fn repo(&self) -> &str {
&self.repo &self.repo

View file

@ -6,9 +6,9 @@ use crate::{patterns::issue_pattern, tests::a_config};
#[tokio::test] #[tokio::test]
async fn with_config_get_net() -> Result<()> { async fn with_config_get_net() -> Result<()> {
//given //given
let net = kxio::net::mock().into(); let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(&net, &fs)?; let config = a_config(net, fs)?;
//when //when
config.net(); config.net();
@ -21,9 +21,9 @@ async fn with_config_get_net() -> Result<()> {
#[test] #[test]
fn with_config_get_fs() -> Result<()> { fn with_config_get_fs() -> Result<()> {
//given //given
let net = kxio::net::mock().into(); let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(&net, &fs)?; let config = a_config(net, fs.clone())?;
//when //when
let result = config.fs(); let result = config.fs();
@ -37,9 +37,9 @@ fn with_config_get_fs() -> Result<()> {
#[test] #[test]
fn with_config_get_issue_pattern() -> Result<()> { fn with_config_get_issue_pattern() -> Result<()> {
//given //given
let net = kxio::net::mock().into(); let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(&net, &fs)?; let config = a_config(net, fs)?;
//when //when
let result = config.issue_pattern(); let result = config.issue_pattern();
@ -53,9 +53,9 @@ fn with_config_get_issue_pattern() -> Result<()> {
#[test] #[test]
fn with_config_get_server() -> Result<()> { fn with_config_get_server() -> Result<()> {
//given //given
let net = kxio::net::mock().into(); let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(&net, &fs)?; let config = a_config(net, fs)?;
//when //when
let result = config.server(); let result = config.server();
@ -69,9 +69,9 @@ fn with_config_get_server() -> Result<()> {
#[test] #[test]
fn with_config_get_auth_token() -> Result<()> { fn with_config_get_auth_token() -> Result<()> {
//given //given
let net = kxio::net::mock().into(); let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(&net, &fs)?; let config = a_config(net, fs)?;
//when //when
let result = config.auth_token(); let result = config.auth_token();
@ -85,9 +85,9 @@ fn with_config_get_auth_token() -> Result<()> {
#[test] #[test]
fn with_config_get_repo() -> Result<()> { fn with_config_get_repo() -> Result<()> {
//given //given
let net = kxio::net::mock().into(); let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(&net, &fs)?; let config = a_config(net, fs)?;
//when //when
let result = config.repo(); let result = config.repo();

View file

@ -6,7 +6,7 @@ use crate::{
model::{Config, Line, Marker}, model::{Config, Line, Marker},
printer::Printer, printer::Printer,
}; };
use anyhow::{Context as _, Result}; use anyhow::Result;
use file_format::FileFormat; use file_format::FileFormat;
use ignore::Walk; use ignore::Walk;
@ -29,17 +29,15 @@ pub fn find_markers(
let mut errors = 0; let mut errors = 0;
for file in Walk::new(config.fs().base()).flatten() { for file in Walk::new(config.fs().base()).flatten() {
let path = file.path(); let path = file.path();
if is_text_file(config, path).context("is text file")? { if is_text_file(config, path)? {
errors += file_scanner errors += file_scanner.scan_file(path, config, printer, &issues)?
.scan_file(path, config, printer, &issues)
.context("scan file")?
} }
} }
Ok(errors) Ok(errors)
} }
fn is_text_file(config: &Config, path: &Path) -> Result<bool> { fn is_text_file(config: &Config, path: &Path) -> Result<bool> {
Ok(config.fs().path(path).is_file()? Ok(config.fs().path_is_file(path)?
&& FileFormat::from_file(path)? && FileFormat::from_file(path)?
.media_type() .media_type()
.starts_with("text/")) .starts_with("text/"))
@ -58,9 +56,7 @@ impl FileScanner for DefaultFileScanner {
let mut errors = 0; let mut errors = 0;
config config
.fs() .fs()
.file(file) .file_read_to_string(file)? // tarpaulin uncovered okay
.reader()?
.to_string() // tarpaulin uncovered okay
.lines() .lines()
.enumerate() .enumerate()
.map(|(n, line)| { .map(|(n, line)| {

View file

@ -2,37 +2,32 @@
use super::*; use super::*;
use assert2::let_assert; use assert2::let_assert;
use kxio::net::Net; use kxio::network::Network;
use model::Config; use model::Config;
use patterns::issue_pattern; use patterns::issue_pattern;
use printer::TestPrinter; use printer::TestPrinter;
#[test] #[test]
fn init_when_all_valid() { fn init_when_all_valid() -> anyhow::Result<()> {
//given //given
let fs = kxio::fs::temp().expect("temp fs");
let _env = THE_ENVIRONMENT.lock(); let _env = THE_ENVIRONMENT.lock();
let fs = kxio::fs::temp()?;
std::env::set_var("GITHUB_WORKSPACE", fs.base()); std::env::set_var("GITHUB_WORKSPACE", fs.base());
std::env::set_var("GITHUB_REPOSITORY", "repo"); std::env::set_var("GITHUB_REPOSITORY", "repo");
std::env::set_var("GITHUB_SERVER_URL", "server"); std::env::set_var("GITHUB_SERVER_URL", "server");
let net = Network::new_mock();
let mock_net = kxio::net::mock();
let net = Net::from(mock_net);
let printer = TestPrinter::default(); let printer = TestPrinter::default();
let expected = Config::builder() let expected = Config::builder()
.net(&net) .net(net.clone())
.fs(&fs) .fs(kxio::fs::new(fs.base().to_path_buf()))
.repo("repo".to_string()) .repo("repo".to_string())
.server("server".to_string()) .server("server".to_string())
.issue_pattern(issue_pattern().expect("pattern")) .issue_pattern(issue_pattern()?)
.maybe_auth_token(Some("auth".to_string())) .maybe_auth_token(Some("auth".to_string()))
.build(); .build();
//when //when
let result = init_config(&printer, &fs, &net).expect("config"); let result = init_config(&printer, net)?;
//then //then
assert_eq!(result.fs().base(), expected.fs().base()); assert_eq!(result.fs().base(), expected.fs().base());
@ -42,50 +37,65 @@ fn init_when_all_valid() {
result.issue_pattern().to_string(), result.issue_pattern().to_string(),
expected.issue_pattern().to_string() expected.issue_pattern().to_string()
); );
Ok(())
} }
#[test] #[test]
fn init_when_no_repository() { fn init_when_no_workspace() -> anyhow::Result<()> {
//given //given
let fs = kxio::fs::temp().expect("temp fs");
let _env = THE_ENVIRONMENT.lock(); let _env = THE_ENVIRONMENT.lock();
std::env::remove_var("GITHUB_WORKSPACE");
std::env::set_var("GITHUB_REPOSITORY", "repo");
std::env::set_var("GITHUB_SERVER_URL", "server");
let printer = TestPrinter::default();
//when
let result = init_config(&printer, Network::new_mock());
//then
let_assert!(Err(e) = result);
assert_eq!(e.to_string(), "GITHUB_WORKSPACE");
Ok(())
}
#[test]
fn init_when_no_repository() -> anyhow::Result<()> {
//given
let _env = THE_ENVIRONMENT.lock();
let fs = kxio::fs::temp()?;
std::env::set_var("GITHUB_WORKSPACE", fs.base()); std::env::set_var("GITHUB_WORKSPACE", fs.base());
std::env::remove_var("GITHUB_REPOSITORY"); std::env::remove_var("GITHUB_REPOSITORY");
std::env::set_var("GITHUB_SERVER_URL", "server"); std::env::set_var("GITHUB_SERVER_URL", "server");
let printer = TestPrinter::default(); let printer = TestPrinter::default();
let mock_net = kxio::net::mock();
let net = Net::from(mock_net);
//when //when
let result = init_config(&printer, &fs, &net); let result = init_config(&printer, Network::new_mock());
//then //then
let_assert!(Err(e) = result); let_assert!(Err(e) = result);
assert_eq!(e.to_string(), "GITHUB_REPOSITORY"); assert_eq!(e.to_string(), "GITHUB_REPOSITORY");
Ok(())
} }
#[test] #[test]
fn init_when_no_server_url() { fn init_when_no_server_url() -> anyhow::Result<()> {
//given //given
let fs = kxio::fs::temp().expect("temp fs");
let _env = THE_ENVIRONMENT.lock(); let _env = THE_ENVIRONMENT.lock();
let fs = kxio::fs::temp()?;
std::env::set_var("GITHUB_WORKSPACE", fs.base()); std::env::set_var("GITHUB_WORKSPACE", fs.base());
std::env::set_var("GITHUB_REPOSITORY", "repo"); std::env::set_var("GITHUB_REPOSITORY", "repo");
std::env::remove_var("GITHUB_SERVER_URL"); std::env::remove_var("GITHUB_SERVER_URL");
let printer = TestPrinter::default(); let printer = TestPrinter::default();
let mock_net = kxio::net::mock();
let net = Net::from(mock_net);
//when //when
let result = init_config(&printer, &fs, &net); let result = init_config(&printer, Network::new_mock());
//then //then
let_assert!(Err(e) = result); let_assert!(Err(e) = result);
assert_eq!(e.to_string(), "GITHUB_SERVER_URL"); assert_eq!(e.to_string(), "GITHUB_SERVER_URL");
Ok(())
} }

View file

@ -13,10 +13,7 @@ mod scanner;
pub static THE_ENVIRONMENT: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(())); pub static THE_ENVIRONMENT: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
pub fn a_config<'net, 'fs>( pub fn a_config(net: kxio::network::Network, fs: kxio::fs::FileSystem) -> Result<Config> {
net: &'net kxio::net::Net,
fs: &'fs kxio::fs::FileSystem,
) -> Result<Config<'net, 'fs>> {
Ok(Config::builder() Ok(Config::builder()
.net(net) .net(net)
.fs(fs) .fs(fs)

View file

@ -2,83 +2,84 @@
use super::*; use super::*;
use anyhow::Result; use anyhow::Result;
use kxio::network::{RequestBody, RequestMethod, SavedRequest, StatusCode};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use kxio::net::{Method, Net, Url};
use printer::TestPrinter; use printer::TestPrinter;
use url::Url;
#[tokio::test] #[tokio::test]
async fn run_with_some_invalids() /* -> Result<()> */ async fn run_with_some_invalids() -> Result<()> {
{
//given //given
let mock_net = kxio::net::mock(); let mut net = kxio::network::MockNetwork::new();
mock_net net.add_get_response(
.on(Method::GET) "https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open",
.url( StatusCode::OK,
Url::parse("https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open") r#"[{"number": 13}]"#,
.expect("parse url"), );
)
.respond(
mock_net
.response()
.status(200)
.body(r#"[{"number": 13}]"#)
.expect("response body"),
);
let net = Net::from(mock_net);
let fs = kxio::fs::temp().expect("temp fs");
fs.file(&fs.base().join("file_with_invalids.txt"))
.write(include_str!("data/file_with_invalids.txt"))
.expect("write file with invalids");
fs.file(&fs.base().join("file_with_valids.txt"))
.write(include_str!("data/file_with_valids.txt"))
.expect("write file with valids");
let _env = THE_ENVIRONMENT.lock(); let _env = THE_ENVIRONMENT.lock();
let fs = kxio::fs::temp()?;
fs.file_write(
&fs.base().join("file_with_invalids.txt"),
include_str!("data/file_with_invalids.txt"),
)?;
fs.file_write(
&fs.base().join("file_with_valids.txt"),
include_str!("data/file_with_valids.txt"),
)?;
std::env::set_var("GITHUB_WORKSPACE", fs.base()); std::env::set_var("GITHUB_WORKSPACE", fs.base());
std::env::set_var("GITHUB_REPOSITORY", "kemitix/test"); std::env::set_var("GITHUB_REPOSITORY", "kemitix/test");
std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net"); std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net");
//when //when
let result = run(&TestPrinter::default(), &fs, &net).await; let result = run(&TestPrinter::default(), net.clone().into()).await;
//then //then
assert!(result.is_err()); // there is an invalid file assert!(result.is_err()); // there is an invalid file
let requests = net.requests();
assert_eq!(
requests,
vec![SavedRequest::new(
RequestMethod::Get,
"https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open",
RequestBody::None,
)]
);
Ok(())
} }
#[tokio::test] #[tokio::test]
async fn run_with_no_invalids() { async fn run_with_no_invalids() -> Result<()> {
//given //given
let mock_net = kxio::net::mock(); let mut net = kxio::network::MockNetwork::new();
mock_net net.add_get_response(
.on(Method::GET) "https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open",
.url( StatusCode::OK,
Url::parse("https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open") r#"[{"number":23},{"number":43}]"#,
.expect("parse url"), );
)
.respond(
mock_net
.response()
.status(200)
.body(r#"[{"number":23},{"number":43}]"#)
.expect("response body"),
);
let net = Net::from(mock_net);
let fs = kxio::fs::temp().expect("temp fs");
fs.file(&fs.base().join("file_with_valids.txt"))
.write(include_str!("data/file_with_valids.txt"))
.expect("write file with valids");
let _env = THE_ENVIRONMENT.lock(); let _env = THE_ENVIRONMENT.lock();
let fs = kxio::fs::temp()?;
fs.file_write(
&fs.base().join("file_with_valids.txt"),
include_str!("data/file_with_valids.txt"),
)?;
std::env::set_var("GITHUB_WORKSPACE", fs.base()); std::env::set_var("GITHUB_WORKSPACE", fs.base());
std::env::set_var("GITHUB_REPOSITORY", "kemitix/test"); std::env::set_var("GITHUB_REPOSITORY", "kemitix/test");
std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net"); std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net");
//when //when
let result = run(&TestPrinter::default(), &fs, &net).await; let result = run(&TestPrinter::default(), net.clone().into()).await;
//then //then
assert!(result.is_ok()); // there is an invalid file assert!(result.is_ok()); // there is an invalid file
let requests = net.requests();
assert_eq!(
requests,
vec![SavedRequest::new(
RequestMethod::Get,
"https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open",
RequestBody::None,
)]
);
Ok(())
} }

View file

@ -1,44 +1,42 @@
use crate::scanner::FileScanner;
// //
use super::*; use super::*;
use std::{cell::RefCell, collections::HashSet, path::PathBuf}; use std::{cell::RefCell, collections::HashSet, fs::File, io::Write, path::PathBuf};
use crate::scanner::FileScanner;
use issues::Issue; use issues::Issue;
use kxio::net::Net;
use model::Config; use model::Config;
use patterns::issue_pattern; use patterns::issue_pattern;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use printer::TestPrinter; use printer::TestPrinter;
#[test] #[test]
fn find_markers_in_dir() { fn find_markers_in_dir() -> anyhow::Result<()> {
//given //given
let fs = kxio::fs::temp().expect("temp fs"); let fs = kxio::fs::temp()?;
let file_with_invalids = fs.base().join("file_with_invalids.txt"); let file_with_invalids = fs.base().join("file_with_invalids.txt");
fs.file(&file_with_invalids) fs.file_write(
.write(include_str!("data/file_with_invalids.txt")) &file_with_invalids,
.expect("write with invalids"); include_str!("data/file_with_invalids.txt"),
fs.file(&fs.base().join("file_with_valids.txt")) )?;
.write(include_str!("data/file_with_valids.txt")) fs.file_write(
.expect("write with valids"); &fs.base().join("file_with_valids.txt"),
include_str!("data/file_with_valids.txt"),
let mock_net = kxio::net::mock(); )?;
let net = Net::from(mock_net);
let config = Config::builder() let config = Config::builder()
.net(&net) .net(kxio::network::Network::new_mock())
.fs(&fs) .fs(fs.clone())
.server("".to_string()) .server("".to_string())
.repo("".to_string()) .repo("".to_string())
.issue_pattern(issue_pattern().expect("pattern")) .issue_pattern(issue_pattern()?)
.build(); .build();
let issues = HashSet::from_iter(vec![Issue::new(23), Issue::new(43)]); let issues = HashSet::from_iter(vec![Issue::new(23), Issue::new(43)]);
let printer = TestPrinter::default(); let printer = TestPrinter::default();
//when //when
let errors = find_markers(&printer, &config, issues, &DefaultFileScanner).expect("when"); let errors = find_markers(&printer, &config, issues, &DefaultFileScanner)?;
//then //then
assert_eq!( assert_eq!(
@ -47,37 +45,37 @@ fn find_markers_in_dir() {
"- Issue number missing: file_with_invalids.txt#3:\n It contains a todo comment: // TODO: this is it\n", "- Issue number missing: file_with_invalids.txt#3:\n It contains a todo comment: // TODO: this is it\n",
"- Issue number missing: file_with_invalids.txt#5:\n It also contains a fix-me comment: // FIXME: and this is it\n", "- Issue number missing: file_with_invalids.txt#5:\n It also contains a fix-me comment: // FIXME: and this is it\n",
"- Closed/Invalid Issue: (3) file_with_invalids.txt#9:\n We also have a todo comment: // TODO: (#3) and it has an issue number, but it is closed\n", "- Closed/Invalid Issue: (3) file_with_invalids.txt#9:\n We also have a todo comment: // TODO: (#3) and it has an issue number, but it is closed\n",
format!(">> 3 errors in {}\n", file_with_invalids.strip_prefix(fs.base()).expect("strip prefix").to_string_lossy()).as_str() format!(">> 3 errors in {}\n", file_with_invalids.strip_prefix(fs.base())?.to_string_lossy()).as_str()
] ]
); );
assert_eq!(errors, 3); assert_eq!(errors, 3);
Ok(())
} }
#[test] #[test]
fn skips_binary_files() { fn skips_binary_files() -> Result<()> {
//given //given
let fs = kxio::fs::temp().expect("temp fs"); let fs = kxio::fs::temp()?;
let binary_path = fs.base().join("binary_file.bin"); let binary_path = fs.base().join("binary_file.bin");
fs.file(&binary_path) let mut binary_file = File::create(binary_path)?;
.write([0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) binary_file.write_all(&[0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])?;
.expect("write binary file");
let text_path = fs.base().join("text_file.txt"); let text_path = fs.base().join("text_file.txt");
fs.file(&text_path) fs.file_write(&text_path, "text contents")?;
.write("text contents")
.expect("write file");
let mock_net = kxio::net::mock(); let net = kxio::network::Network::new_mock();
let net = Net::from(mock_net); let config = a_config(net, fs)?;
let config = a_config(&net, &fs).expect("config");
let issues = HashSet::new(); let issues = HashSet::new();
let file_scanner = TestFileScanner::default(); let file_scanner = TestFileScanner::default();
let printer = TestPrinter::default(); let printer = TestPrinter::default();
//when //when
find_markers(&printer, &config, issues, &file_scanner).expect("when"); find_markers(&printer, &config, issues, &file_scanner)?;
//then //then
assert_eq!(file_scanner.scanned.take(), vec![text_path]); assert_eq!(file_scanner.scanned.take(), vec![text_path]);
Ok(())
} }
#[derive(Default)] #[derive(Default)]