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/CliStorageBackendTest.lvt

namespace Eccelerators.Cli.Tests

using Eccelerators.Cli
using Livt.IO

/**
 * Consumer-provided resettable array backend, independent of physical RAM hints.
 */
component CliTestArrayStorage : IRam<byte>
{
	// Every entry is resettable; callers still rely only on initialized prefixes.
	cells: byte[64]

	/**
	 * Constructs empty array storage in the inherited context.
	 */
	new()
	{
	}

	/**
	 * Reads an addressed byte, returning zero for invalid addresses.
	 */
	override fn Read(address: int) byte
	{
		if (!IsValidAddress(address)) {
			return 0
		}

		return cells[address]
	}

	/**
	 * Writes an addressed byte; invalid writes have no effect.
	 */
	override fn Write(address: int, value: byte)
	{
		if (IsValidAddress(address)) {
			cells[address] = value
		}
	}

	/**
	 * Reports whether the address selects one of the 64 bytes.
	 */
	override fn IsValidAddress(address: int) bool
	{
		return address >= 0 && address < 64
	}
}

/**
 * Exercises identical initialized-prefix and ring behavior for each backend.
 */
component CliStorageChecks<B: IRam<byte> & new()>
{
	// Each component owns a different instance of the selected backend.
	parser: CliParser<B>
	output: CliOutput<B>
	cli: Cli<B, B>

	/**
	 * Creates independent stores; no test assumes initial payload values.
	 */
	new()
	{
		parser = new CliParser<B>()
		output = new CliOutput<B>()
		cli = new Cli<B, B>(false)
	}

	/**
	 * Checks full capacity, rejection, wraparound, clear and parser invalidation.
	 */
	public fn Run()
	{
		output.Clear()
		parser.Clear()

		for (var i = 0; i < 64; i++) {
			assert output.TryWriteByte(i as byte)
			assert parser.AppendByte(65)
		}

		assert !output.TryWriteByte(255)
		assert !parser.AppendByte(66)
		assert parser.GetLineLength() == 64

		for (var i = 0; i < 32; i++) {
			assert output.Peek() == (i as byte)
			assert output.Consume()
		}

		for (var i = 64; i < 96; i++) {
			assert output.TryWriteByte(i as byte)
		}

		for (var i = 32; i < 96; i++) {
			assert output.Peek() == (i as byte)
			assert output.Consume()
		}

		assert output.Peek() == 0
		assert !output.Consume()
		assert output.TryWriteByte(90)
		output.Clear()
		assert output.GetCount() == 0
		assert output.Peek() == 0
		parser.Clear()
		assert parser.GetLineLength() == 0
		assert parser.GetLineByte(0) == 0
		assert parser.AppendByte(120)
		assert parser.AppendByte(32)
		assert parser.AppendByte(50)
		parser.Parse()
		assert parser.GetCommandLength() == 1
		assert parser.GetArgumentCount() == 1
		assert parser.GetArgumentByte(0, 0) == 50
		assert parser.GetArgumentByte(0, 1) == 0

		while (cli.HasOutput()) {
			cli.ConsumeOutput()
		}

		assert cli.AcceptByte(120)
		assert cli.AcceptByte(13)
		assert cli.HasCommand()
		assert cli.GetArgumentCount() == 0
		cli.CompleteCommand()
		assert !cli.HasCommand()
	}
}

/**
 * Confirms consumer-selected storage preserves observable CLI behavior.
 */
@Test
component CliStorageBackendTest
{
	// Independently owned block, distributed, automatic and custom-array checks.
	block: CliStorageChecks<Ram<byte, 64, MemoryStyle.Block>>
	distributed: CliStorageChecks<Ram<byte, 64, MemoryStyle.Distributed>>
	automatic: CliStorageChecks<Ram<byte, 64>>
	array: CliStorageChecks<CliTestArrayStorage>

	/**
	 * Instantiates all supported portable storage choices.
	 */
	new()
	{
		block = new CliStorageChecks<Ram<byte, 64, MemoryStyle.Block>>()
		distributed = new CliStorageChecks<Ram<byte, 64, MemoryStyle.Distributed>>()
		automatic = new CliStorageChecks<Ram<byte, 64>>()
		array = new CliStorageChecks<CliTestArrayStorage>()
	}

	/**
	 * Checks the default block-storage behavior.
	 */
	@Test
	fn BlockStorage()
	{
		block.Run()
	}

	/**
	 * Checks distributed storage in a portable, vendor-neutral build.
	 */
	@Test
	fn DistributedStorage()
	{
		distributed.Run()
	}

	/**
	 * Checks automatically inferred storage.
	 */
	@Test
	fn AutomaticStorage()
	{
		automatic.Run()
	}

	/**
	 * Checks a consumer-provided array implementation.
	 */
	@Test
	fn ArrayStorage()
	{
		array.Run()
	}
}