zeppelin-embed 0.8.0

In-process vector, lexical, and hybrid search for macOS and Apple silicon
Documentation
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]

use super::*;

#[test]
fn all_scalar_and_nonempty_list_kinds_retain_their_values_without_vectors() {
    assert!(matches!(
        PropertyValue::new(PropertyData::Bool(true)).unwrap().data(),
        PropertyData::Bool(true)
    ));
    assert!(matches!(
        PropertyValue::new(PropertyData::I64(i64::MIN))
            .unwrap()
            .data(),
        PropertyData::I64(i64::MIN)
    ));
    assert!(matches!(
        PropertyValue::new(PropertyData::Strings(&["猫", ""]))
            .unwrap()
            .data(),
        PropertyData::Strings(["猫", ""])
    ));
    assert!(matches!(
        PropertyValue::new(PropertyData::Bools(&[true, false]))
            .unwrap()
            .data(),
        PropertyData::Bools([true, false])
    ));
    assert!(matches!(
        PropertyValue::new(PropertyData::Integers(&[i64::MIN, i64::MAX]))
            .unwrap()
            .data(),
        PropertyData::Integers([i64::MIN, i64::MAX])
    ));
    let floats = [f64::from_bits(0x7ff8000000000042), -0.0];
    let PropertyData::Floats(values) = PropertyValue::new(PropertyData::Floats(&floats))
        .unwrap()
        .data()
    else {
        panic!("floating list lost its kind");
    };
    assert_eq!(values.first().unwrap().to_bits(), 0x7ff8000000000042);
    assert_eq!(values.last().unwrap().to_bits(), 0x8000000000000000);
}

#[test]
fn raw_name_admission_checks_byte_limit_before_utf8_work() {
    assert_eq!(
        GraphName::from_utf8(&vec![0xff; MAX_GRAPH_INPUT_BYTES + 1]),
        Err(DomainError::InputTooLarge)
    );
    assert_eq!(GraphName::from_utf8("é".as_bytes()).unwrap().as_str(), "é");
}

#[test]
fn batch_local_references_are_bounded() {
    with_local_refs(|scope| {
        let node = scope.node(0).unwrap();
        let rel = scope.relationship(16_383).unwrap();
        assert_eq!(node.index(), 0);
        assert_eq!(rel.index(), 16_383);
        assert_eq!(
            scope.node(16_384),
            Err(DomainError::LocalReferenceOutOfRange)
        );
        assert_eq!(
            scope.relationship(usize::MAX),
            Err(DomainError::LocalReferenceOutOfRange)
        );
    });
}

#[test]
fn scalar_bits_and_typed_lists_are_distinct_from_finite_vectors() {
    for bits in [
        0,
        1 << 63,
        1,
        0x7ff0_0000_0000_0000,
        0xfff0_0000_0000_0000,
        0x7ff8_0000_0000_0042,
    ] {
        let value = PropertyValue::new(PropertyData::F64(f64::from_bits(bits))).unwrap();
        match value.data() {
            PropertyData::F64(value) => assert_eq!(value.to_bits(), bits),
            other => panic!("unexpected scalar {other:?}"),
        }
        assert_eq!(value.payload_bytes(), 8);
    }
    for data in [
        PropertyData::EmptyList { count: 0 },
        PropertyData::Strings(&[]),
        PropertyData::Bools(&[]),
        PropertyData::Integers(&[]),
        PropertyData::Floats(&[]),
    ] {
        let value = PropertyValue::new(data).unwrap();
        assert_eq!(value.list_len(), Some(0));
        assert_eq!(value.payload_bytes(), 0);
    }
    assert!(matches!(
        PropertyValue::new(PropertyData::Floats(&[]))
            .unwrap()
            .data(),
        PropertyData::Floats(_)
    ));
    assert!(matches!(
        PropertyValue::new(PropertyData::EmptyList { count: 0 })
            .unwrap()
            .data(),
        PropertyData::EmptyList { count: 0 }
    ));
    assert_eq!(
        PropertyValue::new(PropertyData::EmptyList { count: 1 }).unwrap_err(),
        DomainError::NonemptyUntypedList
    );
    let list = vec![i64::MIN; MAX_PROPERTY_LIST_ELEMENTS];
    let value = PropertyValue::new(PropertyData::Integers(&list)).unwrap();
    assert_eq!(value.list_len(), Some(524_288));
    assert_eq!(value.payload_bytes(), 4_194_304);
    assert_eq!(
        PropertyValue::new(PropertyData::Bools(&vec![
            true;
            MAX_PROPERTY_LIST_ELEMENTS + 1
        ]))
        .unwrap_err(),
        DomainError::ListTooLong
    );
    let large = "x".repeat(MAX_GRAPH_INPUT_BYTES);
    assert!(PropertyValue::new(PropertyData::String(&large)).is_ok());
    assert_eq!(
        PropertyValue::new(PropertyData::Strings(&[&large, "x"])).unwrap_err(),
        DomainError::InputTooLarge
    );
    let text = PropertyValue::new(PropertyData::String("\0é")).unwrap();
    assert_eq!(text.payload_bytes(), 3);
    assert_eq!(text.list_len(), None);
    let vector = [0.0_f32, -0.0, f32::MIN, f32::MAX];
    let validated = GraphVector::new(&vector, 4).unwrap();
    assert_eq!(validated.coordinates(), vector);
    assert_eq!(
        validated.coordinates().get(1).unwrap().to_bits(),
        0x8000_0000
    );
    assert_eq!(validated.payload_bytes(), 16);
    assert_eq!(
        GraphVector::new(&[], 0).unwrap_err(),
        DomainError::VectorDimensions
    );
    assert_eq!(
        GraphVector::new(&vector, 3).unwrap_err(),
        DomainError::VectorDimensions
    );
    for invalid in [f32::NAN, f32::INFINITY, f32::NEG_INFINITY] {
        assert_eq!(
            GraphVector::new(&[invalid], 1).unwrap_err(),
            DomainError::NonfiniteVector
        );
    }
}

#[test]
fn application_keys_and_metadata_preserve_kind_and_exact_utf8() {
    let node = ApplicationKey::new(EntityKind::Node, "source", "é").unwrap();
    let rel = ApplicationKey::new(EntityKind::Relationship, "source", "é").unwrap();
    assert_ne!(node, rel);
    assert_ne!(
        node,
        ApplicationKey::new(EntityKind::Node, "Source", "é").unwrap()
    );
    assert_ne!(
        node,
        ApplicationKey::new(EntityKind::Node, "source", "e\u{301}").unwrap()
    );
    assert_eq!(node.namespace().as_str(), "source");
    assert_eq!(node.key().as_str(), "é");
    assert_eq!(node.kind(), EntityKind::Node);
    assert_eq!(GraphName::from_utf8(&[0xff]), Err(DomainError::InvalidUtf8));
    assert_eq!(GraphName::new("\0").unwrap().as_str(), "\0");
    assert_eq!(GraphName::new("").unwrap().as_str(), "");
    assert_eq!(
        GraphName::new(&"a".repeat(MAX_GRAPH_INPUT_BYTES + 1)),
        Err(DomainError::InputTooLarge)
    );
    let id = EntityId::Node(NodeId::new((1_u128 << 100) + 7).unwrap());
    let revision = GraphRevision::new(4).unwrap();
    let generation = GraphGeneration::new(u64::MAX);
    let metadata = EntityMetadata::new(id, Some(node), revision, generation).unwrap();
    assert_eq!(metadata.id(), id);
    assert_eq!(metadata.key(), Some(node));
    assert_eq!(metadata.revision(), revision);
    assert_eq!(metadata.last_change_generation().get(), u64::MAX);
    assert_eq!(
        EntityMetadata::new(id, Some(rel), revision, generation),
        Err(DomainError::EntityKindMismatch)
    );
    assert!(EntityMetadata::new(id, None, revision, GraphGeneration::new(0)).is_ok());
}

#[test]
fn full_width_identity_and_checked_revisions() {
    assert_eq!(NodeId::new(0), Err(DomainError::ZeroIdentity));
    assert_eq!(RelId::new(0), Err(DomainError::ZeroIdentity));
    assert_eq!(StoreInstanceId::new(0), Err(DomainError::ZeroIdentity));
    for bits in [1, 1_u128 << 64, (1_u128 << 64) + 1, u128::MAX] {
        assert_eq!(NodeId::new(bits).unwrap().get(), bits);
        assert_eq!(RelId::new(bits).unwrap().get(), bits);
        assert_eq!(StoreInstanceId::new(bits).unwrap().get(), bits);
    }
    assert_ne!(NodeId::new(1), NodeId::new((1_u128 << 64) + 1));
    assert_eq!(GraphRevision::new(0), Err(DomainError::ZeroRevision));
    assert_eq!(
        GraphRevision::new(41)
            .unwrap()
            .checked_next()
            .unwrap()
            .get(),
        42
    );
    assert_eq!(
        GraphRevision::new(u64::MAX).unwrap().checked_next(),
        Err(DomainError::RevisionOverflow)
    );
}