mirror of
https://github.com/SabreTools/SabreTools.IO.git
synced 2026-11-15 16:41:58 +00:00
Simplify remaining device extensions tests
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
@@ -7,6 +6,84 @@ namespace SabreTools.IO.Extensions.Test
|
||||
{
|
||||
public class DeviceExtensionsTests
|
||||
{
|
||||
#region IsExcludedUnixBlockDevice
|
||||
|
||||
[Theory]
|
||||
[InlineData("dm-0", true)] // Device-mapper (LVM/LUKS, etc.) virtual devices
|
||||
[InlineData("fd0", true)] // Floppy drive
|
||||
[InlineData("loop0", true)] // Loopback-mounted image
|
||||
[InlineData("md0", true)] // Software RAID (mdadm)
|
||||
[InlineData("nbd0", true)] // Network block device
|
||||
[InlineData("ram0", true)] // Ramdisk
|
||||
[InlineData("sda", false)] // Static storage
|
||||
[InlineData("sg0", false)] // Generic SCSI
|
||||
[InlineData("sr0", true)] // Optical drive
|
||||
[InlineData("zd0", true)] // ZFS volume (zvol)
|
||||
[InlineData("zram0", true)] // Compressed ramdisk]
|
||||
public void IsExcludedUnixBlockDeviceTest(string name, bool expected)
|
||||
{
|
||||
bool actual = DeviceExtensions.IsExcludedUnixBlockDevice(name);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadUnixBlockDeviceSize
|
||||
|
||||
[Theory]
|
||||
[InlineData("nvme0n1", 2880)] // Not an sd* device
|
||||
[InlineData("sda", 2880)] // Fixed disk of floppy size, not removable
|
||||
[InlineData("sdb", 30310400)] // USB flash drive, not a floppy size
|
||||
[InlineData("sdc", 0)] // Empty floppy drive (no media)
|
||||
[InlineData("sdh", 2880)] // USB floppy, 1.44 MB
|
||||
[InlineData("sdi", 1440)] // USB floppy, 720 KB (trailing newline)
|
||||
public void ReadUnixBlockDeviceSizeTest(string device, long valueInFile)
|
||||
{
|
||||
long expected = valueInFile * 512;
|
||||
string sysBlockEntry = Path.Combine(Environment.CurrentDirectory, "TestData", "sys", "block", device);
|
||||
long actual = DeviceExtensions.ReadUnixBlockDeviceSize(sysBlockEntry);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadUnixBlockDeviceType
|
||||
|
||||
[Theory]
|
||||
[InlineData("sg0", 5)]
|
||||
[InlineData("sg1", 0)]
|
||||
[InlineData("sg2", 5)]
|
||||
[InlineData("sg3", 1)]
|
||||
[InlineData("sg10", 5)]
|
||||
[InlineData("sga", 5)]
|
||||
[InlineData("sgX", 5)]
|
||||
public void ReadUnixBlockDeviceTypeTest(string device, int expected)
|
||||
{
|
||||
string sysGenericEntry = Path.Combine(Environment.CurrentDirectory, "TestData", "sys", "class", "scsi_generic", device);
|
||||
int actual = DeviceExtensions.ReadUnixBlockDeviceType(sysGenericEntry);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadUnixRemovableFlag
|
||||
|
||||
[Theory]
|
||||
[InlineData("nvme0n1", true)] // Not an sd* device
|
||||
[InlineData("sda", false)] // Fixed disk of floppy size, not removable
|
||||
[InlineData("sdb", true)] // USB flash drive, not a floppy size
|
||||
[InlineData("sdc", true)] // Empty floppy drive (no media)
|
||||
[InlineData("sdh", true)] // USB floppy, 1.44 MB
|
||||
[InlineData("sdi", true)] // USB floppy, 720 KB (trailing newline)
|
||||
public void ReadUnixRemovableFlagTest(string device, bool expected)
|
||||
{
|
||||
string sysBlockEntry = Path.Combine(Environment.CurrentDirectory, "TestData", "sys", "block", device);
|
||||
bool actual = DeviceExtensions.ReadUnixRemovableFlag(sysBlockEntry);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HasDeviceIndexSuffix
|
||||
|
||||
[Theory]
|
||||
@@ -25,6 +102,14 @@ namespace SabreTools.IO.Extensions.Test
|
||||
[InlineData("sr15", "sr", true)]
|
||||
[InlineData("src", "sr", false)]
|
||||
[InlineData("srm", "sr", false)]
|
||||
// Generic block
|
||||
[InlineData("sg0", "sg", true)]
|
||||
[InlineData("sg1", "sg", true)]
|
||||
[InlineData("sg2", "sg", true)]
|
||||
[InlineData("sg3", "sg", true)]
|
||||
[InlineData("sg10", "sg", true)]
|
||||
[InlineData("sga", "sg", false)]
|
||||
[InlineData("sgX", "sg", false)]
|
||||
public void HasDeviceIndexSuffixTest(string name, string prefix, bool expected)
|
||||
{
|
||||
bool actual = DeviceExtensions.HasDeviceIndexSuffix(name, prefix);
|
||||
@@ -32,125 +117,5 @@ namespace SabreTools.IO.Extensions.Test
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EnumerateUnixOpticalGenericPaths
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixOpticalGenericPaths_SysBlockRootNull_ReturnsEmpty()
|
||||
{
|
||||
var actual = DeviceExtensions.EnumerateUnixOpticalGenericPaths(null);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixOpticalGenericPaths_SysBlockRootEmpty_ReturnsEmpty()
|
||||
{
|
||||
var actual = DeviceExtensions.EnumerateUnixOpticalGenericPaths(string.Empty);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixOpticalGenericPaths_MissingDirectory_ReturnsEmpty()
|
||||
{
|
||||
string sysfsScsiGenericRoot = "INVALID";
|
||||
var actual = DeviceExtensions.EnumerateUnixOpticalGenericPaths(sysfsScsiGenericRoot);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixOpticalGenericPaths_OnlyMatchesOpticalSgNodes()
|
||||
{
|
||||
string sysfsScsiGenericRoot = Path.Combine(Environment.CurrentDirectory, "TestData", "sys", "class", "scsi_generic");
|
||||
|
||||
// sg0 - Optical, kept
|
||||
// sg1 - Direct-access disk, skipped
|
||||
// sg2 - Optical (trailing newline), kept
|
||||
// sg3 - Sequential tape, skipped
|
||||
// sg10 - Optical (multi-digit), kept
|
||||
// sga - Name not all-digits, skipped
|
||||
// sgX - Name not all-digits, skipped
|
||||
List<string> expected = ["sg0", "sg10", "sg2"];
|
||||
|
||||
var actual = DeviceExtensions.EnumerateUnixOpticalGenericPaths(sysfsScsiGenericRoot);
|
||||
|
||||
var actualNames = new List<string>();
|
||||
foreach (var p in actual)
|
||||
{
|
||||
actualNames.Add(Path.GetFileName(p));
|
||||
}
|
||||
|
||||
actualNames.Sort(StringComparer.Ordinal);
|
||||
|
||||
Assert.Equal(expected, actualNames);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EnumerateUnixUsbFloppyBlockPaths
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixUsbFloppyBlockPaths_DevRootNull_ReturnsEmpty()
|
||||
{
|
||||
var actual = DeviceExtensions.EnumerateUnixUsbFloppyBlockPaths(null, "/sys/block");
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixUsbFloppyBlockPaths_DevRootEmpty_ReturnsEmpty()
|
||||
{
|
||||
var actual = DeviceExtensions.EnumerateUnixUsbFloppyBlockPaths(string.Empty, "/sys/block");
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixUsbFloppyBlockPaths_SysBlockRootNull_ReturnsEmpty()
|
||||
{
|
||||
var actual = DeviceExtensions.EnumerateUnixUsbFloppyBlockPaths("/dev", null);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixUsbFloppyBlockPaths_SysBlockRootEmpty_ReturnsEmpty()
|
||||
{
|
||||
var actual = DeviceExtensions.EnumerateUnixUsbFloppyBlockPaths("/dev", string.Empty);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixUsbFloppyBlockPaths_MissingDirectory_ReturnsEmpty()
|
||||
{
|
||||
string sysBlockRoot = "INVALID";
|
||||
var actual = DeviceExtensions.EnumerateUnixUsbFloppyBlockPaths("/dev/", sysBlockRoot);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerateUnixUsbFloppyBlockPaths_OnlyMatchesRemovableFloppySizedDisks()
|
||||
{
|
||||
string devRoot = "/dev";
|
||||
string sysBlockRoot = Path.Combine(Environment.CurrentDirectory, "TestData", "sys", "block");
|
||||
|
||||
// nvme0n1 - Not an sd* device, not scanned
|
||||
// sda - Fixed disk of floppy size, not removable, skipped
|
||||
// sdb - USB flash drive, not a floppy size, skipped
|
||||
// sdc - Empty floppy drive (no media), skipped
|
||||
// sdh - USB floppy, 1.44 MB, matched
|
||||
// sdi - USB floppy, 720 KB (trailing newline), matched
|
||||
List<string> expected = ["sdh", "sdi"];
|
||||
|
||||
var actual = DeviceExtensions.EnumerateUnixUsbFloppyBlockPaths(devRoot, sysBlockRoot);
|
||||
|
||||
var actualNames = new List<string>();
|
||||
foreach (var p in actual)
|
||||
{
|
||||
actualNames.Add(Path.GetFileName(p));
|
||||
}
|
||||
|
||||
actualNames.Sort(StringComparer.Ordinal);
|
||||
|
||||
Assert.Equal(expected, actualNames);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,13 +106,12 @@ namespace SabreTools.IO.Extensions
|
||||
/// <summary>
|
||||
/// Enumerate Linux optical drives via their generic SCSI nodes (/dev/sg*).
|
||||
/// </summary>
|
||||
/// <param name="sysfsScsiGenericRoot">sysfs class directory (typically "/sys/class/scsi_generic")</param>
|
||||
/// <returns>Device paths, or an empty list when the sysfs directory is unreadable</returns>
|
||||
/// <remarks>
|
||||
/// Unlike the block nodes, "sg" is not optical-specific, so each candidate is
|
||||
/// confirmed against sysfs: an optical drive reports SCSI peripheral device type 5.
|
||||
/// </remarks>
|
||||
public static List<string> EnumerateUnixOpticalGenericPaths(string? sysfsScsiGenericRoot = "/sys/class/scsi_generic")
|
||||
public static List<string> EnumerateUnixOpticalGenericPaths()
|
||||
{
|
||||
// If the device root is invalid
|
||||
string devRoot = "/dev";
|
||||
@@ -120,11 +119,12 @@ namespace SabreTools.IO.Extensions
|
||||
return [];
|
||||
|
||||
// If the system generic root is invalid
|
||||
if (string.IsNullOrEmpty(sysfsScsiGenericRoot) || !Directory.Exists(sysfsScsiGenericRoot))
|
||||
string sysfsScsiGenericRoot = "/sys/class/scsi_generic";
|
||||
if (!Directory.Exists(sysfsScsiGenericRoot))
|
||||
return [];
|
||||
|
||||
// Attempt to retrieve all matching devices
|
||||
string[] entries = IOExtensions.SafeGetFileSystemEntries(sysfsScsiGenericRoot!, "sg*");
|
||||
string[] entries = IOExtensions.SafeGetFileSystemEntries(sysfsScsiGenericRoot, "sg*");
|
||||
|
||||
// Return only valid devices
|
||||
var result = new List<string>();
|
||||
@@ -149,8 +149,6 @@ namespace SabreTools.IO.Extensions
|
||||
/// Enumerate USB floppy drives, which the kernel exposes as ordinary SCSI disks
|
||||
/// (/dev/sd*) rather than /dev/fd* nodes.
|
||||
/// </summary>
|
||||
/// <param name="devRoot">Root directory device nodes live under (typically "/dev")</param>
|
||||
/// <param name="sysBlockRoot">sysfs block directory (typically "/sys/block")</param>
|
||||
/// <returns>Device paths, or an empty list when the directory is unreadable</returns>
|
||||
/// <remarks>
|
||||
/// A disk is treated as a floppy when it reports itself removable and its media is one of
|
||||
@@ -158,18 +156,20 @@ namespace SabreTools.IO.Extensions
|
||||
/// inserted medium (Win32_LogicalDisk.MediaType) and, like that path, only recognizes the
|
||||
/// drive while floppy media is present.
|
||||
/// </remarks>
|
||||
public static List<string> EnumerateUnixUsbFloppyBlockPaths(string? devRoot = "/dev", string? sysBlockRoot = "/sys/block")
|
||||
public static List<string> EnumerateUnixUsbFloppyBlockPaths()
|
||||
{
|
||||
// If the device root is invalid
|
||||
if (string.IsNullOrEmpty(devRoot) || !Directory.Exists(devRoot))
|
||||
string devRoot = "/dev";
|
||||
if (!Directory.Exists(devRoot))
|
||||
return [];
|
||||
|
||||
// If the system block root is invalid
|
||||
if (string.IsNullOrEmpty(sysBlockRoot) || !Directory.Exists(sysBlockRoot))
|
||||
string sysBlockRoot = "/sys/block";
|
||||
if (!Directory.Exists(sysBlockRoot))
|
||||
return [];
|
||||
|
||||
// Attempt to retrieve all matching devices
|
||||
string[] entries = IOExtensions.SafeGetFileSystemEntries(sysBlockRoot!, "sd*");
|
||||
string[] entries = IOExtensions.SafeGetFileSystemEntries(sysBlockRoot, "sd*");
|
||||
|
||||
// Return only valid devices
|
||||
var result = new List<string>();
|
||||
@@ -342,7 +342,11 @@ namespace SabreTools.IO.Extensions
|
||||
/// <returns>The device size in bytes, 0 on error</returns>
|
||||
public static int ReadUnixBlockDeviceType(string sysGenericEntry)
|
||||
{
|
||||
#if NET20 || NET35
|
||||
string typePath = Path.Combine(Path.Combine(sysGenericEntry, "device"), "type");
|
||||
#else
|
||||
string typePath = Path.Combine(sysGenericEntry, "device", "type");
|
||||
#endif
|
||||
try
|
||||
{
|
||||
if (!File.Exists(typePath))
|
||||
|
||||
Reference in New Issue
Block a user