Skip to content

Commit 181a56d

Browse files
authored
test(authn): table-ify the spiffe_id parser tests (#2733)
1 parent 18796a8 commit 181a56d

3 files changed

Lines changed: 147 additions & 131 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/authn/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,8 @@ tonic = { workspace = true }
3434
tower = { workspace = true }
3535
tracing = { workspace = true }
3636

37+
[dev-dependencies]
38+
carbide-test-support = { path = "../test-support" }
39+
3740
[lints]
3841
workspace = true

crates/authn/src/spiffe_id.rs

Lines changed: 143 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ fn is_valid_trust_domain_char(c: char) -> bool {
377377

378378
#[cfg(test)]
379379
mod tests {
380+
use carbide_test_support::Outcome::*;
381+
use carbide_test_support::scenarios;
382+
380383
use super::*;
381384

382385
pub(crate) const TD_CHARS: &[char] = &[
@@ -392,34 +395,24 @@ mod tests {
392395
'2', '3', '4', '5', '6', '7', '8', '9', '.', '-', '_',
393396
];
394397

395-
macro_rules! spiffe_id_success_tests {
396-
($($name:ident: $value:expr,)*) => {
397-
$(
398-
#[test]
399-
fn $name() {
400-
let (input, expected) = $value;
401-
let spiffe_id = SpiffeId::from_str(input).unwrap();
402-
assert_eq!(spiffe_id, expected);
398+
#[test]
399+
fn spiffe_id_parses_valid_inputs() {
400+
scenarios!(
401+
run = SpiffeId::from_str;
402+
"valid SPIFFE ID without a path" {
403+
"spiffe://trustdomain" => Yields(SpiffeId {
404+
trust_domain: TrustDomain::from_str("trustdomain").unwrap(),
405+
path: "".to_string(),
406+
}),
403407
}
404-
)*
405-
}
406-
}
407408

408-
spiffe_id_success_tests! {
409-
from_valid_spiffe_id_str: (
410-
"spiffe://trustdomain",
411-
SpiffeId {
412-
trust_domain: TrustDomain::from_str("trustdomain").unwrap(),
413-
path: "".to_string(),
409+
"valid URI with a path" {
410+
"spiffe://trustdomain/path/element" => Yields(SpiffeId {
411+
trust_domain: TrustDomain::from_str("trustdomain").unwrap(),
412+
path: "/path/element".to_string(),
413+
}),
414414
}
415-
),
416-
from_valid_uri_str: (
417-
"spiffe://trustdomain/path/element",
418-
SpiffeId {
419-
trust_domain: TrustDomain::from_str("trustdomain").unwrap(),
420-
path: "/path/element".to_string(),
421-
}
422-
),
415+
);
423416
}
424417

425418
#[test]
@@ -469,80 +462,82 @@ mod tests {
469462
assert_eq!(spiffe_id.path, "/path");
470463
}
471464

472-
macro_rules! spiffe_id_error_tests {
473-
($($name:ident: $value:expr,)*) => {
474-
$(
475-
#[test]
476-
fn $name() {
477-
let (input, expected_error) = $value;
478-
let spiffe_id = SpiffeId::from_str(input);
479-
let error = spiffe_id.unwrap_err();
465+
#[test]
466+
fn spiffe_id_rejects_invalid_inputs() {
467+
scenarios!(
468+
run = SpiffeId::from_str;
469+
"empty string" {
470+
"" => FailsWith(SpiffeIdError::Empty),
471+
}
480472

481-
assert_eq!(error, expected_error);
473+
"too short to hold a scheme" {
474+
"spif" => FailsWith(SpiffeIdError::WrongScheme),
475+
}
476+
477+
"bare IP address" {
478+
"192.168.2.2:6688" => FailsWith(SpiffeIdError::WrongScheme),
479+
}
480+
481+
"non-spiffe scheme" {
482+
"http://domain.test/path/element" => FailsWith(SpiffeIdError::WrongScheme),
483+
}
484+
485+
"single-slash authority" {
486+
"spiffe:/path/element" => FailsWith(SpiffeIdError::WrongScheme),
487+
}
488+
489+
"empty authority after slashes" {
490+
"spiffe:///path/element" => FailsWith(SpiffeIdError::MissingTrustDomain),
491+
}
492+
493+
"no authority slashes" {
494+
"spiffe:path/element" => FailsWith(SpiffeIdError::WrongScheme),
495+
}
496+
497+
"query string in path" {
498+
"spiffe://domain.test/path/element?query=1" => {
499+
FailsWith(SpiffeIdError::BadPathSegmentChar)
500+
}
501+
}
502+
503+
"fragment in path" {
504+
"spiffe://domain.test/path/element#fragment-1" => {
505+
FailsWith(SpiffeIdError::BadPathSegmentChar)
506+
}
507+
}
508+
509+
"port in trust domain" {
510+
"spiffe://domain.test:8080/path/element" => {
511+
FailsWith(SpiffeIdError::BadTrustDomainChar)
512+
}
513+
}
514+
515+
"user info in trust domain" {
516+
"spiffe://user:password@test.org/path/element" => {
517+
FailsWith(SpiffeIdError::BadTrustDomainChar)
518+
}
519+
}
520+
521+
"trailing slash, no path" {
522+
"spiffe://test.org/" => FailsWith(SpiffeIdError::TrailingSlash),
482523
}
483-
)*
484-
}
485-
}
486524

487-
spiffe_id_error_tests! {
488-
from_empty_str: ("", SpiffeIdError::Empty),
489-
from_short_invalid_str: ("spif", SpiffeIdError::WrongScheme),
490-
from_str_invalid_uri_str_contains_ip_address: (
491-
"192.168.2.2:6688",
492-
SpiffeIdError::WrongScheme,
493-
),
494-
from_str_uri_str_invalid_scheme: (
495-
"http://domain.test/path/element",
496-
SpiffeIdError::WrongScheme,
497-
),
498-
from_str_uri_str_empty_authority: (
499-
"spiffe:/path/element",
500-
SpiffeIdError::WrongScheme,
501-
),
502-
from_str_uri_str_empty_authority_after_slashes: (
503-
"spiffe:///path/element",
504-
SpiffeIdError::MissingTrustDomain,
505-
),
506-
from_str_uri_str_empty_authority_no_slashes: (
507-
"spiffe:path/element",
508-
SpiffeIdError::WrongScheme,
509-
),
510-
from_str_uri_str_with_query: (
511-
"spiffe://domain.test/path/element?query=1",
512-
SpiffeIdError::BadPathSegmentChar,
513-
),
514-
from_str_uri_str_with_fragment: (
515-
"spiffe://domain.test/path/element#fragment-1",
516-
SpiffeIdError::BadPathSegmentChar,
517-
),
518-
from_str_uri_str_with_port: (
519-
"spiffe://domain.test:8080/path/element",
520-
SpiffeIdError::BadTrustDomainChar,
521-
),
522-
from_str_uri_str_with_user_info: (
523-
"spiffe://user:password@test.org/path/element",
524-
SpiffeIdError::BadTrustDomainChar,
525-
),
526-
from_str_uri_str_with_trailing_slash: (
527-
"spiffe://test.org/",
528-
SpiffeIdError::TrailingSlash,
529-
),
530-
from_str_uri_str_with_emtpy_segment: (
531-
"spiffe://test.org//",
532-
SpiffeIdError::EmptySegment,
533-
),
534-
from_str_uri_str_with_path_with_trailing_slash: (
535-
"spiffe://test.org/path/other/",
536-
SpiffeIdError::TrailingSlash,
537-
),
538-
from_str_uri_str_with_dot_segment: (
539-
"spiffe://test.org/./other",
540-
SpiffeIdError::DotSegment,
541-
),
542-
from_str_uri_str_with_double_dot_segment: (
543-
"spiffe://test.org/../other",
544-
SpiffeIdError::DotSegment,
545-
),
525+
"empty segment" {
526+
"spiffe://test.org//" => FailsWith(SpiffeIdError::EmptySegment),
527+
}
528+
529+
"trailing slash after a path" {
530+
"spiffe://test.org/path/other/" => FailsWith(SpiffeIdError::TrailingSlash),
531+
}
532+
533+
"dot segment" {
534+
"spiffe://test.org/./other" => FailsWith(SpiffeIdError::DotSegment),
535+
}
536+
537+
"double-dot segment" {
538+
"spiffe://test.org/../other" => FailsWith(SpiffeIdError::DotSegment),
539+
}
540+
);
546541
}
547542

548543
#[test]
@@ -612,47 +607,64 @@ mod tests {
612607
}
613608
}
614609

615-
macro_rules! trust_domain_success_tests {
616-
($($name:ident: $value:expr,)*) => {
617-
$(
618-
#[test]
619-
fn $name() {
620-
let (input, expected) = $value;
621-
let trust_domain = TrustDomain::new(input).unwrap();
622-
assert_eq!(trust_domain, expected);
610+
#[test]
611+
fn trust_domain_parses_valid_inputs() {
612+
scenarios!(
613+
run = TrustDomain::new;
614+
"bare domain name" {
615+
"trustdomain" => Yields(TrustDomain {
616+
name: "trustdomain".to_string(),
617+
}),
623618
}
624-
)*
625-
}
626-
}
627619

628-
trust_domain_success_tests! {
629-
from_str_domain: ("trustdomain", TrustDomain{name: "trustdomain".to_string()}),
630-
from_str_spiffeid: ("spiffe://other.test", TrustDomain{name: "other.test".to_string()}),
631-
from_str_spiffeid_with_path: ("spiffe://domain.test/path/element", TrustDomain{name: "domain.test".to_string()}),
632-
}
620+
"SPIFFE ID without a path" {
621+
"spiffe://other.test" => Yields(TrustDomain {
622+
name: "other.test".to_string(),
623+
}),
624+
}
633625

634-
macro_rules! trust_domain_error_tests {
635-
($($name:ident: $value:expr,)*) => {
636-
$(
637-
#[test]
638-
fn $name() {
639-
let (input, expected_error) = $value;
640-
let trust_domain = TrustDomain::new(input);
641-
let error = trust_domain.unwrap_err();
642-
assert_eq!(error, expected_error);
626+
"SPIFFE ID with a path" {
627+
"spiffe://domain.test/path/element" => Yields(TrustDomain {
628+
name: "domain.test".to_string(),
629+
}),
643630
}
644-
)*
645-
}
631+
);
646632
}
647633

648-
trust_domain_error_tests! {
649-
trust_domain_from_empty_str: ("", SpiffeIdError::MissingTrustDomain),
650-
trust_domain_from_invalid_scheme: ("other://domain.test", SpiffeIdError::WrongScheme),
651-
trust_domain_from_uri_with_port: ("spiffe://domain.test:80", SpiffeIdError::BadTrustDomainChar),
652-
trust_domain_from_uri_with_userinfo: ("spiffe://user:pass@domain.test", SpiffeIdError::BadTrustDomainChar),
653-
trust_domain_from_uri_with_invalid_domain: ("spiffe:// domain.test", SpiffeIdError::BadTrustDomainChar),
654-
trust_domain_from_uri_with_empty_scheme: ("://domain.test", SpiffeIdError::WrongScheme),
655-
trust_domain_from_uri_with_empty_domain: ("spiffe:///path", SpiffeIdError::MissingTrustDomain),
634+
#[test]
635+
fn trust_domain_rejects_invalid_inputs() {
636+
scenarios!(
637+
run = TrustDomain::new;
638+
"empty string" {
639+
"" => FailsWith(SpiffeIdError::MissingTrustDomain),
640+
}
641+
642+
"non-spiffe scheme" {
643+
"other://domain.test" => FailsWith(SpiffeIdError::WrongScheme),
644+
}
645+
646+
"port in the domain" {
647+
"spiffe://domain.test:80" => FailsWith(SpiffeIdError::BadTrustDomainChar),
648+
}
649+
650+
"user info in the domain" {
651+
"spiffe://user:pass@domain.test" => {
652+
FailsWith(SpiffeIdError::BadTrustDomainChar)
653+
}
654+
}
655+
656+
"space in the domain" {
657+
"spiffe:// domain.test" => FailsWith(SpiffeIdError::BadTrustDomainChar),
658+
}
659+
660+
"empty scheme" {
661+
"://domain.test" => FailsWith(SpiffeIdError::WrongScheme),
662+
}
663+
664+
"empty domain" {
665+
"spiffe:///path" => FailsWith(SpiffeIdError::MissingTrustDomain),
666+
}
667+
);
656668
}
657669

658670
#[test]

0 commit comments

Comments
 (0)