mirror of
https://git.pumpin.online/funkpower/catena.git
synced 2026-10-23 11:17:13 +00:00
corpus-core: make the stream contract hold under hostile input
This commit is contained in:
@@ -22,8 +22,18 @@ pub struct Hit {
|
||||
/// Position within the channel's own ranking, from one.
|
||||
pub rank: u32,
|
||||
/// The channel's raw score, on whatever scale that channel uses.
|
||||
#[serde(
|
||||
serialize_with = "crate::float::serialize",
|
||||
deserialize_with = "crate::float::deserialize"
|
||||
)]
|
||||
pub score: f64,
|
||||
/// Anything the producer wants to carry through fusion untouched.
|
||||
///
|
||||
/// Keys serialise in sorted order, which is what makes a fused stream
|
||||
/// byte-reproducible. That holds because `serde_json`'s map is a
|
||||
/// `BTreeMap`; enabling its `preserve_order` feature anywhere in the
|
||||
/// dependency graph would switch it to insertion order and break it. The
|
||||
/// test below is what would catch that.
|
||||
#[serde(default)]
|
||||
pub payload: Map<String, Value>,
|
||||
}
|
||||
@@ -42,6 +52,12 @@ impl Hit {
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Record for Hit {
|
||||
fn version(&self) -> u32 {
|
||||
self.v
|
||||
}
|
||||
}
|
||||
|
||||
/// A retrieval channel.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
@@ -80,6 +96,22 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_score_that_is_not_a_number_is_refused_rather_than_written_as_null() {
|
||||
let mut hit = Hit::new("a", Channel::Fts, 1, 0.0);
|
||||
for bad in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
|
||||
hit.score = bad;
|
||||
let e = serde_json::to_string(&hit).unwrap_err();
|
||||
assert!(e.to_string().contains("cannot be written"), "{bad}: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_score_that_overflows_a_float_is_refused_on_the_way_in() {
|
||||
let line = r#"{"id":"a","channel":"fts","rank":1,"score":1e999}"#;
|
||||
assert!(serde_json::from_str::<Hit>(line).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn payload_keys_serialise_in_a_fixed_order() {
|
||||
let mut hit = Hit::new("abc", Channel::Vector, 2, 0.25);
|
||||
|
||||
Reference in New Issue
Block a user