Files
dev/src/natu/natu_test.rs

287 lines
7.4 KiB
Rust

use std::path::{Path, PathBuf};
use googletest::matchers::{contains, eq, is_true};
use googletest::{OrFail, expect_that, gtest};
use status::Code;
use natu::SourceFile;
fn fixture_source(path: &str) -> googletest::Result<SourceFile> {
Ok(SourceFile {
path: PathBuf::from(path),
source: std::fs::read_to_string(fixture_path(path)?).or_fail()?,
})
}
fn fixture_path(path: &str) -> googletest::Result<PathBuf> {
if Path::new(path).exists() {
return Ok(PathBuf::from(path));
}
let runfiles = PathBuf::from(std::env::var("TEST_SRCDIR").or_fail()?);
let workspace = std::env::var("TEST_WORKSPACE").or_fail()?;
Ok(runfiles.join(workspace).join("src/natu").join(path))
}
#[gtest]
fn natu_accepts_clean_source() -> googletest::Result<()> {
let report = natu::future_sight(vec![fixture_source("testdata/clean.nix")?]).or_fail()?;
expect_that!(report.is_clean(), is_true());
Ok(())
}
#[gtest]
fn natu_rejects_invalid_source() -> googletest::Result<()> {
let error = natu::future_sight(vec![fixture_source("testdata/invalid.nix")?])
.err()
.or_fail()?;
expect_that!(error.code(), eq(Code::FailedPrecondition));
Ok(())
}
#[gtest]
fn natu_reports_out_of_order_let_bindings() -> googletest::Result<()> {
let report = natu::future_sight(vec![fixture_source("testdata/lint_findings.nix")?]).or_fail()?;
let let_order_count = report
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.finding.rule_id == "let_order")
.count();
expect_that!(let_order_count, eq(2));
expect_that!(
report.to_string(),
eq(concat!(
"testdata/lint_findings.nix:11 [manual_inherit] Use `inherit` for this assignment\n",
"testdata/lint_findings.nix:12 [manual_inherit_from] Use `inherit` for this selected attribute\n",
"testdata/lint_findings.nix:13 [unquoted_uri] URI literals should be quoted\n",
"testdata/lint_findings.nix [let_order] Let bindings must follow dependency order\n",
" let at line 1: first, second, nested\n",
" let at line 4: nestedSecond, nestedFirst\n",
))
);
Ok(())
}
#[gtest]
fn natu_preserves_suppressed_bindings() -> googletest::Result<()> {
let report = natu::future_sight(vec![SourceFile {
path: PathBuf::from("testdata/nolint.nix"),
source: "{ config, ... }: let\n cfg = config.example; # NOLINT(let_order, single_use_binding)\n value = cfg; # NOLINT(single_use_binding)\nin value\n".into(),
}])
.or_fail()?;
expect_that!(report.is_clean(), is_true());
Ok(())
}
#[gtest]
fn natu_reports_select_dependency_order() -> googletest::Result<()> {
let report = natu::future_sight(vec![SourceFile {
path: PathBuf::from("testdata/select_dependencies.nix"),
source: r#"
let
dependency = { value = 1; };
entry = dependency.value;
in
entry
"#
.into(),
}])
.or_fail()?;
let count = report
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.finding.rule_id == "let_order")
.count();
expect_that!(count, eq(1));
Ok(())
}
#[gtest]
fn natu_reports_redundant_parameter_forwarding() -> googletest::Result<()> {
let report = natu::future_sight(vec![
SourceFile {
path: PathBuf::from("testdata/attribute_parameter.nix"),
source: r#"
{ hosts, ... }:
let
collect = { hosts }: hosts;
in
collect { inherit hosts; }
"#
.into(),
},
SourceFile {
path: PathBuf::from("testdata/plain_parameter.nix"),
source: r#"
value:
let
transform = value: value;
in
transform value
"#
.into(),
},
SourceFile {
path: PathBuf::from("testdata/curried_parameter.nix"),
source: r#"
{ hosts, ... }:
let
transform = prefix: hosts: suffix: hosts;
in
transform "prefix" hosts "suffix"
"#
.into(),
},
SourceFile {
path: PathBuf::from("testdata/local_parameter.nix"),
source: r#"
let
transform = value: value;
in
transform value
"#
.into(),
},
])
.or_fail()?;
let count = report
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.finding.rule_id == "redundant_parameter_forwarding")
.count();
expect_that!(count, eq(3));
Ok(())
}
#[gtest]
fn natu_accepts_value_captured_by_reused_lambda() -> googletest::Result<()> {
let report = natu::future_sight(vec![SourceFile {
path: PathBuf::from("testdata/captured_value.nix"),
source: r#"
let
mapper = _: captured;
captured = 1;
in
[ (mapper 1) (mapper 2) ]
"#
.into(),
}])
.or_fail()?;
expect_that!(report.is_clean(), is_true());
Ok(())
}
#[gtest]
fn natu_reports_single_use_binding() -> googletest::Result<()> {
let report = natu::future_sight(vec![SourceFile {
path: PathBuf::from("testdata/single_use_binding.nix"),
source: r#"
let
single = 1;
recursive = recursive;
in
{ inherit single recursive; }
"#
.into(),
}])
.or_fail()?;
let count = report
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.finding.rule_id == "single_use_binding")
.count();
expect_that!(count, eq(1));
Ok(())
}
#[gtest]
fn natu_reports_list_to_attrs_after_map() -> googletest::Result<()> {
let report = natu::future_sight(vec![SourceFile {
path: PathBuf::from("testdata/list_to_attrs.nix"),
source: r#"
let
generated = lib.listToAttrs (
map (item: lib.nameValuePair item item) items
);
generated_pairs = lib.listToAttrs (
concatLists (
mapAttrsToList (name: _: lib.nameValuePair name name) attrs
)
);
precomputed = lib.listToAttrs pairs;
in
{
inherit generated generated_pairs precomputed;
}
"#
.into(),
}])
.or_fail()?;
let count = report
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.finding.rule_id == "list_to_attrs_map")
.count();
expect_that!(count, eq(1));
Ok(())
}
#[gtest]
fn natu_reports_unquoted_uri() -> googletest::Result<()> {
let report = natu::future_sight(vec![fixture_source("testdata/lint_findings.nix")?]).or_fail()?;
let findings = report
.diagnostics
.iter()
.map(|diagnostic| {
(
report.files.get(diagnostic.file_id).path.clone(),
diagnostic.finding.rule_id,
)
})
.collect::<Vec<_>>();
expect_that!(
findings,
contains(eq(&(
PathBuf::from("testdata/lint_findings.nix"),
"unquoted_uri"
)))
);
Ok(())
}
#[gtest]
fn natu_reports_manual_inherit() -> googletest::Result<()> {
let report = natu::future_sight(vec![fixture_source("testdata/lint_findings.nix")?]).or_fail()?;
let manual_inherit_count = report
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.finding.rule_id == "manual_inherit")
.count();
expect_that!(manual_inherit_count, eq(1));
Ok(())
}
#[gtest]
fn natu_reports_manual_inherit_from() -> googletest::Result<()> {
let report = natu::future_sight(vec![fixture_source("testdata/lint_findings.nix")?]).or_fail()?;
let manual_inherit_from_count = report
.diagnostics
.iter()
.filter(|diagnostic| diagnostic.finding.rule_id == "manual_inherit_from")
.count();
expect_that!(manual_inherit_from_count, eq(1));
Ok(())
}