laburnum 1.17.1

An LSP framework for building language servers and compilers, powered by an incremental query tree with content-addressed storage, task-based dataflow, and parallel queries.
Documentation
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

use {
  laburnum::hash::ident::*,
  std::hash::Hasher as _,
};

#[test]
fn test_deterministic_hashing() {
  const FOO: u64 = 16955109009288690222;
  assert_eq!(Ident::new_bytes(b"foo").as_u64(), FOO);
  assert_eq!(Ident::new("foo").as_u64(), FOO);

  const BAR: u64 = 11752582717284712930;
  assert_eq!(Ident::new_bytes(b"bar").as_u64(), BAR);
  assert_eq!(Ident::new("bar").as_u64(), BAR);

  const BAZ: u64 = 2817160363252627303;
  assert_eq!(Ident::new_bytes(b"baz").as_u64(), BAZ);
  assert_eq!(Ident::new("baz").as_u64(), BAZ);

  const HELLO: u64 = 15142343916341883008;
  assert_eq!(Ident::new_bytes(b"hello").as_u64(), HELLO);
  assert_eq!(Ident::new("hello").as_u64(), HELLO);

  const WORLD: u64 = 9456725390238767176;
  assert_eq!(Ident::new_bytes(b"world").as_u64(), WORLD);
  assert_eq!(Ident::new("world").as_u64(), WORLD);
}

#[test]
fn test_const_context() {
  const FOO: Ident = Ident::new_bytes(b"foo");
  const BAR: Ident = Ident::new_bytes(b"bar");

  assert_eq!(FOO.as_u64(), 16955109009288690222);
  assert_eq!(BAR.as_u64(), 11752582717284712930);
}

#[test]
fn test_hasher_matches_ident() {
  let test_strings = ["foo", "bar", "baz", "hello", "world"];

  for s in test_strings {
    let ident = Ident::new(s);

    let mut hasher = IdentHasher::new();
    hasher.write(s.as_bytes());
    let runtime_hash = hasher.finish();

    assert_eq!(ident.as_u64(), runtime_hash, "Hash mismatch for '{}'", s);
  }
}

#[test]
fn test_hashmap_with_ident_hasher() {
  let mut map: std::collections::HashMap<String, u32, IdentHashState> =
    std::collections::HashMap::with_hasher(IdentHashState);

  map.insert("foo".to_string(), 1);
  map.insert("bar".to_string(), 2);

  assert_eq!(map.get("foo"), Some(&1));
  assert_eq!(map.get("bar"), Some(&2));
}

#[test]
fn test_long_identifier() {
  // Test that identifiers can be longer than 255 bytes
  let long_ident = "a".repeat(1000);
  let ident = Ident::new(&long_ident);
  // Just verify it doesn't panic and produces a hash
  assert!(ident.as_u64() != 0);
}

#[test]
fn test_ident_new() {
  let ident = Ident::new("test");
  let ident_bytes = Ident::new_bytes(b"test");
  assert_eq!(ident.as_u64(), ident_bytes.as_u64());
}

#[test]
fn test_ident_try_new() {
  assert!(Ident::try_new("valid").is_ok());
  // try_new now always succeeds (no length limit)
  assert!(Ident::try_new(&"a".repeat(1000)).is_ok());
}

#[test]
fn test_ident_from_hash() {
  let hash = 12345u64;
  let ident = Ident::from_hash(hash);
  assert_eq!(ident.as_u64(), hash);
}

#[test]
fn test_ident_equality() {
  let ident1 = Ident::new("test");
  let ident2 = Ident::new("test");
  let ident3 = Ident::new("different");

  assert_eq!(ident1, ident2);
  assert_ne!(ident1, ident3);
}

#[test]
fn test_const_ident() {
  const MAIN: Ident = Ident::new("main");
  const HELLO: Ident = Ident::new("hello");
  const MAIN_BYTES: Ident = Ident::new_bytes(b"main");
  const HELLO_BYTES: Ident = Ident::new_bytes(b"hello");

  assert_eq!(MAIN.as_u64(), MAIN_BYTES.as_u64());
  assert_eq!(HELLO.as_u64(), HELLO_BYTES.as_u64());
}