using Xunit;
|
using WIDESEAWCS_S7Simulator.Core.Memory;
|
|
namespace WIDESEAWCS_S7Simulator.UnitTests.Memory
|
{
|
public class MRegionTests
|
{
|
[Fact]
|
public void Constructor_WithValidSize_CreatesRegion()
|
{
|
// Arrange & Act
|
var region = new MRegion(1024);
|
|
// Assert
|
Assert.Equal("M", region.RegionType);
|
Assert.Equal(1024, region.Size);
|
}
|
|
[Fact]
|
public void Read_WithinBounds_ReturnsData()
|
{
|
// Arrange
|
var region = new MRegion(1024);
|
var testData = new byte[] { 0x12, 0x34, 0x56, 0x78 };
|
region.Write(0, testData);
|
|
// Act
|
var result = region.Read(0, 4);
|
|
// Assert
|
Assert.Equal(testData, result);
|
}
|
|
[Fact]
|
public void Read_OutOfBounds_ThrowsArgumentOutOfRange()
|
{
|
// Arrange
|
var region = new MRegion(100);
|
|
// Act & Assert
|
Assert.Throws<ArgumentOutOfRangeException>(() => region.Read(0, 101));
|
}
|
|
[Fact]
|
public void Write_WithinBounds_WritesData()
|
{
|
// Arrange
|
var region = new MRegion(1024);
|
var testData = new byte[] { 0xAA, 0xBB, 0xCC, 0xDD };
|
|
// Act
|
region.Write(100, testData);
|
var result = region.Read(100, 4);
|
|
// Assert
|
Assert.Equal(testData, result);
|
}
|
|
[Fact]
|
public void Write_OutOfBounds_ThrowsArgumentOutOfRange()
|
{
|
// Arrange
|
var region = new MRegion(100);
|
var testData = new byte[] { 0x01, 0x02 };
|
|
// Act & Assert
|
Assert.Throws<ArgumentOutOfRangeException>(() => region.Write(99, testData));
|
}
|
|
[Fact]
|
public void ReadBit_ValidBit_ReturnsCorrectValue()
|
{
|
// Arrange
|
var region = new MRegion(1024);
|
region.Write(0, new byte[] { 0xFF }); // 所有位为1
|
|
// Act
|
var result = region.ReadBit(0, 0);
|
|
// Assert
|
Assert.True(result);
|
}
|
|
[Fact]
|
public void WriteBit_ValidBit_SetsCorrectValue()
|
{
|
// Arrange
|
var region = new MRegion(1024);
|
|
// Act
|
region.WriteBit(0, 3, true);
|
var result = region.ReadBit(0, 3);
|
|
// Assert
|
Assert.True(result);
|
}
|
|
[Fact]
|
public void WriteBit_InvalidBitOffset_ThrowsArgumentOutOfRange()
|
{
|
// Arrange
|
var region = new MRegion(1024);
|
|
// Act & Assert
|
Assert.Throws<ArgumentOutOfRangeException>(() => region.WriteBit(0, 8, true));
|
}
|
|
[Fact]
|
public void Clear_ZerosAllMemory()
|
{
|
// Arrange
|
var region = new MRegion(100);
|
region.Write(0, new byte[] { 0xFF, 0xFF, 0xFF });
|
|
// Act
|
region.Clear();
|
var result = region.Read(0, 3);
|
|
// Assert
|
Assert.Equal(new byte[] { 0, 0, 0 }, result);
|
}
|
|
[Fact]
|
public void ConcurrentReadWrite_ThreadSafe()
|
{
|
// Arrange
|
var region = new MRegion(1024);
|
var exceptions = new System.Collections.Concurrent.ConcurrentBag<Exception>();
|
var cts = new CancellationTokenSource();
|
cts.CancelAfter(1000); // 1秒后取消
|
|
// Act
|
var writeTask = Task.Run(() =>
|
{
|
try
|
{
|
var data = new byte[] { 0xAA, 0xBB };
|
while (!cts.Token.IsCancellationRequested)
|
{
|
region.Write(0, data);
|
}
|
}
|
catch (Exception ex)
|
{
|
exceptions.Add(ex);
|
}
|
}, cts.Token);
|
|
var readTask = Task.Run(() =>
|
{
|
try
|
{
|
while (!cts.Token.IsCancellationRequested)
|
{
|
region.Read(0, 2);
|
}
|
}
|
catch (Exception ex)
|
{
|
exceptions.Add(ex);
|
}
|
}, cts.Token);
|
|
Task.WaitAll(writeTask, readTask);
|
|
// Assert
|
Assert.Empty(exceptions);
|
}
|
}
|
}
|