Merge pull request #39 from constantoine/add_test_coverage
Add coverage for rfc.rs
This commit is contained in:
commit
c36b3a9507
|
@ -15,7 +15,7 @@ categories = ["authentication", "web-programming"]
|
|||
features = [ "qr", "serde_support", "otpauth" ]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["qr", "gen_secret"]
|
||||
otpauth = ["url", "urlencoding"]
|
||||
qr = ["qrcodegen", "image", "base64", "otpauth"]
|
||||
serde_support = ["serde"]
|
||||
|
|
96
src/lib.rs
96
src/lib.rs
|
@ -750,6 +750,31 @@ mod tests {
|
|||
assert_eq!(url.as_str(), "otpauth://totp/Github:constantoine%40github.com?issuer=Github&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=6&algorithm=SHA512");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "otpauth", feature = "gen_secret"))]
|
||||
fn ttl() {
|
||||
let secret = Secret::default();
|
||||
let totp_rfc = Rfc6238::with_defaults(secret.to_bytes().unwrap()).unwrap();
|
||||
let totp = TOTP::from_rfc6238(totp_rfc);
|
||||
assert!(totp.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn ttl_ok() {
|
||||
let totp = TOTP::new(
|
||||
Algorithm::SHA512,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
"TestSecretSuperSecret",
|
||||
Some("Github".to_string()),
|
||||
"constantoine@github.com".to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(totp.ttl().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "otpauth"))]
|
||||
fn returns_base32() {
|
||||
|
@ -889,6 +914,24 @@ mod tests {
|
|||
assert_eq!(totp.step, 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_query_sha512() {
|
||||
let totp = TOTP::<Vec<u8>>::from_url("otpauth://totp/GitHub:test?secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA512").unwrap();
|
||||
assert_eq!(
|
||||
totp.secret,
|
||||
base32::decode(
|
||||
base32::Alphabet::RFC4648 { padding: false },
|
||||
"KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ"
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(totp.algorithm, Algorithm::SHA512);
|
||||
assert_eq!(totp.digits, 8);
|
||||
assert_eq!(totp.skew, 1);
|
||||
assert_eq!(totp.step, 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_to_url() {
|
||||
|
@ -906,6 +949,24 @@ mod tests {
|
|||
assert_eq!(totp.get_url(), totp_bis.get_url());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_unknown_param() {
|
||||
let totp = TOTP::<Vec<u8>>::from_url("otpauth://totp/GitHub:test?secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA256&foo=bar").unwrap();
|
||||
assert_eq!(
|
||||
totp.secret,
|
||||
base32::decode(
|
||||
base32::Alphabet::RFC4648 { padding: false },
|
||||
"KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ"
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(totp.algorithm, Algorithm::SHA256);
|
||||
assert_eq!(totp.digits, 8);
|
||||
assert_eq!(totp.skew, 1);
|
||||
assert_eq!(totp.step, 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_issuer_special() {
|
||||
|
@ -943,6 +1004,24 @@ mod tests {
|
|||
assert_eq!(totp.issuer.unwrap(), "GitHub");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_wrong_scheme() {
|
||||
let totp = TOTP::<Vec<u8>>::from_url("http://totp/GitHub:test?issuer=GitHub&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA256");
|
||||
assert!(totp.is_err());
|
||||
let err = totp.unwrap_err();
|
||||
assert!(matches!(err, TotpUrlError::Scheme(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_wrong_algo() {
|
||||
let totp = TOTP::<Vec<u8>>::from_url("otpauth://totp/GitHub:test?issuer=GitHub&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=MD5");
|
||||
assert!(totp.is_err());
|
||||
let err = totp.unwrap_err();
|
||||
assert!(matches!(err, TotpUrlError::Algorithm(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_query_different_issuers() {
|
||||
|
@ -981,4 +1060,21 @@ mod tests {
|
|||
"025809c9db9c2c918930e018549c90929a083ee757156737812bad40ded64312c1526c73d8f2f59d5c203b97141ddfc331b1192e234f4f43257f50a6d05e382f"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "qr")]
|
||||
fn generates_qr_ok() {
|
||||
let totp = TOTP::new(
|
||||
Algorithm::SHA1,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
"TestSecretSuperSecret",
|
||||
Some("Github".to_string()),
|
||||
"constantoine@github.com".to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
let qr = totp.get_qr();
|
||||
assert!(qr.is_ok());
|
||||
}
|
||||
}
|
||||
|
|
36
src/rfc.rs
36
src/rfc.rs
|
@ -313,6 +313,21 @@ mod tests {
|
|||
assert!(totp.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn rfc_with_default_set_values() {
|
||||
let mut rfc = Rfc6238::with_defaults(GOOD_SECRET.to_string()).unwrap();
|
||||
let ok = rfc.digits(8);
|
||||
assert!(ok.is_ok());
|
||||
assert_eq!(rfc.account_name, "");
|
||||
assert_eq!(rfc.issuer, Some("".to_string()));
|
||||
rfc.issuer("Github".to_string());
|
||||
rfc.account_name("constantoine".to_string());
|
||||
assert_eq!(rfc.account_name, "constantoine");
|
||||
assert_eq!(rfc.issuer, Some("Github".to_string()));
|
||||
assert_eq!(rfc.digits, 8)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "otpauth"))]
|
||||
fn rfc_with_default_set_values() {
|
||||
|
@ -325,4 +340,25 @@ mod tests {
|
|||
assert!(ok.is_ok());
|
||||
assert_eq!(rfc.digits, 8)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "otpauth"))]
|
||||
fn digits_error() {
|
||||
let error = crate::Rfc6238Error::InvalidDigits(9);
|
||||
assert_eq!(
|
||||
error.to_string(),
|
||||
"Implementations MUST extract a 6-digit code at a minimum and possibly 7 and 8-digit code. 9 digits is not allowed".to_string()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "otpauth"))]
|
||||
fn secret_length_error() {
|
||||
let error = Rfc6238Error::SecretTooSmall(120);
|
||||
assert_eq!(
|
||||
error.to_string(),
|
||||
"The length of the shared secret MUST be at least 128 bits. 120 bits is not enough"
|
||||
.to_string()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,9 +237,33 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(feature = "gen_secret")]
|
||||
fn secret_gen_secret() {
|
||||
match Secret::generate_secret() {
|
||||
Secret::Raw(secret) => assert_eq!(secret.len(), 20),
|
||||
Secret::Encoded(_) => panic!("should be raw"),
|
||||
}
|
||||
let sec = Secret::generate_secret();
|
||||
|
||||
assert!(matches!(sec, Secret::Raw(_)));
|
||||
assert_eq!(sec.to_bytes().unwrap().len(), 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen_secret")]
|
||||
fn secret_gen_default() {
|
||||
let sec = Secret::default();
|
||||
|
||||
assert!(matches!(sec, Secret::Raw(_)));
|
||||
assert_eq!(sec.to_bytes().unwrap().len(), 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gen_secret")]
|
||||
fn secret_empty() {
|
||||
let non_ascii = vec![240, 159, 146, 150];
|
||||
let sec = Secret::Encoded(std::str::from_utf8(&non_ascii).unwrap().to_owned());
|
||||
|
||||
let to_r = sec.to_raw();
|
||||
|
||||
assert!(to_r.is_err());
|
||||
|
||||
let to_b = sec.to_bytes();
|
||||
|
||||
assert!(to_b.is_err());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue