|
@@ -44,9 +44,14 @@ static UA_NodeId outNodeId;
|
|
|
#ifdef UA_ENABLE_HISTORIZING
|
|
|
static UA_HistoryDataBackend serverBackend;
|
|
|
|
|
|
-// same size as the test data
|
|
|
-static const size_t testDataSize = sizeof(testData) / sizeof(testData[0]);
|
|
|
-static UA_DateTime receivedTestData[sizeof(testData) / sizeof(testData[0])];
|
|
|
+// to receive data after we inserted data, we need in datavalue more space
|
|
|
+struct ReceiveTupel {
|
|
|
+ UA_DateTime timestamp;
|
|
|
+ UA_Int64 value;
|
|
|
+};
|
|
|
+
|
|
|
+static const size_t receivedDataSize = (sizeof(testData) / sizeof(testData[0])) + 10;
|
|
|
+static struct ReceiveTupel receivedTestData[(sizeof(testData) / sizeof(testData[0])) + 10];
|
|
|
static size_t receivedTestDataPos;
|
|
|
#endif
|
|
|
|
|
@@ -59,6 +64,24 @@ THREAD_CALLBACK(serverloop)
|
|
|
#ifdef UA_ENABLE_HISTORIZING
|
|
|
static UA_Boolean
|
|
|
fillHistoricalDataBackend(UA_HistoryDataBackend backend);
|
|
|
+static void resetReceiveBuffer(void)
|
|
|
+{
|
|
|
+ receivedTestDataPos = 0;
|
|
|
+ memset(receivedTestData, 0, sizeof(receivedTestData));
|
|
|
+}
|
|
|
+static void fillInt64DataValue(UA_DateTime timestamp, UA_Int64 value, UA_DataValue *dataValue)
|
|
|
+{
|
|
|
+ UA_DataValue_init(dataValue);
|
|
|
+ dataValue->hasValue = true;
|
|
|
+ UA_Int64 d = value;
|
|
|
+ UA_Variant_setScalarCopy(&dataValue->value, &d, &UA_TYPES[UA_TYPES_INT64]);
|
|
|
+ dataValue->hasSourceTimestamp = true;
|
|
|
+ dataValue->sourceTimestamp = timestamp;
|
|
|
+ dataValue->hasServerTimestamp = true;
|
|
|
+ dataValue->serverTimestamp = timestamp;
|
|
|
+ dataValue->hasStatus = true;
|
|
|
+ dataValue->status = UA_STATUSCODE_GOOD;
|
|
|
+}
|
|
|
#endif
|
|
|
static void
|
|
|
setup(void)
|
|
@@ -66,9 +89,7 @@ setup(void)
|
|
|
running = true;
|
|
|
config = UA_ServerConfig_new_default();
|
|
|
#ifdef UA_ENABLE_HISTORIZING
|
|
|
- receivedTestDataPos = 0;
|
|
|
- memset(receivedTestData, 0, sizeof(receivedTestData));
|
|
|
-
|
|
|
+ resetReceiveBuffer();
|
|
|
gathering = (UA_HistoryDataGathering*)UA_calloc(1, sizeof(UA_HistoryDataGathering));
|
|
|
*gathering = UA_HistoryDataGathering_Default(1);
|
|
|
config->historyDatabase = UA_HistoryDatabase_default(*gathering);
|
|
@@ -84,7 +105,7 @@ setup(void)
|
|
|
attr.description = UA_LOCALIZEDTEXT("en-US","the answer");
|
|
|
attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer");
|
|
|
attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId;
|
|
|
- attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_HISTORYREAD;
|
|
|
+ attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_HISTORYREAD | UA_ACCESSLEVELMASK_HISTORYWRITE;
|
|
|
attr.historizing = true;
|
|
|
|
|
|
/* Add the variable node to the information model */
|
|
@@ -156,20 +177,12 @@ fillHistoricalDataBackend(UA_HistoryDataBackend backend)
|
|
|
{
|
|
|
fprintf(stderr, "Adding to historical data backend: ");
|
|
|
for (size_t i = 0; i < testDataSize; ++i) {
|
|
|
- fprintf(stderr, "%lld, ", testData[i] / UA_DATETIME_SEC);
|
|
|
+ fprintf(stderr, "%lld, ", (long long)testData[i]);
|
|
|
UA_DataValue value;
|
|
|
- UA_DataValue_init(&value);
|
|
|
- value.hasValue = true;
|
|
|
- UA_Int64 d = testData[i];
|
|
|
- UA_Variant_setScalarCopy(&value.value, &d, &UA_TYPES[UA_TYPES_INT64]);
|
|
|
- value.hasSourceTimestamp = true;
|
|
|
- value.sourceTimestamp = testData[i];
|
|
|
- value.hasServerTimestamp = true;
|
|
|
- value.serverTimestamp = testData[i];
|
|
|
- value.hasStatus = true;
|
|
|
- value.status = UA_STATUSCODE_GOOD;
|
|
|
+ fillInt64DataValue(testData[i], testData[i], &value);
|
|
|
if (backend.serverSetHistoryData(server, backend.context, NULL, NULL, &outNodeId, UA_FALSE, &value) != UA_STATUSCODE_GOOD) {
|
|
|
fprintf(stderr, "\n");
|
|
|
+ UA_DataValue_deleteMembers(&value);
|
|
|
return false;
|
|
|
}
|
|
|
UA_DataValue_deleteMembers(&value);
|
|
@@ -178,17 +191,33 @@ fillHistoricalDataBackend(UA_HistoryDataBackend backend)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-static UA_Boolean checkTestData(UA_Boolean inverse) {
|
|
|
- for (size_t i = 0; i < testDataSize; ++i) {
|
|
|
- if (testDataSize != receivedTestDataPos)
|
|
|
+static UA_Boolean checkTestData(UA_Boolean inverse, UA_DateTime *dataA, struct ReceiveTupel *dataB, size_t dataSize) {
|
|
|
+ for (size_t i = 0; i < dataSize; ++i) {
|
|
|
+ if (!inverse && dataA[i] != dataB[i].timestamp)
|
|
|
return false;
|
|
|
- if (!inverse && testData[i] != receivedTestData[i])
|
|
|
+ if (inverse && dataA[i] != dataB[dataSize-i-1].timestamp)
|
|
|
return false;
|
|
|
- if (inverse && testData[i] != receivedTestData[testDataSize-i-1])
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static UA_Boolean checkModifiedData(UA_DateTime *dataA, size_t dataASize, struct ReceiveTupel *dataB, size_t dataBSize) {
|
|
|
+ for (size_t i = 0; i < dataBSize; ++i) {
|
|
|
+ UA_Boolean found = UA_FALSE;
|
|
|
+ for (size_t j = 0; j < dataASize; ++j) {
|
|
|
+ if (dataA[j] == dataB[i].timestamp)
|
|
|
+ found = UA_TRUE;
|
|
|
+ }
|
|
|
+ if (found && dataB[i].timestamp == dataB[i].value) {
|
|
|
return false;
|
|
|
+ }
|
|
|
+ if (!found && dataB[i].timestamp != dataB[i].value) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
static UA_Boolean
|
|
|
receiveCallback(UA_Client *clt,
|
|
|
const UA_NodeId *nodeId,
|
|
@@ -196,108 +225,413 @@ receiveCallback(UA_Client *clt,
|
|
|
const UA_ExtensionObject *_data,
|
|
|
void *callbackContext) {
|
|
|
UA_HistoryData *data = (UA_HistoryData*)_data->content.decoded.data;
|
|
|
- fprintf(stderr, "Received %lu at pos %lu. moreDataAvailable %d\n", data->dataValuesSize, receivedTestDataPos, moreDataAvailable);
|
|
|
- if (receivedTestDataPos + data->dataValuesSize > testDataSize)
|
|
|
+ fprintf(stderr, "Received %lu at pos %lu. moreDataAvailable %d. Data: ", (unsigned long)data->dataValuesSize, (unsigned long)receivedTestDataPos, moreDataAvailable);
|
|
|
+ if (receivedTestDataPos + data->dataValuesSize > receivedDataSize)
|
|
|
return false;
|
|
|
for (size_t i = 0; i < data->dataValuesSize; ++i) {
|
|
|
- receivedTestData[i+receivedTestDataPos] = *((UA_Int64*)data->dataValues[i].value.data);
|
|
|
+ receivedTestData[i+receivedTestDataPos].timestamp = data->dataValues[i].sourceTimestamp;
|
|
|
+ receivedTestData[i+receivedTestDataPos].value = *((UA_Int64*)data->dataValues[i].value.data);
|
|
|
+ fprintf(stderr, "%lld/%lld, ",
|
|
|
+ (long long)receivedTestData[i+receivedTestDataPos].timestamp,
|
|
|
+ (long long)receivedTestData[i+receivedTestDataPos].value);
|
|
|
}
|
|
|
+ fprintf(stderr, "\n");
|
|
|
receivedTestDataPos += data->dataValuesSize;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
START_TEST(Client_HistorizingReadRawAll)
|
|
|
{
|
|
|
- UA_Client_HistoryRead_raw(client,
|
|
|
- &outNodeId,
|
|
|
- receiveCallback,
|
|
|
- TESTDATA_START_TIME,
|
|
|
- TESTDATA_STOP_TIME,
|
|
|
- UA_STRING_NULL,
|
|
|
- false,
|
|
|
- 100,
|
|
|
- UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
- (void*)false);
|
|
|
- ck_assert(checkTestData(false));
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(testDataSize, receivedTestDataPos);
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
}
|
|
|
END_TEST
|
|
|
|
|
|
START_TEST(Client_HistorizingReadRawOne)
|
|
|
{
|
|
|
- UA_Client_HistoryRead_raw(client,
|
|
|
- &outNodeId,
|
|
|
- receiveCallback,
|
|
|
- TESTDATA_START_TIME,
|
|
|
- TESTDATA_STOP_TIME,
|
|
|
- UA_STRING_NULL,
|
|
|
- false,
|
|
|
- 1,
|
|
|
- UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
- (void*)false);
|
|
|
- ck_assert(checkTestData(false));
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 1,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(testDataSize, receivedTestDataPos);
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
}
|
|
|
END_TEST
|
|
|
|
|
|
START_TEST(Client_HistorizingReadRawTwo)
|
|
|
{
|
|
|
- UA_Client_HistoryRead_raw(client,
|
|
|
- &outNodeId,
|
|
|
- receiveCallback,
|
|
|
- TESTDATA_START_TIME,
|
|
|
- TESTDATA_STOP_TIME,
|
|
|
- UA_STRING_NULL,
|
|
|
- false,
|
|
|
- 2,
|
|
|
- UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
- (void*)false);
|
|
|
- ck_assert(checkTestData(false));
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 2,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(testDataSize, receivedTestDataPos);
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
}
|
|
|
END_TEST
|
|
|
START_TEST(Client_HistorizingReadRawAllInv)
|
|
|
{
|
|
|
- UA_Client_HistoryRead_raw(client,
|
|
|
- &outNodeId,
|
|
|
- receiveCallback,
|
|
|
- TESTDATA_STOP_TIME,
|
|
|
- TESTDATA_START_TIME,
|
|
|
- UA_STRING_NULL,
|
|
|
- false,
|
|
|
- 100,
|
|
|
- UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
- (void*)true);
|
|
|
- ck_assert(checkTestData(true));
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)true);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(testDataSize, receivedTestDataPos);
|
|
|
+ ck_assert(checkTestData(true, testData, receivedTestData, testDataSize));
|
|
|
}
|
|
|
END_TEST
|
|
|
|
|
|
START_TEST(Client_HistorizingReadRawOneInv)
|
|
|
{
|
|
|
- UA_Client_HistoryRead_raw(client,
|
|
|
- &outNodeId,
|
|
|
- receiveCallback,
|
|
|
- TESTDATA_STOP_TIME,
|
|
|
- TESTDATA_START_TIME,
|
|
|
- UA_STRING_NULL,
|
|
|
- false,
|
|
|
- 1,
|
|
|
- UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
- (void*)true);
|
|
|
- ck_assert(checkTestData(true));
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 1,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)true);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(testDataSize, receivedTestDataPos);
|
|
|
+ ck_assert(checkTestData(true, testData, receivedTestData, testDataSize));
|
|
|
}
|
|
|
END_TEST
|
|
|
|
|
|
START_TEST(Client_HistorizingReadRawTwoInv)
|
|
|
{
|
|
|
- UA_Client_HistoryRead_raw(client,
|
|
|
- &outNodeId,
|
|
|
- receiveCallback,
|
|
|
- TESTDATA_STOP_TIME,
|
|
|
- TESTDATA_START_TIME,
|
|
|
- UA_STRING_NULL,
|
|
|
- false,
|
|
|
- 2,
|
|
|
- UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
- (void*)true);
|
|
|
- ck_assert(checkTestData(true));
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 2,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)true);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(testDataSize, receivedTestDataPos);
|
|
|
+ ck_assert(checkTestData(true, testData, receivedTestData, testDataSize));
|
|
|
+}
|
|
|
+END_TEST
|
|
|
+
|
|
|
+START_TEST(Client_HistorizingInsertRawSuccess)
|
|
|
+{
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
+ resetReceiveBuffer();
|
|
|
+ // insert values to the database
|
|
|
+ for (size_t i = 0; i < testInsertDataSuccessSize; ++i) {
|
|
|
+ UA_DataValue value;
|
|
|
+ fillInt64DataValue(testInsertDataSuccess[i], 0, &value);
|
|
|
+ ret = UA_Client_HistoryUpdate_insert(client, &outNodeId, &value);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+ UA_DataValue_deleteMembers(&value);
|
|
|
+ }
|
|
|
+ // check result
|
|
|
+ ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(receivedTestDataPos, testInsertResultDataSize);
|
|
|
+ ck_assert(checkTestData(false, testInsertResultData, receivedTestData, receivedTestDataPos));
|
|
|
+ ck_assert(checkModifiedData(testInsertDataSuccess, testInsertDataSuccessSize, receivedTestData, receivedTestDataPos));
|
|
|
+}
|
|
|
+END_TEST
|
|
|
+
|
|
|
+START_TEST(Client_HistorizingReplaceRawSuccess)
|
|
|
+{
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
+ resetReceiveBuffer();
|
|
|
+ // replace values to the database
|
|
|
+ for (size_t i = 0; i < testReplaceDataSuccessSize; ++i) {
|
|
|
+ UA_DataValue value;
|
|
|
+ fillInt64DataValue(testReplaceDataSuccess[i], 0, &value);
|
|
|
+ ret = UA_Client_HistoryUpdate_replace(client, &outNodeId, &value);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+ UA_DataValue_deleteMembers(&value);
|
|
|
+ }
|
|
|
+ // check result
|
|
|
+ ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(receivedTestDataPos, testDataSize);
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
|
|
|
+ ck_assert(checkModifiedData(testReplaceDataSuccess, testReplaceDataSuccessSize, receivedTestData, receivedTestDataPos));
|
|
|
+}
|
|
|
+END_TEST
|
|
|
+
|
|
|
+START_TEST(Client_HistorizingUpdateRawSuccess)
|
|
|
+{
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
+ resetReceiveBuffer();
|
|
|
+ // insert values to the database
|
|
|
+ for (size_t i = 0; i < testInsertDataSuccessSize; ++i) {
|
|
|
+ UA_DataValue value;
|
|
|
+ fillInt64DataValue(testInsertDataSuccess[i], 0, &value);
|
|
|
+ ret = UA_Client_HistoryUpdate_update(client, &outNodeId, &value);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOODENTRYINSERTED));
|
|
|
+ UA_DataValue_deleteMembers(&value);
|
|
|
+ }
|
|
|
+ // replace values to the database
|
|
|
+ for (size_t i = 0; i < testReplaceDataSuccessSize; ++i) {
|
|
|
+ UA_DataValue value;
|
|
|
+ fillInt64DataValue(testReplaceDataSuccess[i], 0, &value);
|
|
|
+ ret = UA_Client_HistoryUpdate_update(client, &outNodeId, &value);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOODENTRYREPLACED));
|
|
|
+ UA_DataValue_deleteMembers(&value);
|
|
|
+ }
|
|
|
+ // check result
|
|
|
+ ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(receivedTestDataPos, testInsertResultDataSize);
|
|
|
+ ck_assert(checkTestData(false, testInsertResultData, receivedTestData, receivedTestDataPos));
|
|
|
+}
|
|
|
+END_TEST
|
|
|
+
|
|
|
+START_TEST(Client_HistorizingDeleteRaw)
|
|
|
+{
|
|
|
+ for (size_t i = 0; i < testDeleteRangeDataSize; ++i) {
|
|
|
+ fprintf(stderr, "Client_HistorizingDeleteRaw: Testing %lu: {%lld, %lld, %lu, %s}\n",
|
|
|
+ (unsigned long)i,
|
|
|
+ (long long)testDeleteRangeData[i].start,
|
|
|
+ (long long)testDeleteRangeData[i].end,
|
|
|
+ (unsigned long)testDeleteRangeData[i].historySize,
|
|
|
+ UA_StatusCode_name(testDeleteRangeData[i].statusCode));
|
|
|
+ resetReceiveBuffer();
|
|
|
+ serverBackend.removeDataValue(server,
|
|
|
+ serverBackend.context,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ &outNodeId,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME);
|
|
|
+ fillHistoricalDataBackend(serverBackend);
|
|
|
+ // check result
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
|
|
|
+ resetReceiveBuffer();
|
|
|
+
|
|
|
+ ret = UA_Client_HistoryUpdate_deleteRaw(client,
|
|
|
+ &outNodeId,
|
|
|
+ testDeleteRangeData[i].start,
|
|
|
+ testDeleteRangeData[i].end);
|
|
|
+ if (ret != testDeleteRangeData[i].statusCode)
|
|
|
+ fprintf(stderr, "Error: ret %s != statusCode%s\n", UA_StatusCode_name(ret), UA_StatusCode_name(testDeleteRangeData[i].statusCode));
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(testDeleteRangeData[i].statusCode));
|
|
|
+
|
|
|
+ // check result
|
|
|
+ ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+ if (receivedTestDataPos != testDeleteRangeData[i].historySize)
|
|
|
+ fprintf(stderr, "Error: receivedTestDataPos != testDeleteRangeData[i].historySize\n");
|
|
|
+ ck_assert_uint_eq(receivedTestDataPos, testDeleteRangeData[i].historySize);
|
|
|
+ }
|
|
|
+}
|
|
|
+END_TEST
|
|
|
+
|
|
|
+START_TEST(Client_HistorizingInsertRawFail)
|
|
|
+{
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
+ resetReceiveBuffer();
|
|
|
+ // insert values to the database
|
|
|
+ for (size_t i = 0; i < testReplaceDataSuccessSize; ++i) {
|
|
|
+ UA_DataValue value;
|
|
|
+ fillInt64DataValue(testReplaceDataSuccess[i], 0, &value);
|
|
|
+ ret = UA_Client_HistoryUpdate_insert(client, &outNodeId, &value);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_BADENTRYEXISTS));
|
|
|
+ UA_DataValue_deleteMembers(&value);
|
|
|
+ }
|
|
|
+ // check result
|
|
|
+ ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(receivedTestDataPos, testDataSize);
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
|
|
|
+ ck_assert(checkModifiedData(NULL, 0, receivedTestData, receivedTestDataPos));
|
|
|
+}
|
|
|
+END_TEST
|
|
|
+
|
|
|
+START_TEST(Client_HistorizingReplaceRawFail)
|
|
|
+{
|
|
|
+ UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
|
|
|
+ resetReceiveBuffer();
|
|
|
+ // replace values to the database
|
|
|
+ for (size_t i = 0; i < testInsertDataSuccessSize; ++i) {
|
|
|
+ UA_DataValue value;
|
|
|
+ fillInt64DataValue(testInsertDataSuccess[i], 0, &value);
|
|
|
+ ret = UA_Client_HistoryUpdate_replace(client, &outNodeId, &value);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_BADNOENTRYEXISTS));
|
|
|
+ UA_DataValue_deleteMembers(&value);
|
|
|
+ }
|
|
|
+ // check result
|
|
|
+ ret = UA_Client_HistoryRead_raw(client,
|
|
|
+ &outNodeId,
|
|
|
+ receiveCallback,
|
|
|
+ TESTDATA_START_TIME,
|
|
|
+ TESTDATA_STOP_TIME,
|
|
|
+ UA_STRING_NULL,
|
|
|
+ false,
|
|
|
+ 100,
|
|
|
+ UA_TIMESTAMPSTORETURN_BOTH,
|
|
|
+ (void*)false);
|
|
|
+ ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
|
|
|
+
|
|
|
+ ck_assert_uint_eq(receivedTestDataPos, testDataSize);
|
|
|
+ ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
|
|
|
+ ck_assert(checkModifiedData(NULL, 0, receivedTestData, receivedTestDataPos));
|
|
|
}
|
|
|
END_TEST
|
|
|
|
|
@@ -315,6 +649,12 @@ static Suite* testSuite_Client(void)
|
|
|
tcase_add_test(tc_client, Client_HistorizingReadRawAllInv);
|
|
|
tcase_add_test(tc_client, Client_HistorizingReadRawOneInv);
|
|
|
tcase_add_test(tc_client, Client_HistorizingReadRawTwoInv);
|
|
|
+ tcase_add_test(tc_client, Client_HistorizingInsertRawSuccess);
|
|
|
+ tcase_add_test(tc_client, Client_HistorizingReplaceRawSuccess);
|
|
|
+ tcase_add_test(tc_client, Client_HistorizingUpdateRawSuccess);
|
|
|
+ tcase_add_test(tc_client, Client_HistorizingDeleteRaw);
|
|
|
+ tcase_add_test(tc_client, Client_HistorizingInsertRawFail);
|
|
|
+ tcase_add_test(tc_client, Client_HistorizingReplaceRawFail);
|
|
|
#endif /* UA_ENABLE_HISTORIZING */
|
|
|
suite_add_tcase(s, tc_client);
|
|
|
|