Skip to content

Commit

Permalink
cncint cnclon and cncnum fixes (#193)
Browse files Browse the repository at this point in the history
* Temporary checkin so I can merge master

* Get cncnum/cncint/cnclon reimplement working prior to adding new tests.

* Create cnclon_Tests.cs

* Add a test for adding btrieve items and then printing them out.

* Cleanup self review issues.

* Address PR review comments
  • Loading branch information
paladine committed Oct 14, 2020
1 parent e65ee43 commit 717e2e8
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 160 deletions.
Binary file modified MBBSEmu.Tests/Assets/MBBSEMU.DLL
Binary file not shown.
95 changes: 95 additions & 0 deletions MBBSEmu.Tests/ExportedModules/Majorbbs/cnclon_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using MBBSEmu.Memory;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace MBBSEmu.Tests.ExportedModules.Majorbbs
{
public class cnclon_Tests : ExportedModuleTestBase
{
private const int CNCLON_ORDINAL = 126;
private const int CNCINT_ORDINAL = 125;

[Theory]
[InlineData("100", 0, 100, 3)]
[InlineData("-100", 0, -100, 4)]
[InlineData("-100abc000", 0, -100, 4)]
[InlineData("-89755abc000", 0, -89755, 6)]
[InlineData("89755abc000", 0, 89755, 5)]
[InlineData("1234567890123", 0, 0, 11)] //test truncation
[InlineData("abc123", 0, 0, 0)]
[InlineData("abc123", 3, 123, 6)]
[InlineData("abc123", 2, 0, 2)]
[InlineData("abc 123", 3, 123, 7)]
[InlineData("abc -123", 3, -123, 8)]
[InlineData("", 0, 0, 0)]
public void cnclon_Test(string inputString, ushort nxtcmdStartingOffset, int expectedResult, ushort expectedNxtcmdOffset)
{
//Reset State
Reset();

//Set Input Values
var inputLength = (ushort)inputString.Length;

var input = mbbsModule.Memory.GetVariablePointer("INPUT");

mbbsModule.Memory.SetArray(input, Encoding.ASCII.GetBytes(inputString));
mbbsModule.Memory.SetByte(input + inputString.Length, 0);
mbbsModule.Memory.SetWord("INPLEN", inputLength);

//Set nxtcmd
var currentNxtcmd = mbbsEmuMemoryCore.GetPointer("NXTCMD");
var expectedNxtCmd = currentNxtcmd + expectedNxtcmdOffset;
currentNxtcmd.Offset += nxtcmdStartingOffset;
mbbsEmuMemoryCore.SetPointer("NXTCMD", currentNxtcmd);

//Execute Test
ExecuteApiTest(HostProcess.ExportedModules.Majorbbs.Segment, CNCLON_ORDINAL, new List<IntPtr16>());

//Verify Results
Assert.Equal(expectedResult, mbbsEmuCpuCore.Registers.GetLong());
Assert.Equal(expectedNxtCmd, mbbsEmuMemoryCore.GetPointer("NXTCMD"));
}

[Theory]
[InlineData("100", 0, 100, 3)]
[InlineData("-100", 0, -100, 4)]
[InlineData("-100abc000", 0, -100, 4)]
[InlineData("-89755abc000", 0, -24219, 6)]
[InlineData("89755abc000", 0, 24219, 5)]
[InlineData("1234567890123", 0, 0, 11)] //test truncation
[InlineData("abc123", 0, 0, 0)]
[InlineData("abc123", 3, 123, 6)]
[InlineData("abc123", 2, 0, 2)]
[InlineData("abc 123", 3, 123, 7)]
[InlineData("abc -123", 3, -123, 8)]
[InlineData("", 0, 0, 0)]
public void cncint_Test(string inputString, ushort nxtcmdStartingOffset, short expectedResult, ushort expectedNxtcmdOffset)
{
//Reset State
Reset();

//Set Input Values
var inputLength = (ushort)inputString.Length;

var input = mbbsModule.Memory.GetVariablePointer("INPUT");

mbbsModule.Memory.SetArray(input, Encoding.ASCII.GetBytes(inputString));
mbbsModule.Memory.SetByte(input + inputString.Length, 0);
mbbsModule.Memory.SetWord("INPLEN", inputLength);

//Set nxtcmd
var currentNxtcmd = mbbsEmuMemoryCore.GetPointer("NXTCMD");
var expectedNxtCmd = currentNxtcmd + expectedNxtcmdOffset;
currentNxtcmd.Offset += nxtcmdStartingOffset;
mbbsEmuMemoryCore.SetPointer("NXTCMD", currentNxtcmd);

//Execute Test
ExecuteApiTest(HostProcess.ExportedModules.Majorbbs.Segment, CNCINT_ORDINAL, new List<IntPtr16>());

//Verify Results
Assert.Equal(expectedResult, (short) mbbsEmuCpuCore.Registers.AX);
Assert.Equal(expectedNxtCmd, mbbsEmuMemoryCore.GetPointer("NXTCMD"));
}
}
}
30 changes: 16 additions & 14 deletions MBBSEmu.Tests/ExportedModules/Majorbbs/cncnum_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ public class cncnum_Tests : ExportedModuleTestBase
private const int CNCNUM_ORDINAL = 127;

[Theory]
[InlineData("100\0", 0, "100", 4)]
[InlineData("-100\0", 0, "-100", 5)]
[InlineData("-100abc000\0", 0, "-100", 5)]
[InlineData("1234567890123\0", 0, "123456789012", 13)] //test truncation
[InlineData("abc123\0", 0, "", 0)]
[InlineData("abc123\0", 3, "123", 7)]
[InlineData("abc123\0", 2, "", 2)]
[InlineData("abc 123\0", 3, "123", 8)]
[InlineData("abc -123\0", 3, "-123", 9)]
[InlineData("\0", 0, "", 0)]
[InlineData("100", 0, "100", 3)]
[InlineData("-100", 0, "-100", 4)]
[InlineData("-100abc000", 0, "-100", 4)]
[InlineData("1234567890123", 0, "12345678901", 11)] //test truncation
[InlineData("abc123", 0, "", 0)]
[InlineData("abc123", 3, "123", 6)]
[InlineData("abc123", 2, "", 2)]
[InlineData("abc 123", 3, "123", 7)]
[InlineData("abc -123", 3, "-123", 8)]
[InlineData("", 0, "", 0)]
public void cncnum_Test(string inputString, ushort nxtcmdStartingOffset, string expectedResult, ushort expectedNxtcmdOffset)
{
//Reset State
Expand All @@ -28,22 +28,24 @@ public void cncnum_Test(string inputString, ushort nxtcmdStartingOffset, string
//Set Input Values
var inputLength = (ushort)inputString.Length;

mbbsModule.Memory.SetArray("INPUT", Encoding.ASCII.GetBytes(inputString));
var input = mbbsModule.Memory.GetVariablePointer("INPUT");

mbbsModule.Memory.SetArray(input, Encoding.ASCII.GetBytes(inputString));
mbbsModule.Memory.SetByte(input + inputString.Length, 0);
mbbsModule.Memory.SetWord("INPLEN", inputLength);

//Set nxtcmd
var currentNxtcmd = mbbsEmuMemoryCore.GetPointer("NXTCMD");
var expectedNxtCmd = currentNxtcmd + expectedNxtcmdOffset;
currentNxtcmd.Offset += nxtcmdStartingOffset;
mbbsEmuMemoryCore.SetPointer("NXTCMD", currentNxtcmd);

//Execute Test
ExecuteApiTest(HostProcess.ExportedModules.Majorbbs.Segment, CNCNUM_ORDINAL, new List<IntPtr16>());

//Verify Results
var expectedResultPointer = mbbsEmuMemoryCore.GetVariablePointer("INPUT");
expectedResultPointer.Offset += expectedNxtcmdOffset;
Assert.Equal(expectedResult, Encoding.ASCII.GetString(mbbsEmuMemoryCore.GetString(mbbsEmuCpuCore.Registers.DX, mbbsEmuCpuCore.Registers.AX, true)));
Assert.Equal(expectedResultPointer, mbbsEmuMemoryCore.GetPointer("NXTCMD"));
Assert.Equal(expectedNxtCmd, mbbsEmuMemoryCore.GetPointer("NXTCMD"));
}
}
}
56 changes: 55 additions & 1 deletion MBBSEmu.Tests/Integration/BtrievePrint_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace MBBSEmu.Tests.Integration
public class BtrievePrint_Tests : MBBSEmuIntegrationTestBase
{
[Fact]
public void DoEchoTestAndLogOff()
public void DoPrintTestAndLogOff()
{
ExecuteTest((session, host) => {
WaitUntil(':', "Make your selection");
Expand Down Expand Up @@ -37,5 +37,59 @@ public void DoEchoTestAndLogOff()
WaitUntil('.', "Have a nice day");
});
}

private static int mbbsemuHash(string s)
{
int hash = 7;
foreach (char c in s)
{
hash = hash * 31 + c;
}
return hash;
}

[Fact]
public void AddItemsAndPrintTestAndThenLogoff()
{
ExecuteTest((session, host) => {
WaitUntil(':', "Make your selection");
session.SendToModule(Encoding.ASCII.GetBytes("B\r\n"));
WaitUntil(':', "Make your selection");
// add - by id - 31337
session.SendToModule(Encoding.ASCII.GetBytes("AI31337\r\n"));
WaitUntil(':', "Make your selection");
// add - by string - mbbs4evr
session.SendToModule(Encoding.ASCII.GetBytes("ASmbbs4evr\r\n"));
WaitUntil(':', "Make your selection");
session.SendToModule(Encoding.ASCII.GetBytes("P\r\n"));
var lines = WaitUntil('.', "Press X to exit");
var expected = new List<string>() {
" P\r\nPrinting all the btrieve rows.",
".",
".",
"\r\nuid: Sysop lvalue: 23923 svalue: \r\n" +
"uid: Sysop lvalue: 0 svalue: Whatever\r\n" +
"uid: Sysop lvalue: 23556 svalue: 3553088\r\n" +
"uid: Sysop lvalue: 3774400 svalue: hahah\r\n" +
"uid: Sysop lvalue: 31337 svalue: 31337\r\n" +
$"uid: Sysop lvalue: {mbbsemuHash("mbbs4evr")} svalue: mbbs4evr\r\n" +
"Press X to exit.",
};
Assert.Equal(expected, lines);
session.SendToModule(Encoding.ASCII.GetBytes("x\r\nx\r\nx\r\nx\r\nY\r\n"));
WaitUntil('.', "Have a nice day");
});
}

// TODO(paladine): Add a test that inserts the same key to verify key restraints
}
}
8 changes: 8 additions & 0 deletions MBBSEmu/CPU/CPURegisters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,14 @@ public int GetLong(Register highBytes, Register lowBytes)
return (GetValue(highBytes) << 16) | GetValue(lowBytes);
}

