169 lines
6.1 KiB
C#
169 lines
6.1 KiB
C#
using Microsoft.Data.Sqlite;
|
|||
|
|
using PrepStep;
|
||
|
|
|
||
|
|
namespace PrepStep.Tests;
|
||
|
|
|
||
|
|
/// <summary>Integration test di Indexer.ScanAsync: disco temporaneo reale + DB SQLite reale,
|
||
|
|
/// nessun dato inserito a mano (a differenza di CaseInsensitiveLookupIntegrationTests, che
|
||
|
|
/// verifica solo le query a valle su righe già presenti). Copre la scansione vera - upsert
|
||
|
|
/// incrementale, rilevamento nuovi/aggiornati/invariati/rimossi, esclusione cartelle "temp_" -
|
||
|
|
/// che prima di questi test non aveva nessuna copertura (solo Indexer.ParseFilename era
|
||
|
|
/// testato).</summary>
|
||
|
|
public class IndexerScanTests : IDisposable
|
||
|
|
{
|
||
|
|
private readonly string _root = Path.Combine(Path.GetTempPath(), $"cadsearch_scan_{Guid.NewGuid():N}");
|
||
|
|
private readonly string _dbPath;
|
||
|
|
|
||
|
|
public IndexerScanTests()
|
||
|
|
{
|
||
|
|
Directory.CreateDirectory(_root);
|
||
|
|
_dbPath = Path.Combine(_root, "indice.db");
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
SqliteConnection.ClearAllPools();
|
||
|
|
Directory.Delete(_root, recursive: true);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void ScriviFile(string percorso, string contenuto = "dati")
|
||
|
|
{
|
||
|
|
Directory.CreateDirectory(Path.GetDirectoryName(percorso)!);
|
||
|
|
File.WriteAllText(percorso, contenuto);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>IProgress<T> sincrono: Progress<T> marshala il report tramite
|
||
|
|
/// SynchronizationContext.Post (o il thread pool, se assente, come nei test) - l'ultimo
|
||
|
|
/// valore non è garantito visibile subito dopo l'await. Qui Report gira sullo stesso
|
||
|
|
/// thread di background di Indexer.Scan, prima che Task.Run completi: l'ultimo valore è
|
||
|
|
/// quindi affidabile non appena l'await ritorna.</summary>
|
||
|
|
private sealed class ProgressoSincrono : IProgress<ScanProgress>
|
||
|
|
{
|
||
|
|
public ScanProgress? Ultimo { get; private set; }
|
||
|
|
public void Report(ScanProgress value) => Ultimo = value;
|
||
|
|
}
|
||
|
|
|
||
|
|
private async Task ScanAsync()
|
||
|
|
{
|
||
|
|
await Indexer.ScanAsync(_root, _dbPath, new ProgressoSincrono(), CancellationToken.None);
|
||
|
|
}
|
||
|
|
|
||
|
|
private List<(string Codice, string Tipo, string? Famiglia, string CartellaRadice)> LeggiFiles()
|
||
|
|
{
|
||
|
|
using var connection = new SqliteConnection($"Data Source={_dbPath};Mode=ReadOnly");
|
||
|
|
connection.Open();
|
||
|
|
using var cmd = connection.CreateCommand();
|
||
|
|
cmd.CommandText = "SELECT codice, tipo_file, famiglia, cartella_radice FROM files";
|
||
|
|
using var reader = cmd.ExecuteReader();
|
||
|
|
var righe = new List<(string, string, string?, string)>();
|
||
|
|
while (reader.Read())
|
||
|
|
righe.Add((reader.GetString(0), reader.GetString(1),
|
||
|
|
reader.IsDBNull(2) ? null : reader.GetString(2), reader.GetString(3)));
|
||
|
|
return righe;
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task Indicizza_un_file_estraendo_codice_tipo_versione_e_famiglia()
|
||
|
|
{
|
||
|
|
ScriviFile(Path.Combine(_root, "__Corpi", "442", "9244228573.asm.16"));
|
||
|
|
|
||
|
|
await ScanAsync();
|
||
|
|
|
||
|
|
var righe = LeggiFiles();
|
||
|
|
Assert.Single(righe);
|
||
|
|
Assert.Equal(("9244228573", "asm", "442", "__Corpi"), righe[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task Esclude_le_cartelle_radice_che_iniziano_con_temp_()
|
||
|
|
{
|
||
|
|
ScriviFile(Path.Combine(_root, "temp_paris", "vecchio.asm.1"));
|
||
|
|
ScriviFile(Path.Combine(_root, "__Corpi", "9244228573.asm.16"));
|
||
|
|
|
||
|
|
await ScanAsync();
|
||
|
|
|
||
|
|
var righe = LeggiFiles();
|
||
|
|
Assert.Single(righe);
|
||
|
|
Assert.Equal("__Corpi", righe[0].CartellaRadice);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task File_non_modificato_resta_invariato_tra_due_scansioni()
|
||
|
|
{
|
||
|
|
string percorso = Path.Combine(_root, "__Corpi", "file.prt.1");
|
||
|
|
ScriviFile(percorso);
|
||
|
|
await ScanAsync();
|
||
|
|
|
||
|
|
var progress = new ProgressoSincrono();
|
||
|
|
await Indexer.ScanAsync(_root, _dbPath, progress, CancellationToken.None);
|
||
|
|
|
||
|
|
Assert.NotNull(progress.Ultimo);
|
||
|
|
Assert.Equal(0, progress.Ultimo!.Nuovi);
|
||
|
|
Assert.Equal(0, progress.Ultimo.Aggiornati);
|
||
|
|
Assert.Equal(1, progress.Ultimo.Invariati);
|
||
|
|
Assert.Equal(0, progress.Ultimo.Rimossi);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task File_modificato_viene_rilevato_come_aggiornato()
|
||
|
|
{
|
||
|
|
string percorso = Path.Combine(_root, "__Corpi", "file.prt.1");
|
||
|
|
ScriviFile(percorso, "versione 1");
|
||
|
|
await ScanAsync();
|
||
|
|
|
||
|
|
// Contenuto più lungo -> dimensione diversa, quindi rilevato come modifica anche se
|
||
|
|
// il file system non aggiornasse data_modifica entro la risoluzione del clock.
|
||
|
|
ScriviFile(percorso, "versione 2 con più testo dentro");
|
||
|
|
|
||
|
|
var progress = new ProgressoSincrono();
|
||
|
|
await Indexer.ScanAsync(_root, _dbPath, progress, CancellationToken.None);
|
||
|
|
|
||
|
|
Assert.NotNull(progress.Ultimo);
|
||
|
|
Assert.Equal(1, progress.Ultimo!.Aggiornati);
|
||
|
|
Assert.Equal(0, progress.Ultimo.Nuovi);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task File_cancellato_dal_disco_viene_rimosso_dal_db_alla_scansione_successiva()
|
||
|
|
{
|
||
|
|
string percorso = Path.Combine(_root, "__Corpi", "file.prt.1");
|
||
|
|
ScriviFile(percorso);
|
||
|
|
await ScanAsync();
|
||
|
|
Assert.Single(LeggiFiles());
|
||
|
|
|
||
|
|
File.Delete(percorso);
|
||
|
|
await ScanAsync();
|
||
|
|
|
||
|
|
Assert.Empty(LeggiFiles());
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task Files_ultima_versione_tiene_solo_la_versione_piu_recente_per_codice_e_tipo()
|
||
|
|
{
|
||
|
|
ScriviFile(Path.Combine(_root, "__Corpi", "9244228573.asm.40"));
|
||
|
|
ScriviFile(Path.Combine(_root, "__Corpi", "9244228573.asm.41"));
|
||
|
|
|
||
|
|
await ScanAsync();
|
||
|
|
|
||
|
|
using var connection = new SqliteConnection($"Data Source={_dbPath};Mode=ReadOnly");
|
||
|
|
connection.Open();
|
||
|
|
using var cmd = connection.CreateCommand();
|
||
|
|
cmd.CommandText = "SELECT versione FROM files_ultima_versione WHERE codice = '9244228573'";
|
||
|
|
using var reader = cmd.ExecuteReader();
|
||
|
|
Assert.True(reader.Read());
|
||
|
|
Assert.Equal(41L, reader.GetInt64(0));
|
||
|
|
Assert.False(reader.Read());
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task File_senza_pattern_codice_tipo_versione_va_in_tipo_altro()
|
||
|
|
{
|
||
|
|
ScriviFile(Path.Combine(_root, "__Corpi", "leggimi.txt"));
|
||
|
|
|
||
|
|
await ScanAsync();
|
||
|
|
|
||
|
|
var righe = LeggiFiles();
|
||
|
|
Assert.Single(righe);
|
||
|
|
Assert.Equal("altro", righe[0].Tipo);
|
||
|
|
}
|
||
|
|
}
|