*
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
tup.include('../tupfiles/build.lua')
|
||||
tup.include('../cpp/package.lua')
|
||||
|
||||
test_server = define_package{
|
||||
packages={fibre_package},
|
||||
sources={'test_server.cpp'}
|
||||
}
|
||||
|
||||
unit_tests = define_package{
|
||||
packages={fibre_package},
|
||||
sources={'run_tests.cpp'}
|
||||
}
|
||||
|
||||
|
||||
toolchain=GCCToolchain('', 'build', {'-O3', '-fvisibility=hidden', '-frename-registers', '-funroll-loops'}, {})
|
||||
toolchain=GCCToolchain('', 'build', {'-O3', '-g', '-Wall'}, {})
|
||||
--toolchain=GCCToolchain('avr-', {'-Ofast', '-fvisibility=hidden', '-frename-registers', '-funroll-loops', '-I/home/samuel/stlport-avr/stlport'}, {})
|
||||
--toolchain=LLVMToolchain('x86_64', {'-O3', '-fno-sanitize=safe-stack', '-fno-stack-protector'}, {'-flto', '-Wl,-s'})
|
||||
--toolchain=LLVMToolchain('avr', {'-O3', '-std=gnu++11', '--target=avr', '-fno-sanitize=safe-stack', '-fno-stack-protector', '-I/home/samuel/stlport-avr/stlport'}, {'-flto', '-Wl,-s'})
|
||||
|
||||
|
||||
if tup.getconfig("BUILD_FIBRE_TESTS") == "true" then
|
||||
build_executable('test_server', test_server, toolchain)
|
||||
--build_executable('run_tests', unit_tests, toolchain)
|
||||
end
|
||||
@@ -0,0 +1,140 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//#define DEBUG_PROTOCOL
|
||||
void hexdump(const uint8_t* buf, size_t len);
|
||||
|
||||
#include <fibre/crc.hpp>
|
||||
#include <fibre/decoders.hpp>
|
||||
#include <fibre/encoders.hpp>
|
||||
|
||||
void hexdump(const uint8_t* buf, size_t len) {
|
||||
for (size_t pos = 0; pos < len; ++pos) {
|
||||
printf(" %02x", buf[pos]);
|
||||
if ((((pos + 1) % 16) == 0) || ((pos + 1) == len))
|
||||
printf("\r\n");
|
||||
//osDelay(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool varint_decoder_test() {
|
||||
struct test_case_t {
|
||||
uint8_t encoded[10];
|
||||
size_t length;
|
||||
uint32_t decoded;
|
||||
};
|
||||
const test_case_t test_cases[] = {
|
||||
// encoded, length, decoded
|
||||
{ { 0x00 }, 1, 0 },
|
||||
{ { 0x01 }, 1, 1 },
|
||||
{ { 0xff, 0x01 }, 2, 0xff },
|
||||
{ { 0xAC, 0x02 }, 2, 300 },
|
||||
{ { 0xff, 0xff, 0xff, 0xff, 0xf }, 5, 0xffffffff }
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); ++i) {
|
||||
uint32_t result;
|
||||
VarintStreamDecoder<uint32_t> decoder = make_varint_decoder(result);
|
||||
size_t processed_bytes = 0;
|
||||
int status = decoder.process_bytes(test_cases[i].encoded, test_cases[i].length, &processed_bytes);
|
||||
if (status) {
|
||||
return false;
|
||||
} else if (processed_bytes != test_cases[i].length) {
|
||||
printf("test %zu: expected to process %zu bytes but processed %zu bytes\n", i, test_cases[i].length, processed_bytes);
|
||||
return false;
|
||||
} else if (result != test_cases[i].decoded) {
|
||||
printf("test %zu: expected %u but got %u\n", i, test_cases[i].decoded, result);
|
||||
return false;
|
||||
}
|
||||
|
||||
VarintStreamEncoder<uint32_t> encoder = make_varint_encoder(test_cases[i].decoded);
|
||||
uint8_t buffer[10];
|
||||
size_t generated_bytes = 0;
|
||||
status = encoder.get_bytes(buffer, sizeof(buffer), &generated_bytes);
|
||||
if (status) {
|
||||
return false;
|
||||
} else if ((generated_bytes != test_cases[i].length)
|
||||
|| memcmp(buffer, test_cases[i].encoded, test_cases[i].length)) {
|
||||
printf("test %zu: expected:", i);
|
||||
hexdump(test_cases[i].encoded, test_cases[i].length);
|
||||
printf("got: ");
|
||||
hexdump(buffer, generated_bytes);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(void) {
|
||||
/***** Decoder demo (remove or move somewhere else) *****/
|
||||
printf("Running decoder... ");
|
||||
// prepare raw data
|
||||
uint8_t raw_data[] = { 0xBC, 0x03, 0xAC, 0x5e, 0x02, 0x00, 0x00, 0xd1 };
|
||||
//raw_data[3] = calc_crc8<CANONICAL_CRC8_POLYNOMIAL>(CANONICAL_CRC8_INIT, raw_data, 3);
|
||||
//raw_data[7] = calc_crc8<CANONICAL_CRC8_POLYNOMIAL>(raw_data[3], raw_data + 4, 3);
|
||||
|
||||
// instantiate decoder
|
||||
ReceiverState state;
|
||||
auto decoder = make_crc8_decoder<CANONICAL_CRC8_INIT, CANONICAL_CRC8_POLYNOMIAL>(
|
||||
make_decoder_chain(
|
||||
make_length_decoder(state),
|
||||
make_endpoint_id_decoder(state)
|
||||
)
|
||||
);
|
||||
|
||||
// push the raw data through the decoder
|
||||
size_t processed_bytes = 0;
|
||||
int status = decoder.process_bytes(raw_data, sizeof(raw_data), &processed_bytes);
|
||||
|
||||
// expected result: "length: 444, endpoint-id: 300, processed 8 bytes"
|
||||
if (status == 0)
|
||||
printf("length: %zu, endpoint-id: %zu, processed %zu bytes\n", state.length, state.endpoint_id, processed_bytes);
|
||||
else
|
||||
printf("decoder demo failed\n");
|
||||
|
||||
|
||||
/***** Encoder demo (remove or move somewhere else) *****/
|
||||
printf("Running encoder... ");
|
||||
// prepare request
|
||||
Request request = {
|
||||
.endpoint_id = 300,
|
||||
.length = 444,
|
||||
};
|
||||
|
||||
// construct encoder for the request
|
||||
auto e2 = make_crc8_encoder<CANONICAL_CRC8_INIT, CANONICAL_CRC8_POLYNOMIAL>(
|
||||
make_encoder_chain(
|
||||
make_length_encoder(request),
|
||||
make_endpoint_id_encoder(request)
|
||||
)
|
||||
);
|
||||
|
||||
// pull raw data out of the encoder
|
||||
uint8_t buffer[20];
|
||||
size_t generated_bytes = 0;
|
||||
status = e2.get_bytes(buffer, sizeof(buffer), &generated_bytes);
|
||||
if (status == 0) {
|
||||
printf("generated %zu bytes:\n", generated_bytes);
|
||||
hexdump(buffer, generated_bytes);
|
||||
} else {
|
||||
printf("encoder demo failed\n");
|
||||
}
|
||||
|
||||
|
||||
/***** run automated test *****/
|
||||
bool test_result = varint_decoder_test();
|
||||
if (test_result) {
|
||||
printf("all tests passed\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("some tests failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
#include <signal.h>
|
||||
|
||||
#include <fibre/protocol.hpp>
|
||||
#include <fibre/posix_tcp.hpp>
|
||||
#include <fibre/posix_udp.hpp>
|
||||
|
||||
|
||||
class TestClass {
|
||||
public:
|
||||
float property1;
|
||||
float property2;
|
||||
|
||||
float set_both(float arg1, float arg2) {
|
||||
property1 = arg1;
|
||||
property2 = arg2;
|
||||
return property1 + property2;
|
||||
}
|
||||
|
||||
FIBRE_EXPORTS(TestClass,
|
||||
make_protocol_property("property1", &property1),
|
||||
make_protocol_property("property2", &property2),
|
||||
make_protocol_function("set_both", *obj, &TestClass::set_both, "arg1", "arg2")
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
printf("Starting Fibre server...\n");
|
||||
|
||||
TestClass test_object = TestClass();
|
||||
|
||||
// publish the object on Fibre
|
||||
auto definitions = test_object.fibre_definitions;
|
||||
fibre_publish(definitions);
|
||||
|
||||
// Expose Fibre objects on TCP and UDP
|
||||
std::thread server_thread_tcp(serve_on_tcp, 9910);
|
||||
std::thread server_thread_udp(serve_on_udp, 9910);
|
||||
printf("Fibre server started.\n");
|
||||
|
||||
// Dump property1 value
|
||||
while (1) {
|
||||
printf("test_object.property1: %f\n", test_object.property1);
|
||||
usleep(1000000 / 5); // 5 Hz
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user