Skip to content

Commit

Permalink
WIP -- Unit Test Engine (#1087)
Browse files Browse the repository at this point in the history
  • Loading branch information
tgiphil committed Jul 16, 2023
1 parent 32d9587 commit 8014d5d
Show file tree
Hide file tree
Showing 13 changed files with 432 additions and 824 deletions.
224 changes: 177 additions & 47 deletions Source/Mosa.Kernel.x86/UnitTestEngine.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using Mosa.Runtime;
using Mosa.Runtime.x86;

namespace Mosa.Kernel.x86;

Expand All @@ -9,32 +10,66 @@ namespace Mosa.Kernel.x86;
/// </summary>
public static class UnitTestEngine
{
private const int MaxBuffer = 1024 * 64 + 64;
private const byte MaxBuffer = 255;
private const uint MaxParameters = 8; // max 32-bit parameters
private const uint QueueSize = 0x00100000;

private static Pointer Buffer;
private static Pointer Stack;

private static bool Enabled;
private static bool ReadySent;

private static uint UsedBuffer;

private static ushort ComPort;

private static bool Ready;
private static bool ResultReported;

private static uint TestID;
private static byte TestParameterCount;
private static byte TestResultType;
private static Pointer TestMethodAddress;
private static ulong TestResult;

private static Pointer Queue;
private static Pointer QueueNext;
private static Pointer QueueCurrent;

private static uint PendingCount;
private static uint TestCount;

public static void Setup(ushort comPort)
{
Serial.Setup(comPort);

ComPort = comPort;

Serial.Setup(ComPort);

Buffer = new Pointer(Address.DebuggerBuffer);
Stack = new Pointer(Address.UnitTestStack);
Queue = new Pointer(Address.UnitTestQueue);

Enabled = true;
ReadySent = false;
}

private static void SendRawByte(byte b) => Serial.Write(ComPort, b);
Ready = false;
ResultReported = true;

TestID = 0;
TestParameterCount = 0;
TestMethodAddress = Pointer.Zero;
TestResult = 0;

private static void SendByte(byte b) => SendRawByte(b);
QueueNext = Queue;
QueueCurrent = Queue;

PendingCount = 0;
TestCount = 0;

QueueNext.Store32(0);
}

private static void SendByte(byte b) => Serial.Write(ComPort, b);

private static void SendByte(int i) => SendByte((byte)i);

Expand All @@ -54,47 +89,35 @@ private static void SendInteger(ulong i)
SendInteger((uint)((i >> 32) & 0xFFFFFFFF));
}

private const int HeaderSize = 4 + 4;
private const int HeaderSize = 4 + 1;

private static void SendResponseStart(uint id, uint len)
public static void SendResponse(uint id, ulong data)
{
SendInteger(id);
SendInteger(len);
}

private static void SendResponse(uint id) => SendResponseStart(id, 0);

private static void SendResponse(uint id, ulong data)
{
SendResponseStart(id, 8);
SendInteger(data);
}

private static uint GetUInt32(uint offset) => Buffer.Load32(offset);

public static void Process()
{
if (!Enabled)
return;

SendTestUnitResponse();
ProcessTestUnitQueue();

if (!ReadySent)
{
SendResponse(0, 0ul);
ReadySent = true;
SendResponse(0); // Send Ready
}

ProcessQueue();

for (var x = 0; x < 5; x++)
{
for (var i = 0; i < 75; i++)
{
while (ProcessSerial()) ;
}

SendTestUnitResponse();
ProcessTestUnitQueue();
ProcessQueue();
}
}

Expand All @@ -115,7 +138,7 @@ private static bool ProcessSerial()

if (UsedBuffer >= HeaderSize)
{
var length = GetUInt32(4);
var length = Buffer.Load8(4);

if (length > MaxBuffer)
{
Expand All @@ -125,47 +148,154 @@ private static bool ProcessSerial()

if (UsedBuffer == length + HeaderSize)
{
ProcessCommand();
QueueUnitTest();
UsedBuffer = 0;
}
}

return true;
}

