using AutopilotMonitor.Functions.DataAccess.TableStorage;
using Xunit;
namespace AutopilotMonitor.Functions.Tests;
///
/// BlockedDevices rows must be keyed case-insensitively: the enforcement cache
/// (BlockedDeviceService) and Autopilot inventory validation both compare serials
/// OrdinalIgnoreCase, so a case-variant serial must resolve to the same storage row.
///
public class TableDeviceSecurityRepositoryKeyTests
{
[Theory]
[InlineData("ABC123", "ABC123")]
[InlineData("abc123", "ABC123")]
[InlineData(" aBc123 ", "ABC123")]
[InlineData(null, "")]
public void CanonicalizeSerial_TrimsAndUpperCases(string? input, string expected)
=> Assert.Equal(expected, TableDeviceSecurityRepository.CanonicalizeSerial(input));
[Theory]
[InlineData("ABC123", "abc123")]
[InlineData("ABC123", "Abc123 ")]
[InlineData("PF/1#2", "pf/1#2")]
public void DeviceRowKey_IsIdenticalForCaseVariants(string a, string b)
=> Assert.Equal(TableDeviceSecurityRepository.DeviceRowKey(a), TableDeviceSecurityRepository.DeviceRowKey(b));
[Fact]
public void DeviceRowKey_EscapesReservedCharacters()
=> Assert.Equal("PF%2F1%232", TableDeviceSecurityRepository.DeviceRowKey("pf/1#2"));
[Fact]
public void LegacyDeviceRowKey_IsNull_WhenAlreadyCanonical()
=> Assert.Null(TableDeviceSecurityRepository.LegacyDeviceRowKey("ABC123"));
[Fact]
public void LegacyDeviceRowKey_IsVerbatimKey_WhenCaseDiffers()
=> Assert.Equal("abc123", TableDeviceSecurityRepository.LegacyDeviceRowKey("abc123"));
// --- Identity alias rows ---
[Theory]
[InlineData("0F8FAD5B-D9CB-469F-A165-70867728950E")]
[InlineData(" 0f8fad5b-d9cb-469f-a165-70867728950e ")]
[InlineData("{0f8fad5b-d9cb-469f-a165-70867728950e}")]
public void IdentityRowKey_NormalizesGuidForm(string input)
=> Assert.Equal("id:0f8fad5b-d9cb-469f-a165-70867728950e", TableDeviceSecurityRepository.IdentityRowKey(input));
[Fact]
public void IdentityRowKey_NeverCollidesWithASerialKey()
{
// A serial that happens to look like an alias key is escaped (':' → %3A) and upper-cased.
var serialKey = TableDeviceSecurityRepository.DeviceRowKey("id:0f8fad5b-d9cb-469f-a165-70867728950e");
Assert.False(TableDeviceSecurityRepository.IsIdentityRowKey(serialKey));
Assert.True(TableDeviceSecurityRepository.IsIdentityRowKey("id:0f8fad5b-d9cb-469f-a165-70867728950e"));
Assert.False(TableDeviceSecurityRepository.IsIdentityRowKey(null));
}
[Fact]
public void ParseAliasDeviceIds_DedupesAndDropsNonGuids()
{
var parsed = TableDeviceSecurityRepository.ParseAliasDeviceIds(
"0F8FAD5B-D9CB-469F-A165-70867728950E,junk,,0f8fad5b-d9cb-469f-a165-70867728950e, 7c9e6679-7425-40de-944b-e07fc1f90ae7");
Assert.Equal(new[] { "0f8fad5b-d9cb-469f-a165-70867728950e", "7c9e6679-7425-40de-944b-e07fc1f90ae7" }, parsed);
}
[Fact]
public void MergeAliasDeviceIds_KeepsStoredFirst_AppendsNew_IgnoresDuplicates()
{
var merged = TableDeviceSecurityRepository.MergeAliasDeviceIds(
new List { "0f8fad5b-d9cb-469f-a165-70867728950e" },
new[] { "0F8FAD5B-D9CB-469F-A165-70867728950E", "7c9e6679-7425-40de-944b-e07fc1f90ae7", "not-a-guid" });
Assert.Equal(new[] { "0f8fad5b-d9cb-469f-a165-70867728950e", "7c9e6679-7425-40de-944b-e07fc1f90ae7" }, merged);
}
}