it2s-itss-ldm/tests/test_filter.c

316 lines
16 KiB
C

#include <filter.h>
#include <it2s-asn/etsi-its-v2/cam/EI2_CAM.h>
#include <it2s-asn/etsi-its-v2/cpm/EI2_CollectivePerceptionMessage.h>
#include <stdint.h>
#include <stdlib.h>
#include <unity.h>
void setUp(void) {
// set stuff up here
}
void tearDown(void) {
// clean stuff up here
}
void test_ldm_filter_new(void) {
int ret;
uint64_t ref_val = 1000;
EI2_CollectivePerceptionMessage_t* cpm = calloc(1, sizeof(*cpm));
asn_uint642INTEGER(&cpm->payload.managementContainer.referenceTime, ref_val);
ldm_filter_t* filter = NULL;
// Invalid filter
EI2_Filter_t* asn_filter = calloc(1, sizeof(*asn_filter));
asn_filter->present = EI2_Filter_PR_NOTHING;
filter = ldm_filter_new(asn_filter, ldm_data_type_CPM);
TEST_ASSERT_MESSAGE(filter == NULL, "New filter should return NULL when type is NOTHING");
ret = ldm_filter_check(filter, cpm);
TEST_ASSERT_MESSAGE(ret == 1, "Filter check should return 1 when filter is NULL");
// Simple filter with only a statement
asn_filter->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter->choice.filterStatement.attribute, "referenceTime", -1);
asn_filter->choice.filterStatement.Operator = EI2_ComparisonOperators_equal;
asn_filter->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_octsValue;
OCTET_STRING_fromBuf(&asn_filter->choice.filterStatement.refValue.choice.octsValue, (char*)&ref_val, sizeof(uint64_t));
// asn_fprint(stdout, &asn_DEF_EI2_Filter, asn_filter);
// filter: referenceTime = 1000
filter = ldm_filter_new(asn_filter, ldm_data_type_CPM);
TEST_ASSERT_MESSAGE(filter != NULL, "New filter should not return NULL when type is CPM and filter is valid");
ret = ldm_filter_check(filter, cpm);
TEST_ASSERT_MESSAGE(ret == 1, "Filter check should return 1 when filter matches the data");
ASN_STRUCT_FREE(asn_DEF_EI2_Filter, asn_filter);
ldm_filter_release(filter);
// filter with two statements
EI2_Filter_t* asn_filter1 = calloc(1, sizeof(*asn_filter1));
asn_filter1->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter1->choice.filterStatement.attribute, "referenceTime", -1);
asn_filter1->choice.filterStatement.Operator = EI2_ComparisonOperators_gt;
asn_filter1->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_octsValue;
OCTET_STRING_fromBuf(&asn_filter1->choice.filterStatement.refValue.choice.octsValue, (char*)&ref_val, sizeof(uint64_t));
EI2_Filter_t* asn_filter2 = calloc(1, sizeof(*asn_filter2));
asn_filter2->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter2->choice.filterStatement.attribute, "referenceTime", -1);
asn_filter2->choice.filterStatement.Operator = EI2_ComparisonOperators_lt;
asn_filter2->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_octsValue;
OCTET_STRING_fromBuf(&asn_filter2->choice.filterStatement.refValue.choice.octsValue, (char*)&ref_val, sizeof(uint64_t));
asn_filter = calloc(1, sizeof(*asn_filter));
asn_filter->present = EI2_Filter_PR_filterExp;
asn_filter->choice.filterExp = calloc(1, sizeof(EI2_FilterExp_t));
asn_filter->choice.filterExp->logicalOperator = EI2_LogicalOperators_and;
asn_filter->choice.filterExp->filter1 = asn_filter1;
asn_filter->choice.filterExp->filter2 = asn_filter2;
// filter: (referenceTime > 1000) AND (referenceTime < 1000)
filter = ldm_filter_new(asn_filter, ldm_data_type_CPM);
TEST_ASSERT_MESSAGE(filter != NULL, "New filter should not return NULL when type is CPM and filter is valid");
ret = ldm_filter_check(filter, cpm);
TEST_ASSERT_MESSAGE(ret == 0, "Filter check should return 0 when filter does not match the data");
ASN_STRUCT_FREE(asn_DEF_EI2_Filter, asn_filter);
ldm_filter_release(filter);
// filter for an attribute that has no callback
asn_filter = calloc(1, sizeof(*asn_filter));
asn_filter->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter->choice.filterStatement.attribute, "unknownAttribute", -1);
asn_filter->choice.filterStatement.Operator = EI2_ComparisonOperators_equal;
asn_filter->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_intValue;
asn_filter->choice.filterStatement.refValue.choice.intValue = 1000;
filter = ldm_filter_new(asn_filter, ldm_data_type_CPM);
TEST_ASSERT_MESSAGE(filter == NULL, "New filter should return NULL when attribute has no callback");
ASN_STRUCT_FREE(asn_DEF_EI2_Filter, asn_filter);
// filter for a type that has no callback
asn_filter = calloc(1, sizeof(*asn_filter));
asn_filter->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter->choice.filterStatement.attribute, "referenceTime", -1);
asn_filter->choice.filterStatement.Operator = EI2_ComparisonOperators_equal;
asn_filter->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_intValue;
asn_filter->choice.filterStatement.refValue.choice.intValue = 1000;
filter = ldm_filter_new(asn_filter, ldm_data_type_CAM);
TEST_ASSERT_MESSAGE(filter == NULL, "New filter should return NULL when attribute has no callback");
ASN_STRUCT_FREE(asn_DEF_EI2_Filter, asn_filter);
// filter with two statements, but one is invalid, operator is &&
asn_filter1 = calloc(1, sizeof(*asn_filter1));
asn_filter1->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter1->choice.filterStatement.attribute, "referenceTime", -1);
asn_filter1->choice.filterStatement.Operator = EI2_ComparisonOperators_gt;
asn_filter1->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_octsValue;
OCTET_STRING_fromBuf(&asn_filter1->choice.filterStatement.refValue.choice.octsValue, (char*)&ref_val, sizeof(uint64_t));
asn_filter2 = calloc(1, sizeof(*asn_filter2));
asn_filter2->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter2->choice.filterStatement.attribute, "unknownAttribute", -1);
asn_filter2->choice.filterStatement.Operator = EI2_ComparisonOperators_lt;
asn_filter2->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_octsValue;
OCTET_STRING_fromBuf(&asn_filter2->choice.filterStatement.refValue.choice.octsValue, (char*)&ref_val, sizeof(uint64_t));
asn_filter = calloc(1, sizeof(*asn_filter));
asn_filter->present = EI2_Filter_PR_filterExp;
asn_filter->choice.filterExp = calloc(1, sizeof(EI2_FilterExp_t));
asn_filter->choice.filterExp->logicalOperator = EI2_LogicalOperators_and;
asn_filter->choice.filterExp->filter1 = asn_filter1;
asn_filter->choice.filterExp->filter2 = asn_filter2;
// filter: (referenceTime > 1000) AND (unknownAttribute < 1000)
filter = ldm_filter_new(asn_filter, ldm_data_type_CPM);
TEST_ASSERT_MESSAGE(
filter != NULL,
"New filter should not return NULL when type is CPM and filter expression is partially valid (one of the statements is invalid)");
ret = ldm_filter_check(filter, cpm);
TEST_ASSERT_MESSAGE(
ret == 0, "Filter check should return 0 when the non null part of the filter does not match the data (logical operator is &&)");
ASN_STRUCT_FREE(asn_DEF_EI2_Filter, asn_filter);
ldm_filter_release(filter);
// filter with two statements, but one is invalid
asn_filter1 = calloc(1, sizeof(*asn_filter1));
asn_filter1->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter1->choice.filterStatement.attribute, "referenceTime", -1);
asn_filter1->choice.filterStatement.Operator = EI2_ComparisonOperators_gt;
asn_filter1->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_octsValue;
OCTET_STRING_fromBuf(&asn_filter1->choice.filterStatement.refValue.choice.octsValue, (char*)&ref_val, sizeof(uint64_t));
asn_filter2 = calloc(1, sizeof(*asn_filter2));
asn_filter2->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter2->choice.filterStatement.attribute, "unknownAttribute", -1);
asn_filter2->choice.filterStatement.Operator = EI2_ComparisonOperators_lt;
asn_filter2->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_octsValue;
OCTET_STRING_fromBuf(&asn_filter2->choice.filterStatement.refValue.choice.octsValue, (char*)&ref_val, sizeof(uint64_t));
asn_filter = calloc(1, sizeof(*asn_filter));
asn_filter->present = EI2_Filter_PR_filterExp;
asn_filter->choice.filterExp = calloc(1, sizeof(EI2_FilterExp_t));
asn_filter->choice.filterExp->logicalOperator = EI2_LogicalOperators_or;
asn_filter->choice.filterExp->filter1 = asn_filter1;
asn_filter->choice.filterExp->filter2 = asn_filter2;
// filter: (referenceTime > 1000) AND (unknownAttribute < 1000)
filter = ldm_filter_new(asn_filter, ldm_data_type_CPM);
TEST_ASSERT_MESSAGE(
filter != NULL,
"New filter should not return NULL when type is CPM and filter expression is partially valid (one of the statements is invalid)");
ret = ldm_filter_check(filter, cpm);
TEST_ASSERT_MESSAGE(
ret == 1, "Filter check should return 1 when the non null part of the filter does not match the data (logical operator is ||)");
ASN_STRUCT_FREE(asn_DEF_EI2_Filter, asn_filter);
ldm_filter_release(filter);
ASN_STRUCT_FREE(asn_DEF_EI2_CollectivePerceptionMessage, cpm);
}
void test_ldm_filter_complex(void) {
int ret;
EI2_CAM_t* cam = calloc(1, sizeof(*cam));
// asn_random_fill(&asn_DEF_EI2_CAM, (void**)&cam, 1000);
cam->cam.camParameters.highFrequencyContainer.present = EI2_HighFrequencyContainer_PR_basicVehicleContainerHighFrequency;
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedValue = 20;
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedConfidence = 7;
ldm_filter_t* filter = NULL;
// filter: ((speed > 10) && ((speed < 100) || (speed == 123))) && (speed != 50)
// in all these check, (confidence < ref_confidence is also checked)
uint16_t ref_conf = 10;
// filter1: speed > 10
EI2_Filter_t* asn_filter1 = calloc(1, sizeof(*asn_filter1));
asn_filter1->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter1->choice.filterStatement.attribute, "speed", -1);
asn_filter1->choice.filterStatement.Operator = EI2_ComparisonOperators_gt;
asn_filter1->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_speedValue;
asn_filter1->choice.filterStatement.refValue.choice.speedValue.speedValue = 10;
asn_filter1->choice.filterStatement.refValue.choice.speedValue.speedConfidence = ref_conf;
// filter2: speed < 100
EI2_Filter_t* asn_filter2 = calloc(1, sizeof(*asn_filter2));
asn_filter2->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter2->choice.filterStatement.attribute, "speed", -1);
asn_filter2->choice.filterStatement.Operator = EI2_ComparisonOperators_lt;
asn_filter2->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_speedValue;
asn_filter2->choice.filterStatement.refValue.choice.speedValue.speedValue = 100;
asn_filter2->choice.filterStatement.refValue.choice.speedValue.speedConfidence = ref_conf;
// filter3: speed == 123
EI2_Filter_t* asn_filter3 = calloc(1, sizeof(*asn_filter3));
asn_filter3->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter3->choice.filterStatement.attribute, "speed", -1);
asn_filter3->choice.filterStatement.Operator = EI2_ComparisonOperators_equal;
asn_filter3->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_speedValue;
asn_filter3->choice.filterStatement.refValue.choice.speedValue.speedValue = 123;
asn_filter3->choice.filterStatement.refValue.choice.speedValue.speedConfidence = ref_conf;
// filter4: speed != 50
EI2_Filter_t* asn_filter4 = calloc(1, sizeof(*asn_filter4));
asn_filter4->present = EI2_Filter_PR_filterStatement;
OCTET_STRING_fromBuf(&asn_filter4->choice.filterStatement.attribute, "speed", -1);
asn_filter4->choice.filterStatement.Operator = EI2_ComparisonOperators_notequal;
asn_filter4->choice.filterStatement.refValue.present = EI2_ReferenceValue_PR_speedValue;
asn_filter4->choice.filterStatement.refValue.choice.speedValue.speedValue = 50;
asn_filter4->choice.filterStatement.refValue.choice.speedValue.speedConfidence = ref_conf;
// filter: (filter2 || filter3)
EI2_Filter_t* asn_filter5 = calloc(1, sizeof(*asn_filter5));
asn_filter5->present = EI2_Filter_PR_filterExp;
asn_filter5->choice.filterExp = calloc(1, sizeof(EI2_FilterExp_t));
asn_filter5->choice.filterExp->logicalOperator = EI2_LogicalOperators_or;
asn_filter5->choice.filterExp->filter1 = asn_filter2;
asn_filter5->choice.filterExp->filter2 = asn_filter3;
// filter: (filter1 && filter5)
EI2_Filter_t* asn_filter6 = calloc(1, sizeof(*asn_filter6));
asn_filter6->present = EI2_Filter_PR_filterExp;
asn_filter6->choice.filterExp = calloc(1, sizeof(EI2_FilterExp_t));
asn_filter6->choice.filterExp->logicalOperator = EI2_LogicalOperators_and;
asn_filter6->choice.filterExp->filter1 = asn_filter1;
asn_filter6->choice.filterExp->filter2 = asn_filter5;
// filter: (filter6 && filter4)
EI2_Filter_t* asn_filter = calloc(1, sizeof(*asn_filter));
asn_filter->present = EI2_Filter_PR_filterExp;
asn_filter->choice.filterExp = calloc(1, sizeof(EI2_FilterExp_t));
asn_filter->choice.filterExp->logicalOperator = EI2_LogicalOperators_and;
asn_filter->choice.filterExp->filter1 = asn_filter6;
asn_filter->choice.filterExp->filter2 = asn_filter4;
// asn_fprint(stdout, &asn_DEF_EI2_Filter, asn_filter);
filter = ldm_filter_new(asn_filter, ldm_data_type_CAM);
TEST_ASSERT_MESSAGE(filter != NULL, "New filter should not return NULL when type is CAM and filter is valid");
ret = ldm_filter_check(filter, cam);
TEST_ASSERT_MESSAGE(ret == 1, "Filter check should return 1 when filter matches the data");
// check with a CAM that does not match the filter due to the speed value (filter1)
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedValue = 8;
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedConfidence = 7;
ret = ldm_filter_check(filter, cam);
TEST_ASSERT_MESSAGE(ret == 0, "Filter check should return 0 when filter does not match the speed (speed <= 10)");
// check with a CAM that does not match the filter due to the speed value (filter2)
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedValue = 101;
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedConfidence = 7;
ret = ldm_filter_check(filter, cam);
TEST_ASSERT_MESSAGE(ret == 0, "Filter check should return 0 when filter does not match the speed (speed >= 100)");
// check with a CAM that matches the filter due to the speed value (filter3)
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedValue = 123;
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedConfidence = 7;
ret = ldm_filter_check(filter, cam);
TEST_ASSERT_MESSAGE(ret == 1, "Filter check should return 1 when filter matches the speed (speed == 123)");
// check with a CAM that does not match the filter due to the speed value (filter4)
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedValue = 50;
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedConfidence = 7;
ret = ldm_filter_check(filter, cam);
TEST_ASSERT_MESSAGE(ret == 0, "Filter check should return 0 when filter does not match the speed (speed == 50)");
// check with a CAM that does not match the filter due to the speed confidence
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedValue = 20;
cam->cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency.speed.speedConfidence = 11;
ret = ldm_filter_check(filter, cam);
TEST_ASSERT_MESSAGE(ret == 0, "Filter check should return 0 when speed confidence exceeds the reference value");
ASN_STRUCT_FREE(asn_DEF_EI2_CAM, cam);
ASN_STRUCT_FREE(asn_DEF_EI2_Filter, asn_filter);
ldm_filter_release(filter);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_ldm_filter_new);
RUN_TEST(test_ldm_filter_complex);
return UNITY_END();
}