From 800d72de573852bf659da7356d5f0392dbc76e15 Mon Sep 17 00:00:00 2001 From: lixianjing Date: Tue, 15 Oct 2019 14:11:15 +0800 Subject: [PATCH] add stream noisy --- src/streams/SConscript | 37 +++++----- src/streams/noisy/iostream_noisy.c | 73 +++++++++++++++++++ src/streams/noisy/iostream_noisy.h | 68 ++++++++++++++++++ src/streams/noisy/ostream_noisy.c | 108 +++++++++++++++++++++++++++++ src/streams/noisy/ostream_noisy.h | 85 +++++++++++++++++++++++ src/streams/noisy/s | 4 ++ tests/iostream_noisy_test.cc | 25 +++++++ 7 files changed, 382 insertions(+), 18 deletions(-) create mode 100644 src/streams/noisy/iostream_noisy.c create mode 100644 src/streams/noisy/iostream_noisy.h create mode 100644 src/streams/noisy/ostream_noisy.c create mode 100644 src/streams/noisy/ostream_noisy.h create mode 100644 src/streams/noisy/s create mode 100644 tests/iostream_noisy_test.cc diff --git a/src/streams/SConscript b/src/streams/SConscript index 967c1ae40..ec2cf77bf 100644 --- a/src/streams/SConscript +++ b/src/streams/SConscript @@ -1,18 +1,19 @@ -import os -import copy - -BIN_DIR=os.environ['BIN_DIR']; -LIB_DIR=os.environ['LIB_DIR']; - -sources = Glob('buffered/*.c') + Glob('file/*.c') + Glob('inet/*.c') + Glob('mem/*.c') + Glob('serial/*.c') + Glob('shdlc/*.c') - -env=DefaultEnvironment().Clone() - -env.Library(os.path.join(LIB_DIR, 'streams'), sources, LIBS=[]) - -LIBS=['streams'] + env['LIBS'] -env.Program(os.path.join(BIN_DIR, 'udp_send'), ['tools/udp_send.c'], LIBS=LIBS); -env.Program(os.path.join(BIN_DIR, 'udp_recv'), ['tools/udp_recv.c'], LIBS=LIBS); -env.Program(os.path.join(BIN_DIR, 'serial_echo'), ['tools/serial_echo.c'], LIBS=LIBS); -env.Program(os.path.join(BIN_DIR, 'serial_send'), ['tools/serial_send.c'], LIBS=LIBS); -env.Program(os.path.join(BIN_DIR, 'serial_at'), ['tools/serial_at.c'], LIBS=LIBS); +import os +import copy + +BIN_DIR=os.environ['BIN_DIR']; +LIB_DIR=os.environ['LIB_DIR']; + +sources = Glob('buffered/*.c') + Glob('file/*.c') + Glob('inet/*.c') + Glob('mem/*.c') + Glob('serial/*.c') \ + + Glob('shdlc/*.c') + Glob('noisy/*.c') + +env=DefaultEnvironment().Clone() + +env.Library(os.path.join(LIB_DIR, 'streams'), sources, LIBS=[]) + +LIBS=['streams'] + env['LIBS'] +env.Program(os.path.join(BIN_DIR, 'udp_send'), ['tools/udp_send.c'], LIBS=LIBS); +env.Program(os.path.join(BIN_DIR, 'udp_recv'), ['tools/udp_recv.c'], LIBS=LIBS); +env.Program(os.path.join(BIN_DIR, 'serial_echo'), ['tools/serial_echo.c'], LIBS=LIBS); +env.Program(os.path.join(BIN_DIR, 'serial_send'), ['tools/serial_send.c'], LIBS=LIBS); +env.Program(os.path.join(BIN_DIR, 'serial_at'), ['tools/serial_at.c'], LIBS=LIBS); diff --git a/src/streams/noisy/iostream_noisy.c b/src/streams/noisy/iostream_noisy.c new file mode 100644 index 000000000..368b066ce --- /dev/null +++ b/src/streams/noisy/iostream_noisy.c @@ -0,0 +1,73 @@ +/** + * File: iostream_noisy.c + * Author: AWTK Develop Team + * Brief: inject error into stream + * + * Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * License file for more details. + * + */ + +/** + * History: + * ================================================================ + * 2019-10-15 Li XianJing created + * + */ + +#include "tkc/mem.h" +#include "streams/noisy/iostream_noisy.h" + +static ret_t tk_iostream_noisy_on_destroy(object_t* obj) { + tk_iostream_noisy_t* iostream_noisy = TK_IOSTREAM_NOISY(obj); + + OBJECT_UNREF(iostream_noisy->istream); + OBJECT_UNREF(iostream_noisy->real_iostream); + + return RET_OK; +} + +static const object_vtable_t s_tk_iostream_noisy_vtable = { + .type = "tk_iostream_noisy", + .desc = "tk_iostream_noisy", + .size = sizeof(tk_iostream_noisy_t), + .on_destroy = tk_iostream_noisy_on_destroy}; + +static tk_istream_t* tk_iostream_noisy_get_istream(tk_iostream_t* stream) { + tk_iostream_noisy_t* iostream_noisy = TK_IOSTREAM_NOISY(stream); + + return iostream_noisy->istream; +} + +static tk_ostream_t* tk_iostream_noisy_get_ostream(tk_iostream_t* stream) { + tk_iostream_noisy_t* iostream_noisy = TK_IOSTREAM_NOISY(stream); + + return iostream_noisy->ostream; +} + +tk_iostream_t* tk_iostream_noisy_create(tk_iostream_t* real_iostream) { + object_t* obj = NULL; + tk_ostream_t* real_ostream = NULL; + tk_iostream_noisy_t* iostream_noisy = NULL; + return_value_if_fail(real_iostream != NULL, NULL); + real_ostream = tk_iostream_get_ostream(real_iostream); + return_value_if_fail(real_ostream != NULL, NULL); + + obj = object_create(&s_tk_iostream_noisy_vtable); + iostream_noisy = TK_IOSTREAM_NOISY(obj); + return_value_if_fail(iostream_noisy != NULL, NULL); + + iostream_noisy->real_iostream = TK_IOSTREAM(object_ref(OBJECT(real_iostream))); + + iostream_noisy->istream = tk_iostream_get_istream(real_iostream); + iostream_noisy->ostream = tk_ostream_noisy_create(real_ostream); + + TK_IOSTREAM(obj)->get_istream = tk_iostream_noisy_get_istream; + TK_IOSTREAM(obj)->get_ostream = tk_iostream_noisy_get_ostream; + + return TK_IOSTREAM(obj); +} diff --git a/src/streams/noisy/iostream_noisy.h b/src/streams/noisy/iostream_noisy.h new file mode 100644 index 000000000..de6c867f1 --- /dev/null +++ b/src/streams/noisy/iostream_noisy.h @@ -0,0 +1,68 @@ +/** + * File: iostream_noisy.h + * Author: AWTK Develop Team + * Brief: inject error into stream + * + * Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * License file for more details. + * + */ + +/** + * History: + * ================================================================ + * 2019-10-15 Li XianJing created + * + */ + +#ifndef TK_IOSTREAM_NOISY_H +#define TK_IOSTREAM_NOISY_H + +#include "tkc/fs.h" +#include "tkc/iostream.h" +#include "streams/noisy/ostream_noisy.h" + +BEGIN_C_DECLS + +struct _tk_iostream_noisy_t; +typedef struct _tk_iostream_noisy_t tk_iostream_noisy_t; + +/** + * @class tk_iostream_noisy_t + * @parent tk_iostream_t + * + * 在输出流中注入错误,方便进行可靠性测试。 + * + */ +struct _tk_iostream_noisy_t { + tk_iostream_t iostream; + + tk_ostream_t* ostream; + tk_istream_t* istream; + + tk_iostream_t* real_iostream; +}; + +/** + * @method tk_iostream_noisy_create + * + * 创建iostream对象。 + * + * 本函数自动增加real_iostream的引用计数。 + * + * @param {tk_iostream_t*} real_iostream 底层的iostream。 + * + * @return {tk_iostream_t*} 返回iostream对象。 + * + */ +tk_iostream_t* tk_iostream_noisy_create(tk_iostream_t* real_iostream); + +#define TK_IOSTREAM_NOISY(obj) ((tk_iostream_noisy_t*)(obj)) + +END_C_DECLS + +#endif /*TK_IOSTREAM_NOISY_H*/ diff --git a/src/streams/noisy/ostream_noisy.c b/src/streams/noisy/ostream_noisy.c new file mode 100644 index 000000000..14fb3c401 --- /dev/null +++ b/src/streams/noisy/ostream_noisy.c @@ -0,0 +1,108 @@ +/** + * File: ostream_noisy.c + * Author: AWTK Develop Team + * Brief: output stream for noisy + * + * Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * License file for more details. + * + */ + +/** + * History: + * ================================================================ + * 2019-10-15 Li XianJing created + * + */ + +#include "tkc/mem.h" +#include "streams/noisy/ostream_noisy.h" + +static int32_t tk_ostream_noisy_write(tk_ostream_t* stream, const uint8_t* buff, uint32_t size) { + tk_ostream_noisy_t* ostream_noisy = TK_OSTREAM_NOISY(stream); + + ostream_noisy->write_count++; + + if(ostream_noisy->error_level && size > 0) { + if(((ostream_noisy->error_count * 10)/ostream_noisy->write_count) < ostream_noisy->error_level) { + uint32_t i = random()/size; + wbuffer_t* wb = &(ostream_noisy->wb); + wb->cursor = 0; + wbuffer_write_binary(wb, buff, size); + + wb->data[i] = ~buff[i]; + ostream_noisy->error_count++; + return tk_ostream_write(ostream_noisy->real_ostream, wb->data, size); + } + } + + return tk_ostream_write(ostream_noisy->real_ostream, buff, size); +} + +static ret_t tk_ostream_noisy_set_prop(object_t* obj, const char* name, const value_t* v) { + tk_ostream_noisy_t* ostream_noisy = TK_OSTREAM_NOISY(obj); + tk_ostream_t* real_ostream = ostream_noisy->real_ostream; + + if (tk_str_eq(name, TK_OSTREAM_NOISY_PROP_ERROR_LEVEL)) { + ostream_noisy->error_level = value_uint32(v); + return RET_OK; + } else if (tk_str_eq(name, TK_OSTREAM_NOISY_PROP_ERROR_COUNT)) { + ostream_noisy->error_count = value_uint32(v); + return RET_OK; + } else if (tk_str_eq(name, TK_OSTREAM_NOISY_PROP_WRITE_COUNT)) { + ostream_noisy->write_count = value_uint32(v); + return RET_OK; + } + + return object_set_prop(OBJECT(real_ostream), name, v); +} + +static ret_t tk_ostream_noisy_get_prop(object_t* obj, const char* name, value_t* v) { + tk_ostream_noisy_t* ostream_noisy = TK_OSTREAM_NOISY(obj); + tk_ostream_t* real_ostream = ostream_noisy->real_ostream; + + if (tk_str_eq(name, TK_OSTREAM_NOISY_PROP_ERROR_LEVEL)) { + value_set_uint32(v, ostream_noisy->error_level); + return RET_OK; + } else if (tk_str_eq(name, TK_OSTREAM_NOISY_PROP_ERROR_COUNT)) { + value_set_uint32(v, ostream_noisy->error_count); + return RET_OK; + } else if (tk_str_eq(name, TK_OSTREAM_NOISY_PROP_WRITE_COUNT)) { + value_set_uint32(v, ostream_noisy->write_count); + return RET_OK; + } + + return object_get_prop(OBJECT(real_ostream), name, v); +} + +static ret_t tk_ostream_noisy_on_destroy(object_t* obj) { + return RET_OK; +} + +static const object_vtable_t s_tk_ostream_noisy_vtable = {.type = "tk_ostream_noisy", + .desc = "tk_ostream_noisy", + .size = sizeof(tk_ostream_noisy_t), + .on_destroy = tk_ostream_noisy_on_destroy, + .get_prop = tk_ostream_noisy_get_prop, + .set_prop = tk_ostream_noisy_set_prop}; + +tk_ostream_t* tk_ostream_noisy_create(tk_ostream_t* real_ostream) { + object_t* obj = NULL; + tk_ostream_noisy_t* ostream_noisy = NULL; + return_value_if_fail(real_ostream != NULL, NULL); + + obj = object_create(&s_tk_ostream_noisy_vtable); + ostream_noisy = TK_OSTREAM_NOISY(obj); + return_value_if_fail(ostream_noisy != NULL, NULL); + + ostream_noisy->error_level = 1; + ostream_noisy->real_ostream = real_ostream; + wbuffer_init_extendable(&(ostream_noisy->wb)); + TK_OSTREAM(obj)->write = tk_ostream_noisy_write; + + return TK_OSTREAM(obj); +} diff --git a/src/streams/noisy/ostream_noisy.h b/src/streams/noisy/ostream_noisy.h new file mode 100644 index 000000000..d8a132b9e --- /dev/null +++ b/src/streams/noisy/ostream_noisy.h @@ -0,0 +1,85 @@ +/** + * File: ostream_noisy.h + * Author: AWTK Develop Team + * Brief: inject error into stream + * + * Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * License file for more details. + * + */ + +/** + * History: + * ================================================================ + * 2019-10-15 Li XianJing created + * + */ + +#ifndef TK_OSTREAM_NOISY_H +#define TK_OSTREAM_NOISY_H + +#include "tkc/buffer.h" +#include "tkc/ostream.h" + +BEGIN_C_DECLS + +struct _tk_ostream_noisy_t; +typedef struct _tk_ostream_noisy_t tk_ostream_noisy_t; + +/** + * @class tk_ostream_noisy_t + * @parent tk_ostream_t + * + * 在输出流中注入错误,方便进行可靠性测试。 + * + */ +struct _tk_ostream_noisy_t { + tk_ostream_t ostream; + + /** + * @property {uint32_t} error_level + * 错误等级。0-9。0:无错,9:全错。 + */ + uint32_t error_level; + /** + * @property {uint32_t} error_count + * 注入的错误数。 + */ + uint32_t error_count; + /** + * @property {uint32_t} write_count + * 写入的次数。 + */ + uint32_t write_count; + + wbuffer_t wb; + tk_ostream_t* real_ostream; +}; + +/** + * @method tk_ostream_noisy_create + * + * 创建ostream对象。 + * + *> 只能由iostream_noisy调用。 + * + * @param {tk_ostream_t*} real_ostream 实际的ostream对象。 + * + * @return {tk_ostream_t*} 返回ostream对象。 + * + */ +tk_ostream_t* tk_ostream_noisy_create(tk_ostream_t* real_ostream); + +#define TK_OSTREAM_NOISY_PROP_ERROR_LEVEL "error_level" +#define TK_OSTREAM_NOISY_PROP_ERROR_COUNT "error_count" +#define TK_OSTREAM_NOISY_PROP_WRITE_COUNT "write_count" + +#define TK_OSTREAM_NOISY(obj) ((tk_ostream_noisy_t*)(obj)) + +END_C_DECLS + +#endif /*TK_OSTREAM_NOISY_H*/ diff --git a/src/streams/noisy/s b/src/streams/noisy/s new file mode 100644 index 000000000..0954dd97b --- /dev/null +++ b/src/streams/noisy/s @@ -0,0 +1,4 @@ +:%s/shdlc/noisy/g +:%s/SHDLC/NOISY/g +:wq + diff --git a/tests/iostream_noisy_test.cc b/tests/iostream_noisy_test.cc new file mode 100644 index 000000000..dcf5713f5 --- /dev/null +++ b/tests/iostream_noisy_test.cc @@ -0,0 +1,25 @@ +#include "gtest/gtest.h" + +#include "streams/mem/iostream_mem.h" +#include "streams/noisy/ostream_noisy.h" +#include "streams/noisy/iostream_noisy.h" + +TEST(IOStreamNoisy, basic) { + uint8_t buff[62]; + uint8_t rbuff[16]; + const char* str = "12345"; + uint32_t size = strlen(str) + 1; + tk_iostream_t* mem = tk_iostream_mem_create(buff, sizeof(buff), buff, sizeof(buff), FALSE); + tk_iostream_t* io = tk_iostream_noisy_create(mem); + tk_ostream_t* os = tk_iostream_get_ostream(io); + tk_istream_t* is = tk_iostream_get_istream(io); + + object_set_prop_int(OBJECT(os), TK_OSTREAM_NOISY_PROP_ERROR_LEVEL, 0); + ASSERT_EQ(tk_ostream_write(os, (uint8_t*)str, size), size); + ASSERT_EQ(tk_istream_read(is, rbuff, sizeof(rbuff)), size); + ASSERT_STREQ((char*)rbuff, str); + + OBJECT_UNREF(io); + OBJECT_UNREF(mem); +} +