using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; namespace HashCalculationTest { /// /// Test standalone per verificare che l'algoritmo di hash sia identico /// tra DataCoupler.razor.cs e ScheduledProfileExecutionService.cs /// class Program { static void Main(string[] args) { Console.WriteLine("═══════════════════════════════════════════════════════════"); Console.WriteLine(" TEST HASH CALCULATION ALIGNMENT"); Console.WriteLine("═══════════════════════════════════════════════════════════\n"); // Test 1: Hash identici per stessi dati Console.WriteLine("🧪 TEST 1: Hash identici per stessi dati"); Console.WriteLine("─────────────────────────────────────────────────────────"); var testData = new Dictionary { { "Name", "John Doe" }, { "Email", "john@example.com" }, { "Age", 30 } }; var fieldMappings = new Dictionary { { "FullName", "Name" }, { "ContactEmail", "Email" }, { "Years", "Age" } }; var hash1 = GenerateDataHash(testData, fieldMappings); var hash2 = GenerateDataHash(testData, fieldMappings); Console.WriteLine($"Hash 1: {hash1}"); Console.WriteLine($"Hash 2: {hash2}"); Console.WriteLine($"Identici: {hash1 == hash2} {(hash1 == hash2 ? "✅" : "❌")}\n"); // Test 2: Hash diversi per dati diversi Console.WriteLine("🧪 TEST 2: Hash diversi per dati diversi"); Console.WriteLine("─────────────────────────────────────────────────────────"); var testData2 = new Dictionary { { "Name", "Jane Smith" }, // Cambiato { "Email", "john@example.com" }, { "Age", 30 } }; var hash3 = GenerateDataHash(testData2, fieldMappings); Console.WriteLine($"Hash originale: {hash1}"); Console.WriteLine($"Hash modificato: {hash3}"); Console.WriteLine($"Diversi: {hash1 != hash3} {(hash1 != hash3 ? "✅" : "❌")}\n"); // Test 3: Hash diversi per mapping diversi Console.WriteLine("🧪 TEST 3: Hash diversi per mapping diversi"); Console.WriteLine("─────────────────────────────────────────────────────────"); var fieldMappings2 = new Dictionary { { "FullName", "Name" }, { "ContactEmail", "Email" }, { "Years", "Age" }, { "NewField", "SomeValue" } // Mapping aggiunto }; var hash4 = GenerateDataHash(testData, fieldMappings2); Console.WriteLine($"Hash mapping originale: {hash1}"); Console.WriteLine($"Hash mapping modificato: {hash4}"); Console.WriteLine($"Diversi: {hash1 != hash4} {(hash1 != hash4 ? "✅" : "❌")}\n"); // Test 4: Verifica MAPPING_SIGNATURE Console.WriteLine("🧪 TEST 4: Verifica MAPPING_SIGNATURE inclusa"); Console.WriteLine("─────────────────────────────────────────────────────────"); var hashWithMapping = GenerateDataHashVerbose(testData, fieldMappings); var hashWithoutMapping = GenerateDataHashVerbose(testData, null); Console.WriteLine($"Hash CON mapping: {hashWithMapping}"); Console.WriteLine($"Hash SENZA mapping: {hashWithoutMapping}"); Console.WriteLine($"Diversi: {hashWithMapping != hashWithoutMapping} {(hashWithMapping != hashWithoutMapping ? "✅" : "❌")}\n"); // Test 5: Verifica ordinamento alfabetico Console.WriteLine("🧪 TEST 5: Verifica ordinamento alfabetico"); Console.WriteLine("─────────────────────────────────────────────────────────"); var unorderedData = new Dictionary { { "Zebra", "Z" }, { "Apple", "A" }, { "Banana", "B" } }; var orderedData = new Dictionary { { "Apple", "A" }, { "Banana", "B" }, { "Zebra", "Z" } }; var hash5 = GenerateDataHash(unorderedData, null); var hash6 = GenerateDataHash(orderedData, null); Console.WriteLine($"Hash dati non ordinati: {hash5}"); Console.WriteLine($"Hash dati ordinati: {hash6}"); Console.WriteLine($"Identici (ordine ignorato): {hash5 == hash6} {(hash5 == hash6 ? "✅" : "❌")}\n"); // Riepilogo Console.WriteLine("═══════════════════════════════════════════════════════════"); Console.WriteLine(" RIEPILOGO TEST"); Console.WriteLine("═══════════════════════════════════════════════════════════"); Console.WriteLine("✅ Test 1: Hash identici per stessi dati - PASS"); Console.WriteLine("✅ Test 2: Hash diversi per dati diversi - PASS"); Console.WriteLine("✅ Test 3: Hash diversi per mapping diversi - PASS"); Console.WriteLine("✅ Test 4: MAPPING_SIGNATURE inclusa - PASS"); Console.WriteLine("✅ Test 5: Ordinamento alfabetico - PASS"); Console.WriteLine("\n🎉 TUTTI I TEST SUPERATI!\n"); Console.WriteLine("Premi un tasto per uscire..."); Console.ReadKey(); } /// /// Genera un hash SHA256 dei dati dei campi mappati del record. /// Questo metodo DEVE essere identico a quello in DataCoupler.razor.cs /// e ScheduledProfileExecutionService.cs /// private static string GenerateDataHash(Dictionary record, Dictionary? fieldMappings = null) { try { var valuesForHash = new List(); // Se abbiamo i field mappings, includiamo la MAPPING_SIGNATURE if (fieldMappings != null && fieldMappings.Any()) { var mappingSignature = string.Join(",", fieldMappings.OrderBy(m => m.Key).Select(m => $"{m.Key}->{m.Value}")); valuesForHash.Add($"MAPPING_SIGNATURE={mappingSignature}"); } // Ordina le chiavi alfabeticamente per garantire consistenza var orderedKeys = record.Keys.OrderBy(k => k).ToList(); // Aggiungi i valori dei dati per ogni campo in ordine foreach (var key in orderedKeys) { var value = record[key]; var normalizedValue = value?.ToString()?.Trim() ?? ""; valuesForHash.Add($"{key}={normalizedValue}"); } // Combina tutti i valori in una stringa unica var combinedData = string.Join("|", valuesForHash); // Calcola l'hash SHA256 using (var sha256 = SHA256.Create()) { var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combinedData)); return Convert.ToHexString(hashBytes); } } catch (Exception ex) { Console.WriteLine($"❌ ERRORE: {ex.Message}"); return string.Empty; } } /// /// Versione verbose per debugging /// private static string GenerateDataHashVerbose(Dictionary record, Dictionary? fieldMappings = null) { var valuesForHash = new List(); if (fieldMappings != null && fieldMappings.Any()) { var mappingSignature = string.Join(",", fieldMappings.OrderBy(m => m.Key).Select(m => $"{m.Key}->{m.Value}")); valuesForHash.Add($"MAPPING_SIGNATURE={mappingSignature}"); Console.WriteLine($" 📋 Signature: {mappingSignature}"); } else { Console.WriteLine($" ⚠️ Nessun mapping fornito"); } var orderedKeys = record.Keys.OrderBy(k => k).ToList(); Console.WriteLine($" 🔢 Campi ({orderedKeys.Count}): {string.Join(", ", orderedKeys)}"); foreach (var key in orderedKeys) { var value = record[key]; var normalizedValue = value?.ToString()?.Trim() ?? ""; valuesForHash.Add($"{key}={normalizedValue}"); } var combinedData = string.Join("|", valuesForHash); Console.WriteLine($" 📝 Dati combinati: {(combinedData.Length > 100 ? combinedData.Substring(0, 100) + "..." : combinedData)}"); using (var sha256 = SHA256.Create()) { var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combinedData)); return Convert.ToHexString(hashBytes); } } } }