Преглед на файлове

historical_update: Add Test which test server and client code.

Peter Rustler преди 5 години
родител
ревизия
89cf21bea0
променени са 2 файла, в които са добавени 496 реда и са изтрити 94 реда
  1. 432 92
      tests/client/check_client_historical_data.c
  2. 64 2
      tests/client/historical_read_test_data.h

+ 432 - 92
tests/client/check_client_historical_data.c

@@ -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);
 

+ 64 - 2
tests/client/historical_read_test_data.h

@@ -12,9 +12,10 @@
 #define UA_HISTORICAL_READ_TEST_DATA_H_
 
 #include "ua_types.h"
+#include <limits.h>
 
-#define TESTDATA_START_TIME 99
-#define TESTDATA_STOP_TIME 501
+#define TESTDATA_START_TIME 1
+#define TESTDATA_STOP_TIME 601
 static UA_DateTime testData[] = {
     100,
     200,
@@ -22,5 +23,66 @@ static UA_DateTime testData[] = {
     400,
     500
 };
+static const size_t testDataSize = (sizeof(testData) / sizeof(testData[0]));
+
+static UA_DateTime testInsertDataSuccess[] = {
+    50,
+    250,
+    550
+};
+static const size_t testInsertDataSuccessSize = (sizeof(testInsertDataSuccess) / sizeof(testInsertDataSuccess[0]));
+
+
+static UA_DateTime testInsertResultData[] = {
+    50,
+    100,
+    200,
+    250,
+    300,
+    400,
+    500,
+    550
+};
+static size_t testInsertResultDataSize = (sizeof(testInsertResultData) / sizeof(testInsertResultData[0]));
+
+static UA_DateTime testReplaceDataSuccess[] = {
+    100,
+    300,
+    500
+};
+static const size_t testReplaceDataSuccessSize = (sizeof(testReplaceDataSuccess) / sizeof(testReplaceDataSuccess[0]));
+
+struct DeleteRange {
+    UA_DateTime start;
+    UA_DateTime end;
+    size_t historySize;
+    UA_StatusCode statusCode;
+};
+
+static struct DeleteRange testDeleteRangeData[] = {
+{200, 400, 3, UA_STATUSCODE_GOOD},
+{100, 400, 2, UA_STATUSCODE_GOOD},
+{200, 500, 2, UA_STATUSCODE_GOOD},
+{100, 500, 1, UA_STATUSCODE_GOOD},
+{100, 550, 0, UA_STATUSCODE_GOOD},
+{50, 550, 0, UA_STATUSCODE_GOOD},
+{500, 550, 4, UA_STATUSCODE_GOOD},
+{50, 150, 4, UA_STATUSCODE_GOOD},
+{100, 100, 4, UA_STATUSCODE_GOOD},
+{500, 500, 4, UA_STATUSCODE_GOOD},
+{200, 200, 4, UA_STATUSCODE_GOOD},
+{50, 50, 5, UA_STATUSCODE_BADNODATA},
+{550, 550, 5, UA_STATUSCODE_BADNODATA},
+{150, 150, 5, UA_STATUSCODE_BADNODATA},
+{200, 100, 5, UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED},
+{LLONG_MIN, LLONG_MAX, 0, UA_STATUSCODE_GOOD},
+{0, LLONG_MAX, 0, UA_STATUSCODE_GOOD},
+{LLONG_MIN, 0, 5, UA_STATUSCODE_BADNODATA},
+{0, 0, 5, UA_STATUSCODE_BADNODATA},
+{50, 75, 5, UA_STATUSCODE_BADNODATA},
+{50, 100, 5, UA_STATUSCODE_BADNODATA},
+{550, 600, 5, UA_STATUSCODE_BADNODATA}
+};
+static const size_t testDeleteRangeDataSize = (sizeof(testDeleteRangeData) / sizeof(testDeleteRangeData[0]));
 
 #endif /*UA_HISTORICAL_READ_TEST_DATA_H_*/