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 {
  super::storage::{TestPartition, TestPartitions, TestRecordData},
  crate::{
    Ident,
    database::{Database, chunk::RecordWriter},
    record::Record,
  },
};

#[test]
fn test_commit_chunk_returns_new_hashes() {
  let db = Database::<TestPartitions>::new();
  let source_cache = crate::source::cache::reporter::SourceCacheReader::new_empty_for_test();

  let record_a = TestRecordData::Module {
    exports: vec![Ident::new("a")],
  };
  let hash_a = record_a.content_hash();

  let mut writer1 = RecordWriter::new(Ident::new("task1"));
  writer1.insert::<TestPartition, _>("key1", record_a.clone());
  let chunk1 = writer1.build();

  let result1 = db.commit_chunk(chunk1, &source_cache);

  assert!(result1.new_hashes.iter().any(|r| r.hash == hash_a), "hash_a should be reported as new");

  let record_b = TestRecordData::Module {
    exports: vec![Ident::new("b")],
  };
  let hash_b = record_b.content_hash();

  let mut writer2 = RecordWriter::new(Ident::new("task2"));
  writer2.insert::<TestPartition, _>("key2", record_a);
  writer2.insert::<TestPartition, _>("key3", record_b);
  let chunk2 = writer2.build();

  let result2 = db.commit_chunk(chunk2, &source_cache);

  assert!(
    !result2.new_hashes.iter().any(|r| r.hash == hash_a),
    "hash_a should NOT be new (already existed)"
  );
  assert!(
    result2.new_hashes.iter().any(|r| r.hash == hash_b),
    "hash_b should be new"
  );
}

#[test]
fn test_commit_chunk_empty_returns_empty_set() {
  let db = Database::<TestPartitions>::new();
  let source_cache = crate::source::cache::reporter::SourceCacheReader::new_empty_for_test();

  let writer = RecordWriter::new(Ident::new("empty_task"));
  let chunk = writer.build();

  let result = db.commit_chunk(chunk, &source_cache);

  assert!(result.new_hashes.is_empty(), "Empty chunk should return empty hash set");
}

#[test]
fn test_commit_chunk_multiple_same_content_same_chunk() {
  let db = Database::<TestPartitions>::new();
  let source_cache = crate::source::cache::reporter::SourceCacheReader::new_empty_for_test();

  let record = TestRecordData::Function {
    params:      vec![Ident::new("x")],
    return_type: "int".to_string(),
  };
  let hash = record.content_hash();

  let mut writer = RecordWriter::new(Ident::new("task"));
  writer.insert::<TestPartition, _>("key1", record.clone());
  writer.insert::<TestPartition, _>("key2", record.clone());
  writer.insert::<TestPartition, _>("key3", record);
  let chunk = writer.build();

  let result = db.commit_chunk(chunk, &source_cache);

  assert_eq!(result.new_hashes.len(), 1, "Should only have one new hash");
  assert!(result.new_hashes.iter().any(|r| r.hash == hash), "The hash should be in the new set");
}

#[test]
fn test_commit_chunk_all_duplicates_returns_empty() {
  let db = Database::<TestPartitions>::new();
  let source_cache = crate::source::cache::reporter::SourceCacheReader::new_empty_for_test();

  let record = TestRecordData::Struct {
    fields: vec![(Ident::new("field1"), "string".to_string())],
  };
  let hash = record.content_hash();

  let mut writer1 = RecordWriter::new(Ident::new("task1"));
  writer1.insert::<TestPartition, _>("key1", record.clone());
  let chunk1 = writer1.build();

  let result1 = db.commit_chunk(chunk1, &source_cache);
  assert!(result1.new_hashes.iter().any(|r| r.hash == hash));

  let mut writer2 = RecordWriter::new(Ident::new("task2"));
  writer2.insert::<TestPartition, _>("key2", record);
  let chunk2 = writer2.build();

  let result2 = db.commit_chunk(chunk2, &source_cache);

  assert!(
    result2.new_hashes.is_empty(),
    "All records are duplicates, should return empty set"
  );
}

#[test]
fn test_commit_chunk_mixed_new_and_existing() {
  let db = Database::<TestPartitions>::new();
  let source_cache = crate::source::cache::reporter::SourceCacheReader::new_empty_for_test();

  let record_existing = TestRecordData::Module {
    exports: vec![Ident::new("existing")],
  };
  let hash_existing = record_existing.content_hash();

  let mut writer1 = RecordWriter::new(Ident::new("task1"));
  writer1.insert::<TestPartition, _>("key1", record_existing.clone());
  let chunk1 = writer1.build();
  db.commit_chunk(chunk1, &source_cache);

  let record_new1 = TestRecordData::Module {
    exports: vec![Ident::new("new1")],
  };
  let record_new2 = TestRecordData::Module {
    exports: vec![Ident::new("new2")],
  };
  let hash_new1 = record_new1.content_hash();
  let hash_new2 = record_new2.content_hash();

  let mut writer2 = RecordWriter::new(Ident::new("task2"));
  writer2.insert::<TestPartition, _>("existing_key", record_existing);
  writer2.insert::<TestPartition, _>("new_key1", record_new1);
  writer2.insert::<TestPartition, _>("new_key2", record_new2);
  let chunk2 = writer2.build();

  let result = db.commit_chunk(chunk2, &source_cache);

  assert_eq!(result.new_hashes.len(), 2, "Should have exactly 2 new hashes");
  assert!(
    !result.new_hashes.iter().any(|r| r.hash == hash_existing),
    "hash_existing should NOT be new"
  );
  assert!(result.new_hashes.iter().any(|r| r.hash == hash_new1), "hash_new1 should be new");
  assert!(result.new_hashes.iter().any(|r| r.hash == hash_new2), "hash_new2 should be new");
}