/// <summary>
/// Returns a 32-bit long from DX:AX
/// </summary>
public int GetLong()
{
return DX << 16 | AX;
}

/// <summary>
/// Returns a DOS.H compatible struct for register values (WORDREGS, BYTEREGS)
/// </summary>
Expand Down
76 changes: 47 additions & 29 deletions MBBSEmu/HostProcess/ExportedModules/ExportedModuleBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,29 @@ namespace MBBSEmu.HostProcess.ExportedModules
/// </summary>
public abstract class ExportedModuleBase
{
/// <summary>
/// The return value from the GetLeadingNumberFromString methods
/// </summary>
protected class LeadingNumberFromStringResult
{
/// <summary>Whether the integer parsing succeeded</summary>
public bool Valid { get; set; }
/// <summary>The integer valued parsed. Only valid is Valid is true, otherwise 0.</summary>
public int Value { get; set; }
/// <summary>The raw string that was parsed.</summary>
public string StringValue { get; set; }
/// <summary>True to indicate there is more input following what was parsed</summary>
public bool MoreInput { get; set; }

public LeadingNumberFromStringResult()
{
Valid = false;
Value = 0;
StringValue = "";
MoreInput = false;
}
}

public const ushort OUTBUF_SIZE = 8192;

/// <summary>
Expand Down Expand Up @@ -859,14 +882,19 @@ protected enum CharacterAccepterResponse
/// <summary>
/// Consumes all whitespace from input and moves to the first non-whitespace character.
/// </summary>
protected bool ConsumeWhitespace(IEnumerator<char> input)
/// <return>boolean for whether there is more input remaining, and an integer for the count
/// of characters consumed/skipped</return>
protected (bool, int) ConsumeWhitespace(IEnumerator<char> input)
{
var count = 0;
do {
if (!char.IsWhiteSpace(input.Current))
return true;
return (true, count);

++count;
} while (input.MoveNext());

return false;
return (false, count);
}

/// <summary>
Expand All @@ -877,7 +905,8 @@ protected bool ConsumeWhitespace(IEnumerator<char> input)
{
var builder = new StringBuilder();

if (!ConsumeWhitespace(input))
var (moreInput, _) = ConsumeWhitespace(input);
if (!moreInput)
return ("", false);

do {
Expand All @@ -903,32 +932,29 @@ protected bool ConsumeWhitespace(IEnumerator<char> input)
/// This method extracts the valid number (if any) from the given string
/// </summary>
/// <param name="input">Input IEnumerator, assumes MoveNext has already been called</param>
/// <param name="success">True if a valid integer was parsed and returned</param>
/// <return>The number, and a boolean indicating whether there is more input to be read.
/// "123test" would return (123, true) where "123" would return (123, false)
/// </return>
private protected (int, bool) GetLeadingNumberFromString(IEnumerator<char> input, out bool success)
private protected LeadingNumberFromStringResult GetLeadingNumberFromString(IEnumerator<char> input)
{
success = false;

var result = new LeadingNumberFromStringResult();
var count = 0;

var (possibleInteger, moreInput) = ReadString(input, c => {
(result.StringValue, result.MoreInput) = ReadString(input, c => {
if (count >= 11)
return CharacterAccepterResponse.ABORT;
var first = (count++ == 0);
if (first && c == '+')
return CharacterAccepterResponse.SKIP;
if (char.IsDigit(c) || (first && c == '-'))
if ((first && c == '-') || char.IsDigit(c))
return CharacterAccepterResponse.ACCEPT;
return CharacterAccepterResponse.ABORT;
});

result.Valid = Int32.TryParse(result.StringValue, out var value);
if (result.Valid)
result.Value = value;

success = int.TryParse(possibleInteger, out var result);
if (!success)
_logger.Warn($"Unable to cast to long: {possibleInteger}");

return (result, moreInput);
return result;
}

/// <summary>
Expand All @@ -938,21 +964,13 @@ private protected (int, bool) GetLeadingNumberFromString(IEnumerator<char> input
/// This method extracts the valid number (if any) from the given string
/// </summary>
/// <param name="inputString">Input string containers integer values</param>
/// <param name="success">True if a valid integer was parsed and returned</param>
/// <return>The number, and a boolean indicating whether there is more input to be read.
/// "123test" would return (123, true) where "123" would return (123, false)
/// </return>
private protected (int, bool) GetLeadingNumberFromString(string inputString, out bool success)
private protected LeadingNumberFromStringResult GetLeadingNumberFromString(string inputString)
{
var enumerator = inputString.GetEnumerator();
if (!enumerator.MoveNext())
{
success = false;
return (0, false);
}

return GetLeadingNumberFromString(enumerator, out success);
return enumerator.MoveNext() ? GetLeadingNumberFromString(enumerator) : new LeadingNumberFromStringResult();
}

/// <summary>
/// Handles calling functions to format bytes to be sent to the client.
///
Expand Down
Loading

0 comments on commit 717e2e8

Please sign in to comment.