diff --git a/KafkaBridge/test/testLibDebeziumBridge.js b/KafkaBridge/test/testLibDebeziumBridge.js index 0b63fec6..1913ed2f 100644 --- a/KafkaBridge/test/testLibDebeziumBridge.js +++ b/KafkaBridge/test/testLibDebeziumBridge.js @@ -448,6 +448,192 @@ describe('Test parseBeforeAfterEntity', function () { }); revert(); }); + it('Should sort attributes based on datasetId with @none at index 0', async function () { + const config = { + bridgeCommon: { + kafkaSyncOnAttribute: 'kafkaSyncOn' + } + }; + const Logger = function () { + return logger; + }; + const ba = { + id: 'id', + type: 'type', + data: '{\ + "@id":"id", "@type": ["type"],\ + "https://uri.etsi.org/ngsi-ld/createdAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T20:31:26.123656Z"\ + }],\ + "https://example/prop":[{\ + "https://uri.etsi.org/ngsi-ld/hasValue": [{\ + "@value": "value",\ + "@type": "https://example/type"\ + }],\ + "https://uri.etsi.org/ngsi-ld/datasetId": [{\ + "@id": "-+brokenuri:withspecialsigns"\ + }],\ + "https://uri.etsi.org/ngsi-ld/createdAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T20:31:26.123656Z"\ + }],\ + "https://uri.etsi.org/ngsi-ld/modifiedAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T23:11:28.457509Z"\ + }]\ + },\ + {\ + "https://uri.etsi.org/ngsi-ld/hasValue": [{\ + "@value": "value2",\ + "@type": "https://example/type"\ + }],\ + "https://uri.etsi.org/ngsi-ld/createdAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T20:31:26.123656Z"\ + }],\ + "https://uri.etsi.org/ngsi-ld/modifiedAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T23:11:28.457509Z"\ + }]\ + },\ + {\ + "https://uri.etsi.org/ngsi-ld/hasValue": [{\ + "@value": "value3",\ + "@type": "https://example/type"\ + }],\ + "https://uri.etsi.org/ngsi-ld/datasetId": [{\ + "@id": "23brokenuri:withnumbers"\ + }],\ + "https://uri.etsi.org/ngsi-ld/createdAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T20:31:26.123656Z"\ + }],\ + "https://uri.etsi.org/ngsi-ld/modifiedAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T23:11:28.457509Z"\ + }]\ + },\ + {\ + "https://uri.etsi.org/ngsi-ld/hasValue": [{\ + "@value": "value4",\ + "@type": "https://example/type"\ + }],\ + "https://uri.etsi.org/ngsi-ld/datasetId": [{\ + "@id": "uri:normal_second"\ + }],\ + "https://uri.etsi.org/ngsi-ld/createdAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T20:31:26.123656Z"\ + }],\ + "https://uri.etsi.org/ngsi-ld/modifiedAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T23:11:28.457509Z"\ + }]\ + },\ + {\ + "https://uri.etsi.org/ngsi-ld/hasValue": [{\ + "@value": "value5",\ + "@type": "https://example/type"\ + }],\ + "https://uri.etsi.org/ngsi-ld/datasetId": [{\ + "@id": "uri:normal_first"\ + }],\ + "https://uri.etsi.org/ngsi-ld/createdAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T20:31:26.123656Z"\ + }],\ + "https://uri.etsi.org/ngsi-ld/modifiedAt":[{\ + "@type": "https://uri.etsi.org/ngsi-ld/DateTime",\ + "@value": "2022-02-19T23:11:28.457509Z"\ + }]\ + }\ + ]\ + }' + }; + const revert = ToTest.__set__('Logger', Logger); + const debeziumBridge = new ToTest(config); + const result = debeziumBridge.parseBeforeAfterEntity(ba); + assert.deepEqual(result.entity, { id: 'id', type: 'type', 'https://example/prop': 'id\\https://example/prop' }); + assert.deepEqual(result.attributes, { + 'https://example/prop': [{ + id: 'id\\https://example/prop', + entityId: 'id', + nodeType: '@value', + name: 'https://example/prop', + type: 'https://uri.etsi.org/ngsi-ld/Property', + 'https://uri.etsi.org/ngsi-ld/datasetId': '@none', + 'https://uri.etsi.org/ngsi-ld/hasValue': 'value2', + 'https://uri.etsi.org/ngsi-ld/observedAt': [{ + '@type': 'https://uri.etsi.org/ngsi-ld/DateTime', + '@value': '2022-02-19T23:11:28.457509Z' + }], + valueType: 'https://example/type', + index: 0 + }, + { + id: 'id\\https://example/prop', + entityId: 'id', + nodeType: '@value', + name: 'https://example/prop', + type: 'https://uri.etsi.org/ngsi-ld/Property', + 'https://uri.etsi.org/ngsi-ld/datasetId': '-+brokenuri:withspecialsigns', + 'https://uri.etsi.org/ngsi-ld/hasValue': 'value', + 'https://uri.etsi.org/ngsi-ld/observedAt': [{ + '@type': 'https://uri.etsi.org/ngsi-ld/DateTime', + '@value': '2022-02-19T23:11:28.457509Z' + }], + valueType: 'https://example/type', + index: 1 + }, + { + id: 'id\\https://example/prop', + entityId: 'id', + nodeType: '@value', + name: 'https://example/prop', + type: 'https://uri.etsi.org/ngsi-ld/Property', + 'https://uri.etsi.org/ngsi-ld/datasetId': '23brokenuri:withnumbers', + 'https://uri.etsi.org/ngsi-ld/hasValue': 'value3', + 'https://uri.etsi.org/ngsi-ld/observedAt': [{ + '@type': 'https://uri.etsi.org/ngsi-ld/DateTime', + '@value': '2022-02-19T23:11:28.457509Z' + }], + valueType: 'https://example/type', + index: 2 + }, + { + id: 'id\\https://example/prop', + entityId: 'id', + nodeType: '@value', + name: 'https://example/prop', + type: 'https://uri.etsi.org/ngsi-ld/Property', + 'https://uri.etsi.org/ngsi-ld/datasetId': 'uri:normal_first', + 'https://uri.etsi.org/ngsi-ld/hasValue': 'value5', + 'https://uri.etsi.org/ngsi-ld/observedAt': [{ + '@type': 'https://uri.etsi.org/ngsi-ld/DateTime', + '@value': '2022-02-19T23:11:28.457509Z' + }], + valueType: 'https://example/type', + index: 3 + }, + { + id: 'id\\https://example/prop', + entityId: 'id', + nodeType: '@value', + name: 'https://example/prop', + type: 'https://uri.etsi.org/ngsi-ld/Property', + 'https://uri.etsi.org/ngsi-ld/datasetId': 'uri:normal_second', + 'https://uri.etsi.org/ngsi-ld/hasValue': 'value4', + 'https://uri.etsi.org/ngsi-ld/observedAt': [{ + '@type': 'https://uri.etsi.org/ngsi-ld/DateTime', + '@value': '2022-02-19T23:11:28.457509Z' + }], + valueType: 'https://example/type', + index: 4 + }] + }); + revert(); + }); it('Should return `undefined` due to json parse error', async function () { const config = { bridgeCommon: { diff --git a/test/bats/test-bridges/test-debezium-bridge.bats b/test/bats/test-bridges/test-debezium-bridge.bats index d45336b0..f3ab2ad8 100644 --- a/test/bats/test-bridges/test-debezium-bridge.bats +++ b/test/bats/test-bridges/test-debezium-bridge.bats @@ -12,6 +12,7 @@ CLIENT_ID=scorpio KEYCLOAKURL=http://keycloak.local/auth/realms CUTTER=/tmp/CUTTER CUTTER_TIMESTAMPED=/tmp/CUTTER_TIMESTAMPED +CUTTER_DATASETID=/tmp/CUTTER_DATASETID KAFKA_BOOTSTRAP=my-cluster-kafka-bootstrap:9092 KAFKACAT_ATTRIBUTES=/tmp/KAFKACAT_ATTRIBUTES KAFKACAT_ATTRIBUTES_TOPIC=iff.ngsild.attributes @@ -43,7 +44,7 @@ cat << EOF > ${CUTTER} { "type": "Relationship", "object": "urn:workpiece-test:12345", - "datasetId": "urn:workpiece-test:12345-ZZZ" + "datasetId": "urn:workpiece-test:12345-ZZZ" }, { "type": "Relationship", @@ -127,6 +128,39 @@ cat << EOF > ${CUTTER_TIMESTAMPED} } EOF +cat << EOF > ${CUTTER_DATASETID} +{ + "@context": "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context.jsonld", + "id": "${PLASMACUTTER_ID}", + "type": "https://industry-fusion.com/types/v0.9/${KAFKACAT_ENTITY_PLASMACUTTER_NAME}", + "https://industry-fusion.com/types/v0.9/state": [ + { + "type": "Property", + "value": "ON", + "datasetId": "urn:state_on" + }, + { + "type": "Property", + "value": "OFF", + "datasetId": "urn:state_off" + }, + { + "type": "Property", + "value": "ONN", + "datasetId": "2urn:state_on" + }, + { + "type": "Property", + "value": "MAYBE" + }, + { + "type": "Property", + "value": "OFFOFF", + "datasetId": "+=-urn:state_off" + } + ] +} +EOF compare_create_attributes_timestamps() { cat << EOF | diff "$1" - >&3 @@ -263,6 +297,41 @@ compare_delete_plasmacutter() { EOF } +compare_create_attributes_datasetid() { + cat << EOF | diff "$1" - >&3 +{"id":"${PLASMACUTTER_ID}\\\https://industry-fusion.com/types/v0.9/state",\ +"entityId":"${PLASMACUTTER_ID}",\ +"name":"https://industry-fusion.com/types/v0.9/state",\ +"https://uri.etsi.org/ngsi-ld/datasetId":"@none",\ +"type":"https://uri.etsi.org/ngsi-ld/Property",\ +"https://uri.etsi.org/ngsi-ld/hasValue":"MAYBE","nodeType":"@value","index":0} +{"id":"${PLASMACUTTER_ID}\\\https://industry-fusion.com/types/v0.9/state",\ +"entityId":"${PLASMACUTTER_ID}",\ +"name":"https://industry-fusion.com/types/v0.9/state",\ +"https://uri.etsi.org/ngsi-ld/datasetId":"+=-urn:state_off",\ +"type":"https://uri.etsi.org/ngsi-ld/Property",\ +"https://uri.etsi.org/ngsi-ld/hasValue":"OFFOFF","nodeType":"@value","index":1} +{"id":"${PLASMACUTTER_ID}\\\https://industry-fusion.com/types/v0.9/state",\ +"entityId":"${PLASMACUTTER_ID}",\ +"name":"https://industry-fusion.com/types/v0.9/state",\ +"https://uri.etsi.org/ngsi-ld/datasetId":"2urn:state_on",\ +"type":"https://uri.etsi.org/ngsi-ld/Property",\ +"https://uri.etsi.org/ngsi-ld/hasValue":"ONN","nodeType":"@value","index":2} +{"id":"${PLASMACUTTER_ID}\\\https://industry-fusion.com/types/v0.9/state",\ +"entityId":"${PLASMACUTTER_ID}",\ +"name":"https://industry-fusion.com/types/v0.9/state",\ +"https://uri.etsi.org/ngsi-ld/datasetId":"urn:state_off",\ +"type":"https://uri.etsi.org/ngsi-ld/Property",\ +"https://uri.etsi.org/ngsi-ld/hasValue":"OFF","nodeType":"@value","index":3} +{"id":"${PLASMACUTTER_ID}\\\https://industry-fusion.com/types/v0.9/state",\ +"entityId":"${PLASMACUTTER_ID}",\ +"name":"https://industry-fusion.com/types/v0.9/state",\ +"https://uri.etsi.org/ngsi-ld/datasetId":"urn:state_on",\ +"type":"https://uri.etsi.org/ngsi-ld/Property",\ +"https://uri.etsi.org/ngsi-ld/hasValue":"ON","nodeType":"@value","index":4} +EOF +} + get_password() { kubectl -n ${NAMESPACE} get ${USERSECRET} -o jsonpath='{.data.password}'| base64 -d } @@ -385,4 +454,24 @@ teardown(){ run compare_create_attributes_timestamps ${KAFKACAT_ATTRIBUTES} [ "$status" -eq 0 ] +} + +@test "verify debezium bridge sorts attributes based on their datasetIds" { + $SKIP + password=$(get_password) + token=$(get_token) + delete_ngsild "$token" "$PLASMACUTTER_ID" || echo "Could not delete $PLASMACUTTER_ID. But that is okay." + sleep 2 + (exec stdbuf -oL kafkacat -C -t ${KAFKACAT_ATTRIBUTES_TOPIC} -b ${KAFKA_BOOTSTRAP} -o end >${KAFKACAT_ATTRIBUTES}) & + echo "# launched kafkacat for debezium updates, wait some time to let it connect" + sleep 2 + create_ngsild "$token" "$CUTTER_DATASETID" + echo "# Sent ngsild updates, sleep 5s to let debezium bridge react" + sleep 2 + echo "# now killing kafkacat and evaluate result" + killall kafkacat + LC_ALL="en_US.UTF-8" sort -o ${KAFKACAT_ATTRIBUTES} ${KAFKACAT_ATTRIBUTES} + echo "# Compare ATTRIBUTES" + run compare_create_attributes_datasetid ${KAFKACAT_ATTRIBUTES} + [ "$status" -eq 0 ] } \ No newline at end of file