private static void ProcessCommand()
private static void QueueUnitTest()
{
var id = GetUInt32(0);
var id = Buffer.Load32(0);
var length = Buffer.Load8(4);

Screen.Goto(13, 0);
Screen.ClearRow();
Screen.Write("[Data]");
Screen.NextLine();
Screen.ClearRow();
Screen.Write("ID: ");
Screen.Write(id, 10, 5);
var start = Buffer + HeaderSize;
var end = start + length;

QueueUnitTest();
QueueUnitTest(id, start, end);
}

private static void QueueUnitTest()
public static void EnterTestReadyLoop()
{
var id = GetUInt32(0);
var length = GetUInt32(4);
var stackPointer = new Pointer(Native.AllocateStackSpace(MaxParameters * 4));

var start = Buffer + HeaderSize;
var end = start + (int)length;
while (true)
{
if (Ready)
{
TestResult = 0;
ResultReported = false;
Ready = false;
TestCount++;

DisplayUpdate(true);

for (var index = 0; index < TestParameterCount; index++)
{
var value = Stack.Load32(index * 4);
stackPointer.Store32(index * 4, value);
}

switch (TestResultType)
{
case 0: Native.FrameCall(TestMethodAddress.ToUInt32()); break;
case 1: TestResult = Native.FrameCallRetU4(TestMethodAddress.ToUInt32()); break;
case 2: TestResult = Native.FrameCallRetU8(TestMethodAddress.ToUInt32()); break;
case 3: TestResult = Native.FrameCallRetR8(TestMethodAddress.ToUInt32()); break;
default: break;
}

SendResponse(TestID, TestResult);

ResultReported = true;

Native.Int(255);
}
}
}

UnitTestQueue.QueueUnitTest(id, start, end);
public static bool QueueUnitTest(uint id, Pointer start, Pointer end)
{
var len = (uint)start.GetOffset(end);

if (QueueNext + len + 32 > Queue + QueueSize)
{
if (Queue + len + 32 >= QueueCurrent)
return false; // no space

QueueNext.Store32(uint.MaxValue); // mark jump to front

// cycle to front
QueueNext = Queue;
}

QueueNext.Store32(len + 4);
QueueNext += 4;

QueueNext.Store32(id);
QueueNext += 4;

for (var i = start; i < end; i += 4)
{
uint value = i.Load32();
QueueNext.Store32(value);
QueueNext += 4;
}

QueueNext.Store32(0); // mark end
++PendingCount;

return true;
}

private static void SendTestUnitResponse()
public static void ProcessQueue()
{
if (UnitTestRunner.GetResult(out ulong result, out uint id))
if (QueueNext == QueueCurrent)
return;

if (!(ResultReported && !Ready))
return;

var marker = QueueCurrent.Load32();

if (marker == uint.MaxValue)
{
SendResponse(id, result);
QueueCurrent = Queue;
}

TestID = QueueCurrent.Load32(4);
TestMethodAddress = QueueCurrent.LoadPointer(8); // fix for 64bit
TestResultType = QueueCurrent.Load8(12);
TestParameterCount = QueueCurrent.Load8(16);

for (var index = 0u; index < TestParameterCount; index++)
{
var value = QueueCurrent.Load32(20 + index * 4);

Stack.Store32(index * 4, value);
}

var len = QueueCurrent.Load32();

QueueCurrent = QueueCurrent + len + 4;
--PendingCount;

DisplayUpdate();

Ready = true;
}

private static void ProcessTestUnitQueue() => UnitTestQueue.ProcessQueue();
public static void DisplayUpdate(bool test = false)
{
if (!test)
{
Screen.Goto(4, 0);
Screen.Write("Total : ");
Screen.Write(TestCount, 10, 7);

Screen.Goto(5, 0);
Screen.Write("Pending: ");
Screen.Write(PendingCount, 10, 7);
}
else
{
Screen.Goto(6, 0);
Screen.Write("Active : ");
Screen.Write(TestID, 10, 7);
Screen.Write(" @ ");
Screen.Write(TestMethodAddress.ToUInt32(), 16, 8);
}
}
}

0 comments on commit 8014d5d

Please sign in to comment.