Livt packages

Livt.Net

Version 1.4.1

Ethernet, IPv4, TCP, UDP, ARP, TFTP, and Telnet networking components for Livt hardware.

Published files (163)

tests/IcmpEchoResponderTest.lvt

namespace Livt.Net.Tests

using Livt.Net

/**
 * Checks prepared echo replies against request fixtures, independent bytes and rejected replacements.
 */
@Test
component IcmpEchoResponderTest
{
	// Shared request parsers; source remains owned by this fixture.
	ethernet: EthernetFrameParser<ArrayPacketData<128>>
	ipv4: Ipv4PacketParser<EthernetFrameParser<ArrayPacketData<128>>>

	data: ArrayPacketData<128>
	responder: IcmpEchoResponder<ArrayPacketData<128>, 128>

	/**
	 * Constructs the request buffer and responder in one clock context; request setup publishes data.
	 */
	new()
	{
		data = new ArrayPacketData<128>()
		this.ethernet = new EthernetFrameParser<ArrayPacketData<128>>(data)
		this.ipv4 = new Ipv4PacketParser<EthernetFrameParser<ArrayPacketData<128>>>(this.ethernet)
		responder = new IcmpEchoResponder<ArrayPacketData<128>, 128>(this.ethernet, this.ipv4)
	}

	/**
	 * Returns one octet of the deterministic echo-request fixture, including its padding.
	 */
	fn GetRequestByte(index: int) byte
	{
		if (index == 0) {
			return 0x02
		}

		if (index == 1) {
			return 0x55
		}

		if (index == 2) {
			return 0x66
		}

		if (index == 3) {
			return 0x77
		}

		if (index == 4) {
			return 0x11
		}

		if (index == 5) {
			return 0x22
		}

		if (index == 6) {
			return 0x02
		}

		if (index == 7) {
			return 0x10
		}

		if (index == 8) {
			return 0x20
		}

		if (index == 9) {
			return 0x30
		}

		if (index == 10) {
			return 0x40
		}

		if (index == 11) {
			return 0x50
		}

		if (index == 12) {
			return 0x08
		}

		if (index == 13) {
			return 0x00
		}

		if (index == 14) {
			return 0x45
		}

		if (index == 15) {
			return 0x00
		}

		if (index == 16) {
			return 0x00
		}

		if (index == 17) {
			return 0x28
		}

		if (index == 18) {
			return 0x12
		}

		if (index == 19) {
			return 0x34
		}

		if (index == 20) {
			return 0x40
		}

		if (index == 21) {
			return 0x00
		}

		if (index == 22) {
			return 0x40
		}

		if (index == 23) {
			return 0x01
		}

		if (index == 24) {
			return 0x00
		}

		if (index == 25) {
			return 0x00
		}

		if (index == 26) {
			return 0x0A
		}

		if (index == 27) {
			return 0x00
		}

		if (index == 28) {
			return 0x00
		}

		if (index == 29) {
			return 0x02
		}

		if (index == 30) {
			return 0x0A
		}

		if (index == 31) {
			return 0x00
		}

		if (index == 32) {
			return 0x00
		}

		if (index == 33) {
			return 0x01
		}

		if (index == 34) {
			return 0x08
		}

		if (index == 35) {
			return 0x00
		}

		if (index == 36) {
			return 0x7F
		}

		if (index == 37) {
			return 0x5E
		}

		if (index == 38) {
			return 0x12
		}

		if (index == 39) {
			return 0x34
		}

		if (index == 40) {
			return 0x00
		}

		if (index == 41) {
			return 0x01
		}

		if (index == 42) {
			return 0x61
		}

		if (index == 43) {
			return 0x62
		}

		if (index == 44) {
			return 0x63
		}

		if (index == 45) {
			return 0x64
		}

		if (index == 46) {
			return 0x65
		}

		if (index == 47) {
			return 0x66
		}

		if (index == 48) {
			return 0x67
		}

		if (index == 49) {
			return 0x68
		}

		if (index == 50) {
			return 0x69
		}

		if (index == 51) {
			return 0x6A
		}

		if (index == 52) {
			return 0x6B
		}

		if (index == 53) {
			return 0x6C
		}

		return 0x00
	}

	/**
	 * Prepares an independently initialized request and checks reply bytes or rejection behavior.
	 */
	@Test
	fn RecognizesEchoRequestForLocalIpv4()
	{
		var frame: byte[128]
		var localIp: byte[4]
		localIp[0] = 0x0A
		localIp[1] = 0x00
		localIp[2] = 0x00
		localIp[3] = 0x01

		for (var i = 0; i < 128; i++) {
			var requestByte = this.GetRequestByte(i)
			frame[i] = requestByte
		}

		assert (this.PrepareRequest(frame, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00], localIp, 128) == PacketDataResult.Success) == true
		var localMac: byte[6] = [0x02, 0x55, 0x66, 0x77, 0x11, 0x22]
		assert this.PrepareRequest(frame, localMac, localIp, 128) == PacketDataResult.Success
		assert this.responder.GetAvailableLength() == 60
		this.responder.Invalidate()

		localIp[3] = 0x03
		assert (this.PrepareRequest(frame, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00], localIp, 128) == PacketDataResult.Success) == false
	}

	/**
	 * Prepares an independently initialized request and checks reply bytes or rejection behavior.
	 */
	@Test
	fn BuildsEchoReplyBytes()
	{
		var frame: byte[128]
		var localMac: byte[6]
		localMac[0] = 0x02
		localMac[1] = 0x55
		localMac[2] = 0x66
		localMac[3] = 0x77
		localMac[4] = 0x11
		localMac[5] = 0x22
		var localIp: byte[4]
		localIp[0] = 0x0A
		localIp[1] = 0x00
		localIp[2] = 0x00
		localIp[3] = 0x01

		for (var i = 0; i < 128; i++) {
			var requestByte = this.GetRequestByte(i)
			frame[i] = requestByte
		}

		assert this.PrepareRequest(frame, localMac, localIp, 128) == PacketDataResult.Success
		var responderByte: byte = 0x00
		assert this.responder.TryRead(0, responderByte) == PacketDataResult.Success
		assert responderByte == 0x02
		assert this.responder.TryRead(5, responderByte) == PacketDataResult.Success
		assert responderByte == 0x50
		assert this.responder.TryRead(6, responderByte) == PacketDataResult.Success
		assert responderByte == 0x02
		assert this.responder.TryRead(11, responderByte) == PacketDataResult.Success
		assert responderByte == 0x22
		assert this.responder.TryRead(12, responderByte) == PacketDataResult.Success
		assert responderByte == 0x08
		assert this.responder.TryRead(13, responderByte) == PacketDataResult.Success
		assert responderByte == 0x00
		assert this.responder.TryRead(14, responderByte) == PacketDataResult.Success
		assert responderByte == 0x45
		assert this.responder.TryRead(17, responderByte) == PacketDataResult.Success
		assert responderByte == 0x28
		assert this.responder.TryRead(23, responderByte) == PacketDataResult.Success
		assert responderByte == 0x01
		assert this.responder.TryRead(24, responderByte) == PacketDataResult.Success
		assert responderByte == 0x14
		assert this.responder.TryRead(25, responderByte) == PacketDataResult.Success
		assert responderByte == 0x9F
		assert this.responder.TryRead(26, responderByte) == PacketDataResult.Success
		assert responderByte == 0x0A
		assert this.responder.TryRead(29, responderByte) == PacketDataResult.Success
		assert responderByte == 0x01
		assert this.responder.TryRead(30, responderByte) == PacketDataResult.Success
		assert responderByte == 0x0A
		assert this.responder.TryRead(33, responderByte) == PacketDataResult.Success
		assert responderByte == 0x02
		assert this.responder.TryRead(34, responderByte) == PacketDataResult.Success
		assert responderByte == 0x00
		assert this.responder.TryRead(36, responderByte) == PacketDataResult.Success
		assert responderByte == 0x87
		assert this.responder.TryRead(37, responderByte) == PacketDataResult.Success
		assert responderByte == 0x5E
		assert this.responder.TryRead(38, responderByte) == PacketDataResult.Success
		assert responderByte == 0x12
		assert this.responder.TryRead(53, responderByte) == PacketDataResult.Success
		assert responderByte == 0x6C
		assert this.responder.TryRead(59, responderByte) == PacketDataResult.Success
		assert responderByte == 0x00
	}

	/**
	 * Prepares an independently initialized request and checks reply bytes or rejection behavior.
	 */
	@Test
	fn TreatsHighBitBytesAsUnsigned()
	{
		var frame: byte[128]
		var localMac: byte[6]
		localMac[0] = 0x02
		localMac[1] = 0x55
		localMac[2] = 0x66
		localMac[3] = 0x77
		localMac[4] = 0x11
		localMac[5] = 0x22
		var localIp: byte[4]
		localIp[0] = 0x0A
		localIp[1] = 0x00
		localIp[2] = 0x00
		localIp[3] = 0x01

		for (var i = 0; i < 128; i++) {
			var requestByte = this.GetRequestByte(i)
			frame[i] = requestByte
		}

		frame[18] = 0xAB

		// Incoming checksum is deliberately inconsistent; reply is computed from bytes.
		frame[36] = 0xF1
		frame[37] = 0x02

		assert this.PrepareRequest(frame, localMac, localIp, 128) == PacketDataResult.Success
		var responderByte: byte = 0x00
		assert this.responder.TryRead(24, responderByte) == PacketDataResult.Success
		assert responderByte == 0x7B
		assert this.responder.TryRead(25, responderByte) == PacketDataResult.Success
		assert responderByte == 0x9E
		assert this.responder.TryRead(36, responderByte) == PacketDataResult.Success
		assert responderByte == 0x87
		assert this.responder.TryRead(37, responderByte) == PacketDataResult.Success
		assert responderByte == 0x5E
	}

	/**
	 * Prepares an independently initialized request and checks reply bytes or rejection behavior.
	 */
	@Test
	fn HoldsPreparedBytesAndClearsFailedReplacement()
	{
		var request: byte[128]
		var mac: byte[6] = [0x02, 0x55, 0x66, 0x77, 0x11, 0x22]
		var ip: byte[4] = [0x0A, 0x00, 0x00, 0x01]
		var value: byte = 0x00

		for (var i = 0; i < 128; i++) {
			request[i] = this.GetRequestByte(i)
		}

		assert this.PrepareRequest(request, mac, ip, 54) == PacketDataResult.Success
		request[42] = 0xFF
		request[33] = 0x03

		// Reuse the actual request provider; the reply owns its snapshot and checksum.
		assert data.TryRelease() == PacketDataResult.Success
		assert data.TryWrite(0, 0xEE) == PacketDataResult.Success
		assert data.TryPublish() == PacketDataResult.Success
		assert responder.TryRead(42, value) == PacketDataResult.Success
		assert value == 0x61
		assert responder.TryRead(36, value) == PacketDataResult.Success
		assert value == 0x87
		assert this.PrepareRequest(request, mac, ip, 54) == PacketDataResult.Invalid
		assert responder.IsReady() == false
		assert responder.GetAvailableLength() == 0
		assert responder.TryRead(0, value) == PacketDataResult.NotReady
		request[33] = 0x01
		assert this.PrepareRequest(request, mac, ip, 53) == PacketDataResult.Invalid
		assert this.PrepareRequest(request, mac, ip, 54) == PacketDataResult.Success
		assert responder.TryRead(42, value) == PacketDataResult.Success
		assert value == 0xFF
		responder.Invalidate()
	}


	/** Checks the padded final checksum word while checksum and snapshot share one pass. */
	@Test
	fn BuildsOddLengthEchoReply()
	{
		var request: byte[128]
		var mac: byte[6] = [0x02, 0x55, 0x66, 0x77, 0x11, 0x22]
		var ip: byte[4] = [0x0A, 0x00, 0x00, 0x01]

		for (var i = 0; i < 128; i++) {
			request[i] = this.GetRequestByte(i)
		}

		request[17] = 0x25
		assert this.PrepareRequest(request, mac, ip, 51) == PacketDataResult.Success
		assert responder.GetAvailableLength() == 60
		var value: byte = 0x00
		assert responder.TryRead(17, value) == PacketDataResult.Success
		assert value == 0x25
		assert responder.TryRead(24, value) == PacketDataResult.Success
		assert value == 0x14
		assert responder.TryRead(25, value) == PacketDataResult.Success
		assert value == 0xA2
		assert responder.TryRead(36, value) == PacketDataResult.Success
		assert value == 0xF3
		assert responder.TryRead(37, value) == PacketDataResult.Success
		assert value == 0x34
		assert responder.TryRead(50, value) == PacketDataResult.Success
		assert value == 0x69
		assert responder.TryRead(51, value) == PacketDataResult.Success
		assert value == 0x00
	}

	/**
	 * Loads the explicit test prefix into the component-based response API.
	 */
	fn PrepareRequest(bytes: byte[128], mac: byte[6], ip: byte[4], length: int) PacketDataResult
	{
		responder.Invalidate()

		if (data.IsReady()) {
			data.TryRelease()
		}
		else {
			data.TryClear()
		}

		for (var i = 0; i < length; i++) {
			assert data.TryWrite(i, bytes[i]) == PacketDataResult.Success
		}

		assert data.TryPublish() == PacketDataResult.Success
		return responder.TryPrepare(mac, ip)
	}
}