add Error test, fix clippy

This commit is contained in:
weisd
2025-06-09 11:29:23 +08:00
parent 96de65ebab
commit 91c099e35f
108 changed files with 1594 additions and 282 deletions
+3 -3
View File
@@ -1,14 +1,14 @@
use crate::error::Error as IamError;
use crate::error::{Error, Result};
use crate::policy::{iam_policy_claim_name_sa, Policy, Validator, INHERITED_POLICY_TYPE};
use crate::policy::{INHERITED_POLICY_TYPE, Policy, Validator, iam_policy_claim_name_sa};
use crate::utils;
use crate::utils::extract_claims;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use serde_json::{Value, json};
use std::collections::HashMap;
use time::macros::offset;
use time::OffsetDateTime;
use time::macros::offset;
const ACCESS_KEY_MIN_LEN: usize = 3;
const ACCESS_KEY_MAX_LEN: usize = 20;
+201
View File
@@ -160,3 +160,204 @@ pub fn is_err_no_such_group(err: &Error) -> bool {
pub fn is_err_no_such_service_account(err: &Error) -> bool {
matches!(err, Error::NoSuchServiceAccount(_))
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::{Error as IoError, ErrorKind};
#[test]
fn test_policy_error_from_io_error() {
let io_error = IoError::new(ErrorKind::PermissionDenied, "permission denied");
let policy_error: Error = io_error.into();
match policy_error {
Error::Io(inner_io) => {
assert_eq!(inner_io.kind(), ErrorKind::PermissionDenied);
assert!(inner_io.to_string().contains("permission denied"));
}
_ => panic!("Expected Io variant"),
}
}
#[test]
fn test_policy_error_other_function() {
let custom_error = "Custom policy error";
let policy_error = Error::other(custom_error);
match policy_error {
Error::Io(io_error) => {
assert!(io_error.to_string().contains(custom_error));
assert_eq!(io_error.kind(), ErrorKind::Other);
}
_ => panic!("Expected Io variant"),
}
}
#[test]
fn test_policy_error_from_crypto_error() {
// Test conversion from crypto::Error - use an actual variant
let crypto_error = crypto::Error::ErrUnexpectedHeader;
let policy_error: Error = crypto_error.into();
match policy_error {
Error::CryptoError(_) => {
// Verify the conversion worked
assert!(policy_error.to_string().contains("crypto"));
}
_ => panic!("Expected CryptoError variant"),
}
}
#[test]
fn test_policy_error_from_jwt_error() {
use jsonwebtoken::{Algorithm, DecodingKey, Validation, decode};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
exp: usize,
}
// Create an invalid JWT to generate a JWT error
let invalid_token = "invalid.jwt.token";
let key = DecodingKey::from_secret(b"secret");
let validation = Validation::new(Algorithm::HS256);
let jwt_result = decode::<Claims>(invalid_token, &key, &validation);
assert!(jwt_result.is_err());
let jwt_error = jwt_result.unwrap_err();
let policy_error: Error = jwt_error.into();
match policy_error {
Error::JWTError(_) => {
// Verify the conversion worked
assert!(policy_error.to_string().contains("jwt err"));
}
_ => panic!("Expected JWTError variant"),
}
}
#[test]
fn test_policy_error_from_serde_json() {
// Test conversion from serde_json::Error
let invalid_json = r#"{"invalid": json}"#;
let json_error = serde_json::from_str::<serde_json::Value>(invalid_json).unwrap_err();
let policy_error: Error = json_error.into();
match policy_error {
Error::Io(io_error) => {
assert_eq!(io_error.kind(), ErrorKind::Other);
}
_ => panic!("Expected Io variant"),
}
}
#[test]
fn test_policy_error_from_time_component_range() {
use time::{Date, Month};
// Create an invalid date to generate a ComponentRange error
let time_result = Date::from_calendar_date(2023, Month::January, 32); // Invalid day
assert!(time_result.is_err());
let time_error = time_result.unwrap_err();
let policy_error: Error = time_error.into();
match policy_error {
Error::Io(io_error) => {
assert_eq!(io_error.kind(), ErrorKind::Other);
}
_ => panic!("Expected Io variant"),
}
}
#[test]
#[allow(clippy::invalid_regex)]
fn test_policy_error_from_regex_error() {
use regex::Regex;
// Create an invalid regex to generate a regex error (unclosed bracket)
let regex_result = Regex::new("[");
assert!(regex_result.is_err());
let regex_error = regex_result.unwrap_err();
let policy_error: Error = regex_error.into();
match policy_error {
Error::Io(io_error) => {
assert_eq!(io_error.kind(), ErrorKind::Other);
}
_ => panic!("Expected Io variant"),
}
}
#[test]
fn test_helper_functions() {
// Test helper functions for error type checking
assert!(is_err_no_such_policy(&Error::NoSuchPolicy));
assert!(!is_err_no_such_policy(&Error::NoSuchUser("test".to_string())));
assert!(is_err_no_such_user(&Error::NoSuchUser("test".to_string())));
assert!(!is_err_no_such_user(&Error::NoSuchAccount("test".to_string())));
assert!(is_err_no_such_account(&Error::NoSuchAccount("test".to_string())));
assert!(!is_err_no_such_account(&Error::NoSuchUser("test".to_string())));
assert!(is_err_no_such_temp_account(&Error::NoSuchTempAccount("test".to_string())));
assert!(!is_err_no_such_temp_account(&Error::NoSuchAccount("test".to_string())));
assert!(is_err_no_such_group(&Error::NoSuchGroup("test".to_string())));
assert!(!is_err_no_such_group(&Error::NoSuchUser("test".to_string())));
assert!(is_err_no_such_service_account(&Error::NoSuchServiceAccount("test".to_string())));
assert!(!is_err_no_such_service_account(&Error::NoSuchAccount("test".to_string())));
}
#[test]
fn test_error_display_format() {
let test_cases = vec![
(Error::NoSuchUser("testuser".to_string()), "user 'testuser' does not exist"),
(Error::NoSuchAccount("testaccount".to_string()), "account 'testaccount' does not exist"),
(
Error::NoSuchServiceAccount("service1".to_string()),
"service account 'service1' does not exist",
),
(Error::NoSuchTempAccount("temp1".to_string()), "temp account 'temp1' does not exist"),
(Error::NoSuchGroup("group1".to_string()), "group 'group1' does not exist"),
(Error::NoSuchPolicy, "policy does not exist"),
(Error::PolicyInUse, "policy in use"),
(Error::GroupNotEmpty, "group not empty"),
(Error::InvalidArgument, "invalid arguments specified"),
(Error::IamSysNotInitialized, "not initialized"),
(Error::InvalidServiceType("invalid".to_string()), "invalid service type: invalid"),
(Error::ErrCredMalformed, "malformed credential"),
(Error::CredNotInitialized, "CredNotInitialized"),
(Error::InvalidAccessKeyLength, "invalid access key length"),
(Error::InvalidSecretKeyLength, "invalid secret key length"),
(Error::ContainsReservedChars, "access key contains reserved characters =,"),
(Error::GroupNameContainsReservedChars, "group name contains reserved characters =,"),
(Error::NoAccessKey, "no access key"),
(Error::InvalidToken, "invalid token"),
(Error::InvalidAccessKey, "invalid access_key"),
(Error::IAMActionNotAllowed, "action not allowed"),
(Error::InvalidExpiration, "invalid expiration"),
(Error::NoSecretKeyWithAccessKey, "no secret key with access key"),
(Error::NoAccessKeyWithSecretKey, "no access key with secret key"),
(Error::PolicyTooLarge, "policy too large"),
];
for (error, expected_message) in test_cases {
assert_eq!(error.to_string(), expected_message);
}
}
#[test]
fn test_string_error_variant() {
let custom_message = "Custom error message";
let error = Error::StringError(custom_message.to_string());
assert_eq!(error.to_string(), custom_message);
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use std::{collections::HashSet, ops::Deref};
use strum::{EnumString, IntoStaticStr};
use super::{utils::wildcard, Error as IamError, Validator};
use super::{Error as IamError, Validator, utils::wildcard};
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
pub struct ActionSet(pub HashSet<Action>);
+2 -2
View File
@@ -1,6 +1,6 @@
use crate::policy::function::condition::Condition;
use serde::ser::SerializeMap;
use serde::{de, Deserialize, Serialize, Serializer};
use serde::{Deserialize, Serialize, Serializer, de};
use std::collections::HashMap;
use std::collections::HashSet;
@@ -163,12 +163,12 @@ pub struct Value;
#[cfg(test)]
mod tests {
use crate::policy::Functions;
use crate::policy::function::condition::Condition::*;
use crate::policy::function::func::FuncKeyValue;
use crate::policy::function::key::Key;
use crate::policy::function::string::StringFunc;
use crate::policy::function::string::StringFuncValue;
use crate::policy::Functions;
use test_case::test_case;
#[test_case(
+1 -1
View File
@@ -1,6 +1,6 @@
use super::func::InnerFunc;
use ipnetwork::IpNetwork;
use serde::{de::Visitor, Deserialize, Serialize};
use serde::{Deserialize, Serialize, de::Visitor};
use std::{borrow::Cow, collections::HashMap, net::IpAddr};
pub type AddrFunc = InnerFunc<AddrFuncValue>;
+1 -1
View File
@@ -1,6 +1,6 @@
use super::func::InnerFunc;
use serde::de::{Error, IgnoredAny, SeqAccess};
use serde::{de, Deserialize, Deserializer, Serialize};
use serde::{Deserialize, Deserializer, Serialize, de};
use std::{collections::HashMap, fmt};
pub type BoolFunc = InnerFunc<BoolFuncValue>;
+2 -6
View File
@@ -1,6 +1,6 @@
use serde::Deserialize;
use serde::de::{Error, MapAccess};
use serde::ser::SerializeMap;
use serde::Deserialize;
use std::collections::HashMap;
use time::OffsetDateTime;
@@ -122,11 +122,7 @@ impl Condition {
DateGreaterThanEquals(s) => s.evaluate(OffsetDateTime::ge, values),
};
if self.is_negate() {
!r
} else {
r
}
if self.is_negate() { !r } else { r }
}
#[inline]
+3 -3
View File
@@ -1,7 +1,7 @@
use super::func::InnerFunc;
use serde::{de, Deserialize, Deserializer, Serialize};
use serde::{Deserialize, Deserializer, Serialize, de};
use std::{collections::HashMap, fmt};
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
pub type DateFunc = InnerFunc<DateFuncValue>;
@@ -82,7 +82,7 @@ mod tests {
key_name::S3KeyName::*,
};
use test_case::test_case;
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
fn new_func(name: KeyName, variable: Option<String>, value: &str) -> DateFunc {
DateFunc {
+1 -1
View File
@@ -1,8 +1,8 @@
use std::marker::PhantomData;
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize,
de::{self, Visitor},
};
use super::key::Key;
+1 -1
View File
@@ -2,8 +2,8 @@ use std::collections::HashMap;
use super::func::InnerFunc;
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize,
de::{Error, Visitor},
};
pub type NumberFunc = InnerFunc<NumberFuncValue>;
+1 -1
View File
@@ -7,7 +7,7 @@ use std::{borrow::Cow, collections::HashMap};
use crate::policy::function::func::FuncKeyValue;
use crate::policy::utils::wildcard;
use serde::{de, ser::SerializeSeq, Deserialize, Deserializer, Serialize};
use serde::{Deserialize, Deserializer, Serialize, de, ser::SerializeSeq};
use super::{func::InnerFunc, key_name::KeyName};
+2 -2
View File
@@ -1,4 +1,4 @@
use super::{action::Action, statement::BPStatement, Effect, Error as IamError, Statement, ID};
use super::{Effect, Error as IamError, ID, Statement, action::Action, statement::BPStatement};
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};
use serde_json::Value;
@@ -252,9 +252,9 @@ pub mod default {
use std::{collections::HashSet, sync::LazyLock};
use crate::policy::{
ActionSet, DEFAULT_VERSION, Effect, Functions, ResourceSet, Statement,
action::{Action, AdminAction, KmsAction, S3Action},
resource::Resource,
ActionSet, Effect, Functions, ResourceSet, Statement, DEFAULT_VERSION,
};
use super::Policy;
+1 -1
View File
@@ -1,4 +1,4 @@
use super::{utils::wildcard, Validator};
use super::{Validator, utils::wildcard};
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
+1 -1
View File
@@ -7,9 +7,9 @@ use std::{
};
use super::{
Error as IamError, Validator,
function::key_name::KeyName,
utils::{path, wildcard},
Error as IamError, Validator,
};
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
+2 -2
View File
@@ -1,6 +1,6 @@
use super::{
action::Action, ActionSet, Args, BucketPolicyArgs, Effect, Error as IamError, Functions, Principal, ResourceSet, Validator,
ID,
ActionSet, Args, BucketPolicyArgs, Effect, Error as IamError, Functions, ID, Principal, ResourceSet, Validator,
action::Action,
};
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};
+1 -5
View File
@@ -85,11 +85,7 @@ pub fn clean(path: &str) -> String {
}
}
if out.w == 0 {
".".into()
} else {
out.string()
}
if out.w == 0 { ".".into() } else { out.string() }
}
#[cfg(test)]
+1 -1
View File
@@ -1,6 +1,6 @@
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header};
use rand::{Rng, RngCore};
use serde::{de::DeserializeOwned, Serialize};
use serde::{Serialize, de::DeserializeOwned};
use std::io::{Error, Result};
pub fn gen_access_key(length: usize) -> Result<String> {
+2 -2
View File
@@ -1,7 +1,7 @@
use policy::policy::action::Action;
use policy::policy::action::S3Action::*;
use policy::policy::ActionSet;
use policy::policy::Effect::*;
use policy::policy::action::Action;
use policy::policy::action::S3Action::*;
use policy::policy::*;
use serde_json::Value;
use std::collections::HashMap;