Files
STM32F4-Base/IEC60870-Slave/test/iec104_asdu_transport_test.c
T
STF 4c55544f05
CI / L0 静态门禁 (pre-commit) (push) Failing after 45s
CI / L0.5 主机侧单测 (MSVC) (push) Failing after 42s
通信协议代码
2026-10-26 08:31:48 -04:00

126 lines
6.0 KiB
C

/* 公共ASDU与104传输的集成回归:独立测试中的字节向量仍用于期望值。
* 公共套件单独构建时不链接104实现;本文件专门检查I帧接入边界。 */
#define main common_asdu_suite_main
#include "iec60870_asdu_test.c"
#undef main
#include "IEC104_Codec.h"
/**
* 功能:验证公共对象构造的ASDU可按标准104布局封装并交付给公共解析器。
* 输入参数:无。
* 输出参数:无。
* 返回值:全部检查成功返回1,断言失败返回0。
* 说明:复用30种类型的独立载荷向量,覆盖42种类型/SQ组合及真实I帧序号。
*/
static int test_common_asdu_in_iframe(void)
{
const IEC60870_AppLayerParameters_t parameters = IEC104_APP_LAYER_PARAMETERS_DEFAULT;
static const uint8_t addresses[2][3] = {{0x56, 0x34, 0x12}, {0x57, 0x34, 0x12}};
size_t v;
unsigned int layouts = 0;
CHECK(parameters.sizeOfTypeId == 1 && parameters.sizeOfVSQ == 1);
CHECK(parameters.sizeOfCOT == 2 && parameters.sizeOfCA == 2 && parameters.sizeOfIOA == 3);
CHECK(parameters.originatorAddress == 0 && parameters.maxSizeOfASDU == 249);
for (v = 0; v < COUNT(vectors); ++v) {
const Vector *vector = &vectors[v];
int sq;
for (sq = 0; sq <= (vector->command ? 0 : 1); ++sq) {
uint8_t frame[64], expected[64], apdu[IEC104_MAX_APDU_LEN];
IEC60870_AsduHeader_t header = Header();
IEC60870_Asdu_t asdu;
IEC60870_AsduInfo_t info;
IEC104_ApciInfo_t apci;
TestObject input, output;
const uint8_t *data = NULL;
uint16_t length = 0, n;
int i, count = vector->command ? 1 : 2;
header.cause_of_transmission = vector->command ? 6 : 3;
header.is_negative_confirm = vector->command;
n = Wire_Header(&parameters, vector->type, (uint8_t)(count | (sq << 7)),
vector->command ? 0xC6 : 0x83, expected);
CHECK(IEC60870_Asdu_Create(&asdu, &parameters, frame, sizeof(frame), &header, sq) == IEC60870_ASDU_OK);
for (i = 0; i < count; ++i) {
CHECK(Sample_Object(vector->type, 0x123456U + (uint32_t)i, &input) == IEC60870_ASDU_OK);
CHECK(IEC60870_Asdu_Add_InformationObject(&asdu, Object_Base(&input, vector->type)) == IEC60870_ASDU_OK);
if (!sq || i == 0) {
memcpy(expected + n, addresses[i], 3);
n += 3;
}
memcpy(expected + n, vector->payload, vector->size);
n += vector->size;
}
CHECK(IEC60870_Asdu_Get_Data(&asdu, &data, &length) == IEC60870_ASDU_OK);
CHECK(length == n && memcmp(data, expected, n) == 0);
CHECK(IEC104_Build_Iframe(apdu, 0x1234, 0x2345, data, length) == length + IEC104_APCI_LEN);
CHECK(apdu[0] == 0x68 && apdu[1] == length + 4);
CHECK(apdu[2] == 0x68 && apdu[3] == 0x24 && apdu[4] == 0x8A && apdu[5] == 0x46);
CHECK(IEC104_Parse_APCI(apdu, (uint16_t)(length + IEC104_APCI_LEN), &apci));
CHECK(apci.frame_type == IEC104_FRAME_TYPE_I && apci.send_number == 0x1234 && apci.receive_number == 0x2345);
CHECK(apci.asdu_len == length && memcmp(apci.asdu, expected, n) == 0);
CHECK(IEC60870_Asdu_Parse(&parameters, apci.asdu, apci.asdu_len, &info) == IEC60870_ASDU_OK);
for (i = 0; i < count; ++i) {
CHECK(IEC60870_Asdu_Get_Element(&info, (uint8_t)i, &output, Object_Size(vector->type)) == IEC60870_ASDU_OK);
CHECK(Object_Base(&output, vector->type)->ioa == 0x123456U + (uint32_t)i);
CHECK(Check_Object(vector, &output));
}
++layouts;
}
}
CHECK(layouts == 42);
return 1;
}
/**
* 功能:验证公共ASDU容量与104帧容量分别生效。
* 输入参数:无。
* 输出参数:无。
* 返回值:全部检查成功返回1,断言失败返回0。
* 说明:公共层可构造254字节,104仍只接受至249字节;拒绝时输出保持不变。
*/
static int test_transport_length_boundary(void)
{
IEC60870_AppLayerParameters_t parameters = IEC104_APP_LAYER_PARAMETERS_DEFAULT;
IEC60870_AsduHeader_t header = Header();
IEC60870_Asdu_t asdu;
IEC60870_AsduInfo_t info;
IEC60870_MeasuredValueNormalized_t value;
IEC104_ApciInfo_t apci;
uint8_t frame[IEC60870_MAX_ASDU_LEN], apdu[260], before[260];
unsigned int i;
CHECK(IEC60870_MeasuredValueNormalized_Create(&value, 0, -1, 0) == IEC60870_ASDU_OK);
CHECK(IEC60870_Asdu_Create(&asdu, &parameters, frame, sizeof(frame), &header, 1) == IEC60870_ASDU_OK);
for (i = 0; i < 80; ++i) {
value.object.ioa = i;
CHECK(IEC60870_Asdu_Add_InformationObject(&asdu, &value.object) == IEC60870_ASDU_OK);
}
CHECK(asdu.length == 249);
CHECK(IEC104_Build_Iframe(apdu, 0, 0, frame, asdu.length) == 255);
CHECK(IEC104_Parse_APCI(apdu, 255, &apci));
CHECK(apci.asdu_len == 249 && memcmp(apci.asdu, frame, 249) == 0);
parameters.sizeOfCOT = 1; parameters.sizeOfCA = 1;
parameters.sizeOfIOA = 2; parameters.maxSizeOfASDU = 254;
header.common_address = 0x67;
CHECK(IEC60870_Asdu_Create(&asdu, &parameters, frame, sizeof(frame), &header, 0) == IEC60870_ASDU_OK);
for (i = 0; i < 50; ++i) {
value.object.ioa = i;
CHECK(IEC60870_Asdu_Add_InformationObject(&asdu, &value.object) == IEC60870_ASDU_OK);
}
CHECK(asdu.length == 254);
CHECK(IEC60870_Asdu_Parse(&parameters, frame, asdu.length, &info) == IEC60870_ASDU_OK);
memset(apdu, 0xA5, sizeof(apdu));
memcpy(before, apdu, sizeof(before));
CHECK(IEC104_Build_Iframe(apdu, 0, 0, frame, 250) == -1);
CHECK(memcmp(before, apdu, sizeof(apdu)) == 0);
CHECK(IEC104_Build_Iframe(apdu, 0, 0, frame, 254) == -1);
CHECK(memcmp(before, apdu, sizeof(apdu)) == 0);
return 1;
}
int main(void)
{
if (!test_common_asdu_in_iframe() || !test_transport_length_boundary()) { return 1; }
puts("104 ASDU transport: 2 groups passed (42 layouts, 249/254-byte boundary)");
return 0;
}