WEB Carriers Safe-matrix Refactored

Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
Alexey
2026-08-26 20:33:33 +03:00
parent 8b2b88f30c
commit 34eeb2d856
49 changed files with 3406 additions and 936 deletions
+222
View File
@@ -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);
}
}