2026-09-21 11:18:43 +02:00
|
|
|
using PrepStep;
|
2026-09-16 16:25:52 +02:00
|
|
|
using Microsoft.Data.Sqlite;
|
|
|
|
|
|
2026-09-21 11:18:43 +02:00
|
|
|
namespace PrepStep.Tests;
|
2026-09-16 16:25:52 +02:00
|
|
|
|
|
|
|
|
/// <summary>Ricrea lo schema reale del DB (stessa costante SQL usata da Indexer.ScanAsync) e
|
|
|
|
|
/// verifica, con dati inseriti a mano, i due comportamenti che in passato hanno causato bug
|
|
|
|
|
/// silenziosi: il confronto case-insensitive su codice/tipo_file e la vista
|
|
|
|
|
/// files_ultima_versione che tiene solo l'ultima versione per cartella_radice+codice+tipo.</summary>
|
|
|
|
|
public class CaseInsensitiveLookupIntegrationTests : IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly string _dbPath = Path.Combine(Path.GetTempPath(), $"cadsearch_test_{Guid.NewGuid():N}.db");
|
|
|
|
|
private readonly SqliteConnection _connection;
|
|
|
|
|
|
|
|
|
|
public CaseInsensitiveLookupIntegrationTests()
|
|
|
|
|
{
|
|
|
|
|
_connection = new SqliteConnection($"Data Source={_dbPath}");
|
|
|
|
|
_connection.Open();
|
|
|
|
|
using var schemaCmd = _connection.CreateCommand();
|
|
|
|
|
schemaCmd.CommandText = Indexer.Schema;
|
|
|
|
|
schemaCmd.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
_connection.Dispose();
|
|
|
|
|
SqliteConnection.ClearPool(_connection);
|
|
|
|
|
File.Delete(_dbPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InserisciFile(string percorso, string cartella, string codice, string tipo, int versione, string dataModifica)
|
|
|
|
|
{
|
|
|
|
|
using var cmd = _connection.CreateCommand();
|
|
|
|
|
cmd.CommandText = """
|
|
|
|
|
INSERT INTO files (percorso_completo, percorso_relativo, nome_file, cartella_radice,
|
|
|
|
|
famiglia, codice, tipo_file, versione, dimensione_byte, data_modifica, scansionato_il)
|
|
|
|
|
VALUES (@p, @p, @p, @cartella, NULL, @codice, @tipo, @versione, 1, @modifica, @modifica)
|
|
|
|
|
""";
|
|
|
|
|
cmd.Parameters.AddWithValue("@p", percorso);
|
|
|
|
|
cmd.Parameters.AddWithValue("@cartella", cartella);
|
|
|
|
|
cmd.Parameters.AddWithValue("@codice", codice);
|
|
|
|
|
cmd.Parameters.AddWithValue("@tipo", tipo);
|
|
|
|
|
cmd.Parameters.AddWithValue("@versione", versione);
|
|
|
|
|
cmd.Parameters.AddWithValue("@modifica", dataModifica);
|
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Stessa query (LOWER su entrambi i lati) usata da Form1 per risolvere un codice
|
|
|
|
|
/// referenziato in un .asm: la scansione euristica del binario può restituire maiuscole
|
|
|
|
|
/// diverse da quelle del file reale su disco (es. "_D100" estratto vs "_d100" su X:\).</summary>
|
|
|
|
|
private List<(string Tipo, string Percorso)> CercaCasoInsensitive(string codiceCercato)
|
|
|
|
|
{
|
|
|
|
|
using var cmd = _connection.CreateCommand();
|
|
|
|
|
cmd.CommandText = "SELECT tipo_file, percorso_completo FROM files_ultima_versione "
|
|
|
|
|
+ "WHERE LOWER(codice) = LOWER(@codice) AND LOWER(tipo_file) IN ('prt', 'asm') "
|
|
|
|
|
+ "ORDER BY tipo_file, data_modifica DESC";
|
|
|
|
|
cmd.Parameters.AddWithValue("@codice", codiceCercato);
|
|
|
|
|
using var reader = cmd.ExecuteReader();
|
|
|
|
|
var risultati = new List<(string, string)>();
|
|
|
|
|
while (reader.Read())
|
|
|
|
|
risultati.Add((reader.GetString(0), reader.GetString(1)));
|
|
|
|
|
return risultati;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Trova_il_file_anche_se_la_maiuscola_del_codice_non_corrisponde()
|
|
|
|
|
{
|
|
|
|
|
InserisciFile(@"X:\__Corpi\442\M_B\9244228573_d100.asm.16", "__Corpi", "9244228573_d100", "asm", 16, "2018-08-22T14:51:19Z");
|
|
|
|
|
|
|
|
|
|
var risultati = CercaCasoInsensitive("9244228573_D100");
|
|
|
|
|
|
|
|
|
|
Assert.Single(risultati);
|
|
|
|
|
Assert.Equal("asm", risultati[0].Tipo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Trova_il_file_anche_se_il_tipo_e_maiuscolo()
|
|
|
|
|
{
|
|
|
|
|
InserisciFile(@"X:\Commerciali\Elettrici\1504240807.PRT.1", "Commerciali", "1504240807", "PRT", 1, "2020-01-01T00:00:00Z");
|
|
|
|
|
|
|
|
|
|
var risultati = CercaCasoInsensitive("1504240807");
|
|
|
|
|
|
|
|
|
|
Assert.Single(risultati);
|
|
|
|
|
Assert.Equal("PRT", risultati[0].Tipo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Tra_due_cartelle_radice_diverse_tiene_solo_la_versione_piu_recente()
|
|
|
|
|
{
|
|
|
|
|
// Stesso codice+tipo duplicato su due cartelle radice diverse (capitato con temp_paris
|
|
|
|
|
// vs __Corpi): la vista files_ultima_versione deve restituire il più recente per
|
|
|
|
|
// cartella, ma la query applicativa a valle deve poi tenerne solo uno in assoluto
|
|
|
|
|
// (comportamento verificato qui a livello di dati grezzi restituiti dalla vista).
|
|
|
|
|
InserisciFile(@"X:\temp_paris\gabbia45_modelli_copia\9244228573.asm.1", "temp_paris", "9244228573", "asm", 1, "2014-06-25T07:38:13Z");
|
|
|
|
|
InserisciFile(@"X:\__Corpi\442\M_B\9244228573.asm.41", "__Corpi", "9244228573", "asm", 41, "2019-05-08T13:27:23Z");
|
|
|
|
|
|
|
|
|
|
var risultati = CercaCasoInsensitive("9244228573");
|
|
|
|
|
|
|
|
|
|
// La vista non deduplica tra cartelle radice diverse: la query applicativa ordina per
|
|
|
|
|
// data_modifica DESC e tiene solo la prima per tipo, cioè quella più recente.
|
|
|
|
|
Assert.Equal(2, risultati.Count);
|
|
|
|
|
Assert.Equal(@"X:\__Corpi\442\M_B\9244228573.asm.41", risultati[0].Percorso);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void La_vista_ultima_versione_scarta_le_versioni_precedenti_nella_stessa_cartella()
|
|
|
|
|
{
|
|
|
|
|
InserisciFile(@"X:\__Corpi\442\M_B\9244228573.asm.40", "__Corpi", "9244228573", "asm", 40, "2018-08-22T14:51:27Z");
|
|
|
|
|
InserisciFile(@"X:\__Corpi\442\M_B\9244228573.asm.41", "__Corpi", "9244228573", "asm", 41, "2019-05-08T13:27:23Z");
|
|
|
|
|
|
|
|
|
|
var risultati = CercaCasoInsensitive("9244228573");
|
|
|
|
|
|
|
|
|
|
Assert.Single(risultati);
|
|
|
|
|
Assert.Contains(".asm.41", risultati[0].Percorso);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Nessun_risultato_per_un_codice_non_indicizzato()
|
|
|
|
|
{
|
|
|
|
|
InserisciFile(@"X:\__Corpi\442\M_B\9244228573.asm.41", "__Corpi", "9244228573", "asm", 41, "2019-05-08T13:27:23Z");
|
|
|
|
|
|
|
|
|
|
Assert.Empty(CercaCasoInsensitive("0000000000"));
|
|
|
|
|
}
|
|
|
|
|
}
|