Livt packages
Eccelerators.Cli
Version 1.4.1
Transport-independent, bounded command-line input, parsing, editing, and output for Livt FPGA applications.
Published files (23)
tests/CliTest.lvt
namespace Eccelerators.Cli.Tests
using Eccelerators.Cli
@Test
component CliTest
{
cli: Cli
silentCli: Cli
new()
{
this.cli = new Cli(true)
this.silentCli = new Cli(false)
}
fn WaitForPrompt()
{
assert this.cli.Service() == true
}
fn ConsumeExpected(value: byte)
{
assert this.cli.HasOutput() == true
assert this.cli.PeekOutput() == value
assert this.cli.ConsumeOutput() == true
}
fn ConsumePrompt()
{
this.ConsumeExpected(0x3E)
this.ConsumeExpected(0x20)
}
@Test
fn EmitsInitialPrompt()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
assert this.cli.HasOutput() == false
}
@Test
fn AcceptsAndParsesAnEchoedCommand()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
var line = "echo one two\n".Encode()
for (var i = 0; i < line.Length(); i++) {
assert this.cli.AcceptByte(line[i]) == true
}
assert this.cli.HasCommand() == true
var command = "echo".Encode()
var first = "one".Encode()
var second = "two".Encode()
assert this.cli.CommandEquals(command) == true
assert this.cli.GetArgumentCount() == 2
assert this.cli.ArgumentEquals(0, first) == true
assert this.cli.ArgumentEquals(1, second) == true
assert this.cli.CanAcceptByte() == false
}
@Test
fn EchoesBackspaceAsTerminalEraseSequence()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
assert this.cli.AcceptByte(0x61) == true
assert this.cli.AcceptByte(0x62) == true
assert this.cli.AcceptByte(0x08) == true
this.ConsumeExpected(0x61)
this.ConsumeExpected(0x62)
this.ConsumeExpected(0x08)
this.ConsumeExpected(0x20)
this.ConsumeExpected(0x08)
}
@Test
fn QueuesResponseThenNextPrompt()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
var line = "go\n".Encode()
for (var i = 0; i < line.Length(); i++) {
assert this.cli.AcceptByte(line[i]) == true
}
var response = "OK".Encode()
assert this.cli.TryWriteLine(response) == true
assert this.cli.CompleteCommand() == true
this.WaitForPrompt()
this.ConsumeExpected(0x67)
this.ConsumeExpected(0x6F)
this.ConsumeExpected(0x0D)
this.ConsumeExpected(0x0A)
this.ConsumeExpected(0x4F)
this.ConsumeExpected(0x4B)
this.ConsumeExpected(0x0D)
this.ConsumeExpected(0x0A)
this.ConsumePrompt()
}
@Test
fn EmptyLineSchedulesAnotherPromptWithoutCommand()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
assert this.cli.AcceptByte(0x0A) == true
assert this.cli.HasCommand() == false
this.WaitForPrompt()
this.ConsumeExpected(0x0D)
this.ConsumeExpected(0x0A)
this.ConsumePrompt()
}
@Test
fn ReportsOverflowAndRecoversToPrompt()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
for (var i = 0; i < CliLineEditor.MAX_LINE_LENGTH; i++) {
assert this.cli.AcceptByte(0x61) == true
this.ConsumeExpected(0x61)
}
assert this.cli.AcceptByte(0x62) == true
assert this.cli.AcceptByte(0x0A) == true
assert this.cli.HasCommand() == false
assert this.cli.GetOutputCount() == 24
assert this.cli.Service() == true
var expected = "\r\nError: line too long\r\n> ".Encode()
for (var i = 0; i < expected.Length(); i++) {
this.ConsumeExpected(expected[i])
}
assert this.cli.HasOutput() == false
}
@Test
fn WritesArgumentsAsOneLine()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
var line = "echo one two\n".Encode()
for (var i = 0; i < line.Length(); i++) {
assert this.cli.AcceptByte(line[i]) == true
}
for (var i = 0; i < line.Length() - 1; i++) {
this.ConsumeExpected(line[i])
}
this.ConsumeExpected(0x0D)
this.ConsumeExpected(0x0A)
assert this.cli.TryWriteArgumentsLine() == true
var expected = "one two\r\n".Encode()
for (var i = 0; i < expected.Length(); i++) {
this.ConsumeExpected(expected[i])
}
}
@Test
fn RejectsTooManyArgumentsAndRecoversToPrompt()
{
this.cli.Reset()
this.WaitForPrompt()
this.ConsumePrompt()
var line = "go 1 2 3 4 5 6 7 8 9\n".Encode()
for (var i = 0; i < line.Length(); i++) {
assert this.cli.AcceptByte(line[i]) == true
}
assert this.cli.HasCommand() == false
assert this.cli.Service() == true
var expected = "go 1 2 3 4 5 6 7 8 9\r\nError: too many arguments\r\n> ".Encode()
for (var i = 0; i < expected.Length(); i++) {
this.ConsumeExpected(expected[i])
}
assert this.cli.HasOutput() == false
}
@Test
fn AcceptsFreeTextWithMoreThanEightWords()
{
this.silentCli.Reset()
this.silentCli.EnableFreeText()
assert this.silentCli.Service() == true
assert this.silentCli.ConsumeOutput() == true
assert this.silentCli.ConsumeOutput() == true
var line = "one two three four five six seven eight nine ten\n".Encode()
for (var index = 0; index < line.Length(); index++) {
assert this.silentCli.AcceptByte(line[index]) == true
}
assert this.silentCli.HasCommand() == true
assert this.silentCli.GetLineLength() == line.Length() - 1
var expected = "one two three four five six seven eight nine ten".Encode()
for (var index = 0; index < expected.Length(); index++) {
assert this.silentCli.GetLineByte(index) == expected[index]
}
this.silentCli.DisableFreeText()
}
@Test
fn DisablesLocalEcho()
{
this.silentCli.Reset()
assert this.silentCli.Service() == true
assert this.silentCli.ConsumeOutput() == true
assert this.silentCli.ConsumeOutput() == true
var line = "go\n".Encode()
for (var i = 0; i < line.Length(); i++) {
assert this.silentCli.AcceptByte(line[i]) == true
}
assert this.silentCli.HasCommand() == true
assert this.silentCli.HasOutput() == false
}
@Test
fn AppliesAndReleasesInputBackpressure()
{
this.cli.Reset()
assert this.cli.Service() == true
var fill = "1234567890123456789012345678901".Encode()
assert this.cli.TryWrite(fill) == true
assert this.cli.CanAcceptByte() == false
assert this.cli.AcceptByte(0x61) == false
assert this.cli.ConsumeOutput() == true
assert this.cli.CanAcceptByte() == true
assert this.cli.AcceptByte(0x61) == true
}
}