mirror of
https://github.com/telemt/telemt.git
synced 2026-09-17 15:58:31 +03:00
WEB Carriers Safe-matrix Refactored
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
use super::*;
|
||||
use crate::web::manager::{CarrierCapabilities, CarrierRequest};
|
||||
|
||||
fn request(hash: u8) -> CarrierRequest {
|
||||
CarrierRequest::automatic(
|
||||
CarrierClientClass::Bridge,
|
||||
CarrierCapabilities::all(),
|
||||
1,
|
||||
None,
|
||||
[hash; 32],
|
||||
)
|
||||
}
|
||||
|
||||
fn context(hash: u8) -> CarrierLearningContext {
|
||||
CarrierLearningContext {
|
||||
profile_key: [1; 32],
|
||||
client_ip: IpAddr::V4(std::net::Ipv4Addr::new(192, 0, 2, hash)),
|
||||
class: CarrierClientClass::Bridge,
|
||||
user_agent_hash: [hash; 32],
|
||||
epoch: 1,
|
||||
ip_learning_eligible: true,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn policy_epoch_rejects_late_outcomes_and_clears_state() {
|
||||
let now = Instant::now();
|
||||
let mut learning = CarrierLearning::new(6);
|
||||
let epoch = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
learning.record_chain(now, epoch, context(1), &[], WebCarrier::Websocket);
|
||||
assert_eq!(learning.entries.len(), 3);
|
||||
let next = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
false,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
assert_ne!(epoch, next);
|
||||
learning.record_chain(now, epoch, context(1), &[], WebCarrier::Https);
|
||||
assert!(learning.entries.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aggressive_policy_ranks_one_atomic_chain_sample() {
|
||||
let now = Instant::now();
|
||||
let mut learning = CarrierLearning::new(6);
|
||||
let epoch = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
learning.record_chain(now, epoch, context(2), &[], WebCarrier::Websocket);
|
||||
let (ranked, scores) = learning.rank(
|
||||
now,
|
||||
&[
|
||||
WebCarrier::Https,
|
||||
WebCarrier::Websocket,
|
||||
WebCarrier::HttpsLanes,
|
||||
],
|
||||
request(2),
|
||||
[1; 32],
|
||||
context(2).client_ip,
|
||||
true,
|
||||
);
|
||||
assert_eq!(
|
||||
ranked,
|
||||
[
|
||||
WebCarrier::Websocket,
|
||||
WebCarrier::Https,
|
||||
WebCarrier::HttpsLanes,
|
||||
]
|
||||
);
|
||||
assert_eq!(scores[WebCarrier::Websocket.index()], 33);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_half_windows_expire_without_sliding_updates() {
|
||||
let start = Instant::now();
|
||||
let mut learning = CarrierLearning::new(6);
|
||||
let epoch = learning
|
||||
.apply_policy(
|
||||
start,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
learning.record_chain(start, epoch, context(3), &[], WebCarrier::Websocket);
|
||||
learning.record_chain(
|
||||
start + Duration::from_secs(6),
|
||||
epoch,
|
||||
context(3),
|
||||
&[],
|
||||
WebCarrier::Websocket,
|
||||
);
|
||||
learning.prune(start + Duration::from_secs(11));
|
||||
assert_eq!(learning.entries.len(), 3);
|
||||
learning.prune(start + Duration::from_secs(16));
|
||||
assert!(learning.entries.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exhausted_epoch_and_insertion_identifiers_fail_closed() {
|
||||
let now = Instant::now();
|
||||
let mut learning = CarrierLearning::new(3);
|
||||
learning.epoch = Some(u64::MAX);
|
||||
assert_eq!(
|
||||
learning.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
),
|
||||
None
|
||||
);
|
||||
learning.record_chain(now, u64::MAX, context(4), &[], WebCarrier::Https);
|
||||
assert!(learning.entries.is_empty());
|
||||
|
||||
learning.epoch = Some(1);
|
||||
learning.insertion_sequence = u64::MAX;
|
||||
learning.record_chain(now, 1, context(4), &[], WebCarrier::Https);
|
||||
assert!(learning.entries.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_reported_failures_do_not_create_negative_evidence() {
|
||||
let now = Instant::now();
|
||||
let mut learning = CarrierLearning::new(3);
|
||||
let epoch = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
learning.record_chain(
|
||||
now,
|
||||
epoch,
|
||||
context(5),
|
||||
&[WebCarrier::Websocket],
|
||||
WebCarrier::Https,
|
||||
);
|
||||
let (_, scores) = learning.rank(
|
||||
now,
|
||||
&[WebCarrier::Websocket, WebCarrier::HttpsLanes],
|
||||
request(5),
|
||||
[1; 32],
|
||||
context(5).client_ip,
|
||||
true,
|
||||
);
|
||||
assert_eq!(scores[WebCarrier::Websocket.index()], 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_new_old_policy_rejects_both_stale_epochs() {
|
||||
let now = Instant::now();
|
||||
let mut learning = CarrierLearning::new(3);
|
||||
let old = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
let middle = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Balanced,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
let current = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
assert_ne!(old, middle);
|
||||
assert_ne!(middle, current);
|
||||
assert_ne!(old, current);
|
||||
learning.record_chain(now, old, context(6), &[], WebCarrier::Https);
|
||||
learning.record_chain(now, middle, context(6), &[], WebCarrier::Https);
|
||||
assert!(learning.entries.is_empty());
|
||||
learning.record_chain(now, current, context(6), &[], WebCarrier::Https);
|
||||
assert_eq!(learning.entries.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fifo_metadata_stays_within_the_entry_capacity() {
|
||||
let now = Instant::now();
|
||||
let mut learning = CarrierLearning::new(3);
|
||||
let epoch = learning
|
||||
.apply_policy(
|
||||
now,
|
||||
true,
|
||||
WebCarrierNegotiationAggressiveness::Aggressive,
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.unwrap();
|
||||
for hash in 1..=32 {
|
||||
learning.record_chain(now, epoch, context(hash), &[], WebCarrier::Https);
|
||||
assert!(learning.entries.len() <= 3);
|
||||
assert!(learning.insertion_order.len() <= 3);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user