Map27
 All Classes Functions Variables Enumerations Enumerator Pages
test.cpp
Version
1.3 2011-12-8 Fixed incorrect distro link.

Test suite that exercises and tests much of the code without being connected to a real radio

// test.cpp
//
// Map27 test suite
//
// Author: Mike McCauley (mikem@airspayce.com)
// Copyright (C) 2013 Mike McCauley
// $Id: test.cpp,v 1.12 2013/07/14 07:15:46 mikem Exp mikem $
#include "FCS.h"
#include "Address.h"
#include "PhysicalLayer.h"
#include "Port.h"
#include "DataLayer.h"
#include "NetworkLayer.h"
#include "ApplicationLayer.h"
#include "Timer.h"
#include "Log.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
class TestPort : public Map27Port
{
public:
TestPort()
{
peer = 0;
readPos = 0;
writePos = 0;
}
void send(uint8_t ch)
{
peer->buf[peer->writePos++] = ch;
}
bool canRead()
{
return (readPos != writePos);
}
uint8_t read()
{
return buf[readPos++];
}
#define TEST_BUF_LEN 256
TestPort* peer;
uint8_t buf[TEST_BUF_LEN];
uint8_t readPos;
uint8_t writePos;
};
class TestPhysicalLayer : public Map27PhysicalLayer
{
public:
uint8_t d1;
uint8_t d2;
uint8_t d3;
uint8_t savebuf[MAP27_MAX_MESSAGE_LEN];
uint16_t savebufLen;
void handleLinkRequest(uint8_t n1, uint8_t k, uint8_t version)
{
d1 = n1;
d2 = k;
d3 = version;
}
void handleLinkAcknowledge(uint8_t n_r, uint8_t n_k)
{
d1 = n_r;
d2 = n_k;
}
void handleLinkTransfer(uint8_t n_s, uint8_t ar, uint8_t* buf, uint16_t bufLen)
{
d1 = n_s;
d2 = ar;
memcpy(savebuf, buf, bufLen);
savebufLen = bufLen;
}
};
class TestDataLayer : public Map27DataLayer
{
public:
uint32_t numPackets;
TestDataLayer()
{
numPackets = 0;
}
void output_network_layer_packet(uint8_t* buf, uint16_t bufLen)
{
numPackets++;
}
};
class TestNetworkLayer : public Map27NetworkLayer
{
public:
uint8_t savebuf[MAP27_MAX_MESSAGE_LEN];
uint16_t savebufLen;
uint32_t numPackets;
TestNetworkLayer()
{
savebufLen = 0;
numPackets = 0;
}
void receiveStatus(uint8_t* buf, uint16_t bufLen)
{
memcpy(savebuf, buf, bufLen);
savebufLen = bufLen;
numPackets++;
// Fake a StatusAck so sender returns to IDLE
uint8_t msg[6];
msg[0] = MAP27_NETWORK_MESSAGE_TYPE_ACK_POSITIVE;
msg[1] = MAP27_ADDRESS_DUMMYP;
msg[2] = MAP27_ADDRESS_DUMMYI;
msg[3] = MAP27_ADDRESS_DUMMYI;
msg[4] = MAP27_ADDRESS_ADESC_NO_ADDRESS;
msg[5] = MAP27_NETWORK_MESSAGE_STATUS_CAUSE_SUCCESS;
dataLayer()->network_layer_packet(msg, sizeof(msg));
}
};
class TestApplicationLayer : public Map27ApplicationLayer
{
public:
uint8_t savebuf[MAP27_MAX_MESSAGE_LEN];
uint8_t savedata;
uint16_t savebufLen;
uint32_t numPackets;
TestApplicationLayer()
{
savebufLen = 0;
numPackets = 0;
}
void receiveStatus(Map27Address& address, uint8_t status)
{
numPackets++;
savedata = status;
// Fake a StatusAck so sender returns to IDLE
uint8_t msg[6];
msg[0] = MAP27_NETWORK_MESSAGE_TYPE_ACK_POSITIVE;
msg[1] = MAP27_ADDRESS_DUMMYP;
msg[2] = MAP27_ADDRESS_DUMMYI;
msg[3] = MAP27_ADDRESS_DUMMYI;
msg[4] = MAP27_ADDRESS_ADESC_NO_ADDRESS;
msg[5] = MAP27_NETWORK_MESSAGE_STATUS_CAUSE_SUCCESS;
networkLayer()->dataLayer()->network_layer_packet(msg, sizeof(msg));
}
void receiveSST(Map27Address& address, uint8_t* buf, uint8_t bufLen)
{
memcpy(savebuf, buf, bufLen);
savebufLen = bufLen;
numPackets++;
// Fake a SSTAck so sender returns to IDLE
uint8_t msg[6];
msg[0] = MAP27_NETWORK_MESSAGE_TYPE_ACK_POSITIVE;
msg[1] = MAP27_ADDRESS_DUMMYP;
msg[2] = MAP27_ADDRESS_DUMMYI;
msg[3] = MAP27_ADDRESS_DUMMYI;
msg[4] = MAP27_ADDRESS_ADESC_NO_ADDRESS;
msg[5] = MAP27_NETWORK_MESSAGE_STATUS_CAUSE_SUCCESS;
networkLayer()->dataLayer()->network_layer_packet(msg, sizeof(msg));
}
};
static uint32_t test_num = 0;
void ok(bool test)
{
test_num++;
printf("%d: \t%s\n", test_num, test ? "OK" : "Not OK");
}
uint8_t timerTriggerCount = 0;
void timerCallback(void* arg)
{
timerTriggerCount++;
}
void
testTimer()
{
t.setInterval(1500);
t.setCallback(timerCallback);
t.start();
ok(timerTriggerCount == 0);
ok(t.active());
sleep(1);
t.poll();
ok(t.active());
sleep(2);
t.poll();
ok(!t.active());
ok(timerTriggerCount == 1);
}
void testFcs()
{
unsigned char test1[] = { 0x3b }; /* FCS = 0x016c */
unsigned char test2[] = "123456789"; /* b4c8 or c8b4 ???? */
unsigned char test3[] = { 0x01, 0x06, 0x01, 0x01, 0x10, 0x03 }; /* Tait 2040 LR FCS = 0x6bc8 */
unsigned int result;
result = Map27FCS::fcs(test1, sizeof(test1));
ok(result == 0x016c);
result = Map27FCS::fcs(test2, sizeof(test2) - 1);
ok(result == 0xc8b4);
result = Map27FCS::fcs(test3, sizeof(test3));
ok(result == 0x6bc8);
}
void testAddress()
{
a.setPrefix(123);
ok(a.prefix() == 123);
a.setIdent(MAP27_ADDRESS_PSTNGI);
ok(a.ident() == MAP27_ADDRESS_PSTNGI);
uint8_t binary_address[] = { 0x11, 0x22, 0x33 };
a.setAddress(MAP27_ADDRESS_ADESC_SAMIS_BCD, binary_address, sizeof(binary_address));
ok(a.adesc() == MAP27_ADDRESS_ADESC_SAMIS_BCD);
ok(a.alen() == sizeof(binary_address));
ok(memcmp(a.address(), binary_address, sizeof(binary_address)) == 0);
// Test decoding of prefix/ident
uint8_t test_address_basic[] = { 0x01, 0x02, 0x03 };
ok(a.decodeBasic(test_address_basic, sizeof(test_address_basic)) == 3);
ok(a.decodeBasic(test_address_basic, sizeof(test_address_basic) - 1) == 0); // insuff data
ok(a.prefix() == 1);
ok(a.ident() == 515);
ok(a.adesc() == MAP27_ADDRESS_ADESC_NO_ADDRESS);
ok(a.alen() == 0);
uint8_t test_address[] = { 0x02, 0x03, 0x04, 0x12, 0x11, 0x22 };
ok(a.decode(test_address, sizeof(test_address)) == 6);
ok(a.decode(test_address, sizeof(test_address) - 1) == 0); // insuff data
uint8_t buf[30];
ok(a.encodeBasic(buf, sizeof(buf)) == 3);
ok(memcmp(buf, test_address, 3) == 0);
ok(a.encode(buf, sizeof(buf)) == 6);
ok(memcmp(buf, test_address, sizeof(test_address)) == 0);
// Test prefix/UI conversions
// Sample data from my Tait 2040:
// IBI is 5602
uint16_t ibi = 5602;
a.setPrefix(7);
a.setIdent(5996);
ok(a.mpt1343_prefix() == 207);
ok(a.mpt1343_fin(ibi) == 4801);
ok(a.mpt1343_un3d(ibi) == 594);
}
void testPhysical()
{
TestPort port1;
TestPort port2;
TestPhysicalLayer p1;
TestPhysicalLayer p2;
port1.peer = &port2;
port2.peer = &port1;
p1.setPort(&port1);
p2.setPort(&port2);
p1.sendLinkRequest(1, 2, 3);
p1.poll();
p2.poll();
ok(p2.d1 == 1);
ok(p2.d2 == 2);
ok(p2.d3 == 3);
p1.sendLinkAcknowledge(3, 4);
p1.poll();
p2.poll();
ok(p2.d1 == 3);
ok(p2.d2 == 4);
uint8_t data1[] = { 0x00, 0x10, 0x11, 0x12, 0x13}; // Requires a DLE stuff
p1.sendLinkTransfer(5, 6, data1, sizeof(data1));
p1.poll();
p2.poll();
ok(p2.d1 == 5);
ok(p2.d2 == 6);
ok(p2.savebufLen == sizeof(data1));
ok(memcmp(p2.savebuf, data1, sizeof(data1)) == 0);
}
void testDataLayer()
{
TestPort port1;
TestPort port2;
TestDataLayer dl1;
TestDataLayer dl2;
port1.peer = &port2;
port2.peer = &port1;
pl1.setPort(&port1);
pl2.setPort(&port2);
pl1.setDataLayer(&dl1);
pl2.setDataLayer(&dl2);
dl1.setPhysicalLayer(&pl1);
dl2.setPhysicalLayer(&pl2);
dl1.power_on();
dl2.power_on();
uint8_t count = 0;
uint32_t i;
while (dl2.numPackets < 10)
{
dl1.poll();
dl2.poll();
uint8_t buf[] = { 0xb0, count++ };
dl1.network_layer_packet(buf, sizeof(buf));
}
ok(dl1.isReady());
ok(dl2.isReady());
ok(dl2.numPackets == 10);
}
void testNetworkLayer()
{
TestPort port1;
TestPort port2;
TestNetworkLayer nl1;
TestNetworkLayer nl2;
port1.peer = &port2;
port2.peer = &port1;
pl1.setPort(&port1);
pl2.setPort(&port2);
pl1.setDataLayer(&dl1);
pl2.setDataLayer(&dl2);
dl1.setPhysicalLayer(&pl1);
dl2.setPhysicalLayer(&pl2);
dl1.setNetworkLayer(&nl1);
dl2.setNetworkLayer(&nl2);
nl1.setDataLayer(&dl1);
nl2.setDataLayer(&dl2);
nl1.power_on();
nl2.power_on();
Map27Address address;
address.setPrefix(7);
address.setIdent(5996);
uint32_t i;
while (nl2.numPackets < 10)
{
nl1.poll();
nl2.poll();
nl1.sendStatus(address, 1);
}
ok(nl2.numPackets == 10);
uint8_t expected[] = { 0x80, 0x07, 0x17, 0x6c, 0x00, 0x01 };
ok(memcmp(expected, nl2.savebuf, sizeof(expected)) == 0);
ok(nl2.savebufLen == sizeof(expected));
}
void testApplicationLayer()
{
TestPort port1;
TestPort port2;
TestApplicationLayer al1;
TestApplicationLayer al2;
port1.peer = &port2;
port2.peer = &port1;
pl1.setPort(&port1);
pl2.setPort(&port2);
pl1.setDataLayer(&dl1);
pl2.setDataLayer(&dl2);
dl1.setPhysicalLayer(&pl1);
dl2.setPhysicalLayer(&pl2);
dl1.setNetworkLayer(&nl1);
dl2.setNetworkLayer(&nl2);
nl1.setDataLayer(&dl1);
nl2.setDataLayer(&dl2);
al1.setNetworkLayer(&nl1);
al2.setNetworkLayer(&nl2);
al1.power_on();
al2.power_on();
Map27Address address;
address.setPrefix(7);
address.setIdent(5996);
uint32_t i;
uint8_t count = 0;
while (al2.numPackets < 10)
{
al1.poll();
al2.poll();
if (nl1.is_idle())
{
nl1.sendStatus(address, count++);
}
}
ok(al2.numPackets == 10);
ok(al2.savedata == 10);
al2.numPackets = 0;
uint32_t test_data = 0;
while (al2.numPackets < 10)
{
al1.poll();
al2.poll();
if (nl1.is_idle())
{
nl1.sendSST(address, (uint8_t*)&test_data, sizeof(test_data));
test_data++;
}
}
ok(al2.numPackets == 10);
uint32_t expected_data = 9;
ok(memcmp((uint8_t*)&expected_data , al2.savebuf, sizeof(test_data)) == 0);
ok(al2.savebufLen == sizeof(test_data));
}
int main(int argc, char** argv)
{
#if 1
testTimer();
testFcs();
testAddress();
testPhysical();
testDataLayer();
testNetworkLayer();
#endif
testApplicationLayer();
return 0;
}