Refactor the construction of the `Mistrust` type in tests.

This patch refactors how we construct the `Mistrust` type in the tests
found in the fs-mistrust crate such that it is possible to construct an
instance of the `Mistrust` type using a set of operations available via
the `MistrustBuilder`'s methods.

We handle some of the portability issues found while testing this code
on Windows in the convenience function `mistrust_build()` instead of
having duplicated code in multiple test cases.

See: tpo/core/arti#557.
This commit is contained in:
Alexander Færøy 2022-08-29 16:22:57 +02:00
parent 514aaf41b8
commit d208706280
2 changed files with 93 additions and 97 deletions

View File

@ -815,7 +815,7 @@ impl<'a> Verifier<'a> {
mod test {
#![allow(clippy::unwrap_used)]
use super::*;
use testing::Dir;
use testing::{mistrust_build, Dir, MistrustOp};
#[cfg(target_family = "unix")]
use testing::LinkType;
@ -833,20 +833,10 @@ mod test {
d.chmod("e/f", 0o777);
d.link_rel(LinkType::Dir, "a/b/c", "d");
let mut b = Mistrust::builder();
let m = b
.ignore_prefix(d.canonical_root());
#[cfg(all(
target_family = "unix",
not(target_os = "ios"),
not(target_os = "android")
))]
let m = m.trust_no_group_id();
let m = m
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustNoGroupId(),
]);
// /a/b/c should be fine...
m.check_directory(d.path("a/b/c")).unwrap();
@ -874,18 +864,14 @@ mod test {
}
// With normal settings should be okay...
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.build()
.unwrap();
let m = mistrust_build(&[MistrustOp::IgnorePrefix(d.canonical_root())]);
m.check_directory(d.path("a/b")).unwrap();
// With admin_only, it'll fail.
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.trust_admin_only()
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustAdminOnly(),
]);
let err = m.check_directory(d.path("a/b")).unwrap_err();
assert!(matches!(err, Error::BadOwner(_, _)));
@ -900,20 +886,10 @@ mod test {
d.chmod("a", 0o700);
d.chmod("b", 0o600);
let mut b = Mistrust::builder();
let m = b
.ignore_prefix(d.canonical_root());
#[cfg(all(
target_family = "unix",
not(target_os = "ios"),
not(target_os = "android")
))]
let m = m.trust_no_group_id();
let m = m
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustNoGroupId(),
]);
// If we insist stuff is its own type, it works fine.
m.verifier().require_directory().check(d.path("a")).unwrap();
@ -944,20 +920,10 @@ mod test {
d.chmod("a/b", 0o750);
d.chmod("a/b/c", 0o640);
let mut b = Mistrust::builder();
let m = b
.ignore_prefix(d.canonical_root());
#[cfg(all(
target_family = "unix",
not(target_os = "ios"),
not(target_os = "android")
))]
let m = m.trust_no_group_id();
let m = m
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustNoGroupId(),
]);
// These will fail, since the file or directory is readable.
let e = m.verifier().check(d.path("a/b")).unwrap_err();
@ -982,20 +948,10 @@ mod test {
d.chmod("a", 0o700);
d.chmod("a/b", 0o700);
let mut b = Mistrust::builder();
let m = b
.ignore_prefix(d.canonical_root());
#[cfg(all(
target_family = "unix",
not(target_os = "ios"),
not(target_os = "android")
))]
let m = m.trust_no_group_id();
let m = m
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustNoGroupId(),
]);
// Only one error occurs, so we get that error.
let e = m
@ -1029,10 +985,7 @@ mod test {
d.chmod("a/b", 0o755);
d.chmod("a/b/c", 0o700);
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.build()
.unwrap();
let m = mistrust_build(&[MistrustOp::IgnorePrefix(d.canonical_root())]);
// `a` is world-writable, so the first check will fail.
m.check_directory(d.path("a/b/c")).unwrap_err();
@ -1058,11 +1011,10 @@ mod test {
d.chmod("a", 0o770);
d.chmod("a/b", 0o770);
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.trust_no_group_id()
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustNoGroupId(),
]);
// By default, we shouldn't be accept this directory, since it is
// group-writable.
@ -1072,20 +1024,19 @@ mod test {
// But we can make the group trusted, which will make it okay for the
// directory to be group-writable.
let gid = d.path("a/b").metadata().unwrap().gid();
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.trust_group(gid)
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustGroup(gid),
]);
m.check_directory(d.path("a/b")).unwrap();
// OTOH, if we made a _different_ group trusted, it'll fail.
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.trust_group(gid ^ 1)
.build()
.unwrap();
let m = mistrust_build(&[
MistrustOp::IgnorePrefix(d.canonical_root()),
MistrustOp::TrustGroup(gid ^ 1),
]);
let e = m.check_directory(d.path("a/b")).unwrap_err();
assert!(matches!(e, Error::BadPermission(..)));
@ -1096,10 +1047,7 @@ mod test {
let d = Dir::new();
d.dir("a/b");
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.build()
.unwrap();
let m = mistrust_build(&[MistrustOp::IgnorePrefix(d.canonical_root())]);
#[cfg(target_family = "unix")]
{
@ -1133,10 +1081,7 @@ mod test {
d.chmod("a/b/c", 0o755);
d.chmod("a/b/c/d", 0o666);
let m = Mistrust::builder()
.ignore_prefix(d.canonical_root())
.build()
.unwrap();
let m = mistrust_build(&[MistrustOp::IgnorePrefix(d.canonical_root())]);
// A check should work...
m.check_directory(d.path("a/b")).unwrap();
@ -1165,10 +1110,7 @@ mod test {
d.chmod("a/b/c", 0o777);
d.chmod("a/b/c/d", 0o666);
let m = Mistrust::builder()
.dangerously_trust_everyone()
.build()
.unwrap();
let m = mistrust_build(&[MistrustOp::DangerouslyTrustEveryone()]);
// This is fine.
m.check_directory(d.path("a/b/c")).unwrap();

View File

@ -12,6 +12,8 @@ use std::{
#[cfg(target_family = "unix")]
use std::os::unix::{self, fs::PermissionsExt};
use crate::Mistrust;
/// A temporary directory with convenience functions to build items inside it.
#[derive(Debug)]
pub(crate) struct Dir {
@ -143,3 +145,55 @@ impl Dir {
}
}
}
/// A utility type to represent the different operations available for a MistrustBuilder.
#[derive(Debug)]
pub(crate) enum MistrustOp<'a> {
IgnorePrefix(&'a Path),
DangerouslyTrustEveryone(),
TrustNoGroupId(),
#[cfg(target_family = "unix")]
TrustAdminOnly(),
#[cfg(target_family = "unix")]
TrustGroup(u32),
}
/// A convenience function to construct a Mistrust type using a set of given operations.
pub(crate) fn mistrust_build(ops: &[MistrustOp]) -> Mistrust {
ops.iter()
.fold(&mut Mistrust::builder(), |m, op| {
match op {
MistrustOp::IgnorePrefix(prefix) => m.ignore_prefix(prefix),
MistrustOp::DangerouslyTrustEveryone() => m.dangerously_trust_everyone(),
MistrustOp::TrustNoGroupId() => {
// We call `m.trust_no_group_id()` on platforms where it is available.
// Otherwise, we simply return `m` unmodified here.
#[cfg(all(
target_family = "unix",
not(target_os = "ios"),
not(target_os = "android")
))]
return m.trust_no_group_id();
#[cfg(not(all(
target_family = "unix",
not(target_os = "ios"),
not(target_os = "android")
)))]
return m;
}
#[cfg(target_family = "unix")]
MistrustOp::TrustAdminOnly() => m.trust_admin_only(),
#[cfg(target_family = "unix")]
MistrustOp::TrustGroup(gid) => m.trust_group(*gid),
}
})
.build()
.unwrap()
}