check_client_historical_data.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
  6. */
  7. #include <check.h>
  8. #include <open62541/server.h>
  9. #include <open62541/server_config_default.h>
  10. #include <open62541/client_config_default.h>
  11. #include <open62541/client.h>
  12. #include <open62541/plugin/historydatabase.h>
  13. #include <open62541/plugin/historydatabase_default.h>
  14. #include "client/ua_client_internal.h"
  15. #include "ua_network_tcp.h"
  16. #include "testing_clock.h"
  17. #include "testing_networklayers.h"
  18. #include "thread_wrapper.h"
  19. #include "ua_plugin_history_data_backend.h"
  20. #include "ua_historydatabackend_memory.h"
  21. #include "ua_historydatagathering_default.h"
  22. #ifdef UA_ENABLE_HISTORIZING
  23. #include "historical_read_test_data.h"
  24. #endif
  25. #include <stddef.h>
  26. static UA_Server *server;
  27. static UA_ServerConfig *config;
  28. #ifdef UA_ENABLE_HISTORIZING
  29. static UA_HistoryDataGathering *gathering;
  30. #endif
  31. static UA_Boolean running;
  32. static THREAD_HANDLE server_thread;
  33. static UA_Client *client;
  34. static UA_NodeId parentNodeId;
  35. static UA_NodeId parentReferenceNodeId;
  36. static UA_NodeId outNodeId;
  37. #ifdef UA_ENABLE_HISTORIZING
  38. static UA_HistoryDataBackend serverBackend;
  39. // to receive data after we inserted data, we need in datavalue more space
  40. struct ReceiveTupel {
  41. UA_DateTime timestamp;
  42. UA_Int64 value;
  43. };
  44. static const size_t receivedDataSize = (sizeof(testData) / sizeof(testData[0])) + 10;
  45. static struct ReceiveTupel receivedTestData[(sizeof(testData) / sizeof(testData[0])) + 10];
  46. static size_t receivedTestDataPos;
  47. #endif
  48. THREAD_CALLBACK(serverloop)
  49. {
  50. while(running)
  51. UA_Server_run_iterate(server, true);
  52. return 0;
  53. }
  54. #ifdef UA_ENABLE_HISTORIZING
  55. static UA_Boolean
  56. fillHistoricalDataBackend(UA_HistoryDataBackend backend);
  57. static void resetReceiveBuffer(void)
  58. {
  59. receivedTestDataPos = 0;
  60. memset(receivedTestData, 0, sizeof(receivedTestData));
  61. }
  62. static void fillInt64DataValue(UA_DateTime timestamp, UA_Int64 value, UA_DataValue *dataValue)
  63. {
  64. UA_DataValue_init(dataValue);
  65. dataValue->hasValue = true;
  66. UA_Int64 d = value;
  67. UA_Variant_setScalarCopy(&dataValue->value, &d, &UA_TYPES[UA_TYPES_INT64]);
  68. dataValue->hasSourceTimestamp = true;
  69. dataValue->sourceTimestamp = timestamp;
  70. dataValue->hasServerTimestamp = true;
  71. dataValue->serverTimestamp = timestamp;
  72. dataValue->hasStatus = true;
  73. dataValue->status = UA_STATUSCODE_GOOD;
  74. }
  75. #endif
  76. static void
  77. setup(void)
  78. {
  79. running = true;
  80. config = UA_ServerConfig_new_default();
  81. #ifdef UA_ENABLE_HISTORIZING
  82. resetReceiveBuffer();
  83. gathering = (UA_HistoryDataGathering*)UA_calloc(1, sizeof(UA_HistoryDataGathering));
  84. *gathering = UA_HistoryDataGathering_Default(1);
  85. config->historyDatabase = UA_HistoryDatabase_default(*gathering);
  86. #endif
  87. server = UA_Server_new(config);
  88. UA_StatusCode retval = UA_Server_run_startup(server);
  89. ck_assert_str_eq(UA_StatusCode_name(retval), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  90. THREAD_CREATE(server_thread, serverloop);
  91. /* Define the attribute of the uint32 variable node */
  92. UA_VariableAttributes attr = UA_VariableAttributes_default;
  93. UA_UInt32 myUint32 = 40;
  94. UA_Variant_setScalar(&attr.value, &myUint32, &UA_TYPES[UA_TYPES_UINT32]);
  95. attr.description = UA_LOCALIZEDTEXT("en-US","the answer");
  96. attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer");
  97. attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId;
  98. attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_HISTORYREAD | UA_ACCESSLEVELMASK_HISTORYWRITE;
  99. attr.historizing = true;
  100. /* Add the variable node to the information model */
  101. UA_NodeId uint32NodeId = UA_NODEID_STRING(1, "the.answer");
  102. UA_QualifiedName uint32Name = UA_QUALIFIEDNAME(1, "the answer");
  103. parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
  104. parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
  105. UA_NodeId_init(&outNodeId);
  106. ck_assert_uint_eq(UA_Server_addVariableNode(server,
  107. uint32NodeId,
  108. parentNodeId,
  109. parentReferenceNodeId,
  110. uint32Name,
  111. UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
  112. attr,
  113. NULL,
  114. &outNodeId)
  115. , UA_STATUSCODE_GOOD);
  116. #ifdef UA_ENABLE_HISTORIZING
  117. UA_HistorizingNodeIdSettings setting;
  118. serverBackend = UA_HistoryDataBackend_Memory(1, 100);
  119. setting.historizingBackend = serverBackend;
  120. setting.maxHistoryDataResponseSize = 100;
  121. setting.historizingUpdateStrategy = UA_HISTORIZINGUPDATESTRATEGY_USER;
  122. retval = gathering->registerNodeId(server, gathering->context, &outNodeId, setting);
  123. ck_assert_str_eq(UA_StatusCode_name(retval), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  124. ck_assert(fillHistoricalDataBackend(setting.historizingBackend));
  125. #endif
  126. client = UA_Client_new();
  127. UA_ClientConfig_setDefault(UA_Client_getConfig(client));
  128. retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
  129. ck_assert_str_eq(UA_StatusCode_name(retval), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  130. UA_Client_recv = client->connection.recv;
  131. client->connection.recv = UA_Client_recvTesting;
  132. }
  133. static void
  134. teardown(void)
  135. {
  136. /* cleanup */
  137. #ifdef UA_ENABLE_HISTORIZING
  138. UA_HistoryDataBackend_Memory_deleteMembers(&serverBackend);
  139. #endif
  140. UA_Client_disconnect(client);
  141. UA_Client_delete(client);
  142. UA_NodeId_deleteMembers(&parentNodeId);
  143. UA_NodeId_deleteMembers(&parentReferenceNodeId);
  144. UA_NodeId_deleteMembers(&outNodeId);
  145. running = false;
  146. THREAD_JOIN(server_thread);
  147. UA_Server_run_shutdown(server);
  148. UA_Server_delete(server);
  149. UA_ServerConfig_delete(config);
  150. #ifdef UA_ENABLE_HISTORIZING
  151. UA_free(gathering);
  152. #endif
  153. }
  154. #ifdef UA_ENABLE_HISTORIZING
  155. #include <stdio.h>
  156. #include "ua_session.h"
  157. static UA_Boolean
  158. fillHistoricalDataBackend(UA_HistoryDataBackend backend)
  159. {
  160. fprintf(stderr, "Adding to historical data backend: ");
  161. for (size_t i = 0; i < testDataSize; ++i) {
  162. fprintf(stderr, "%lld, ", (long long)testData[i]);
  163. UA_DataValue value;
  164. fillInt64DataValue(testData[i], testData[i], &value);
  165. if (backend.serverSetHistoryData(server, backend.context, NULL, NULL, &outNodeId, UA_FALSE, &value) != UA_STATUSCODE_GOOD) {
  166. fprintf(stderr, "\n");
  167. UA_DataValue_deleteMembers(&value);
  168. return false;
  169. }
  170. UA_DataValue_deleteMembers(&value);
  171. }
  172. fprintf(stderr, "\n");
  173. return true;
  174. }
  175. static UA_Boolean checkTestData(UA_Boolean inverse, UA_DateTime *dataA, struct ReceiveTupel *dataB, size_t dataSize) {
  176. for (size_t i = 0; i < dataSize; ++i) {
  177. if (!inverse && dataA[i] != dataB[i].timestamp)
  178. return false;
  179. if (inverse && dataA[i] != dataB[dataSize-i-1].timestamp)
  180. return false;
  181. }
  182. return true;
  183. }
  184. static UA_Boolean checkModifiedData(UA_DateTime *dataA, size_t dataASize, struct ReceiveTupel *dataB, size_t dataBSize) {
  185. for (size_t i = 0; i < dataBSize; ++i) {
  186. UA_Boolean found = UA_FALSE;
  187. for (size_t j = 0; j < dataASize; ++j) {
  188. if (dataA[j] == dataB[i].timestamp)
  189. found = UA_TRUE;
  190. }
  191. if (found && dataB[i].timestamp == dataB[i].value) {
  192. return false;
  193. }
  194. if (!found && dataB[i].timestamp != dataB[i].value) {
  195. return false;
  196. }
  197. }
  198. return true;
  199. }
  200. static UA_Boolean
  201. receiveCallback(UA_Client *clt,
  202. const UA_NodeId *nodeId,
  203. UA_Boolean moreDataAvailable,
  204. const UA_ExtensionObject *_data,
  205. void *callbackContext) {
  206. UA_HistoryData *data = (UA_HistoryData*)_data->content.decoded.data;
  207. fprintf(stderr, "Received %lu at pos %lu. moreDataAvailable %d. Data: ", (unsigned long)data->dataValuesSize, (unsigned long)receivedTestDataPos, moreDataAvailable);
  208. if (receivedTestDataPos + data->dataValuesSize > receivedDataSize)
  209. return false;
  210. for (size_t i = 0; i < data->dataValuesSize; ++i) {
  211. receivedTestData[i+receivedTestDataPos].timestamp = data->dataValues[i].sourceTimestamp;
  212. receivedTestData[i+receivedTestDataPos].value = *((UA_Int64*)data->dataValues[i].value.data);
  213. fprintf(stderr, "%lld/%lld, ",
  214. (long long)receivedTestData[i+receivedTestDataPos].timestamp,
  215. (long long)receivedTestData[i+receivedTestDataPos].value);
  216. }
  217. fprintf(stderr, "\n");
  218. receivedTestDataPos += data->dataValuesSize;
  219. return true;
  220. }
  221. START_TEST(Client_HistorizingReadRawAll)
  222. {
  223. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  224. &outNodeId,
  225. receiveCallback,
  226. TESTDATA_START_TIME,
  227. TESTDATA_STOP_TIME,
  228. UA_STRING_NULL,
  229. false,
  230. 100,
  231. UA_TIMESTAMPSTORETURN_BOTH,
  232. (void*)false);
  233. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  234. ck_assert_uint_eq(testDataSize, receivedTestDataPos);
  235. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  236. }
  237. END_TEST
  238. START_TEST(Client_HistorizingReadRawOne)
  239. {
  240. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  241. &outNodeId,
  242. receiveCallback,
  243. TESTDATA_START_TIME,
  244. TESTDATA_STOP_TIME,
  245. UA_STRING_NULL,
  246. false,
  247. 1,
  248. UA_TIMESTAMPSTORETURN_BOTH,
  249. (void*)false);
  250. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  251. ck_assert_uint_eq(testDataSize, receivedTestDataPos);
  252. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  253. }
  254. END_TEST
  255. START_TEST(Client_HistorizingReadRawTwo)
  256. {
  257. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  258. &outNodeId,
  259. receiveCallback,
  260. TESTDATA_START_TIME,
  261. TESTDATA_STOP_TIME,
  262. UA_STRING_NULL,
  263. false,
  264. 2,
  265. UA_TIMESTAMPSTORETURN_BOTH,
  266. (void*)false);
  267. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  268. ck_assert_uint_eq(testDataSize, receivedTestDataPos);
  269. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  270. }
  271. END_TEST
  272. START_TEST(Client_HistorizingReadRawAllInv)
  273. {
  274. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  275. &outNodeId,
  276. receiveCallback,
  277. TESTDATA_STOP_TIME,
  278. TESTDATA_START_TIME,
  279. UA_STRING_NULL,
  280. false,
  281. 100,
  282. UA_TIMESTAMPSTORETURN_BOTH,
  283. (void*)true);
  284. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  285. ck_assert_uint_eq(testDataSize, receivedTestDataPos);
  286. ck_assert(checkTestData(true, testData, receivedTestData, testDataSize));
  287. }
  288. END_TEST
  289. START_TEST(Client_HistorizingReadRawOneInv)
  290. {
  291. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  292. &outNodeId,
  293. receiveCallback,
  294. TESTDATA_STOP_TIME,
  295. TESTDATA_START_TIME,
  296. UA_STRING_NULL,
  297. false,
  298. 1,
  299. UA_TIMESTAMPSTORETURN_BOTH,
  300. (void*)true);
  301. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  302. ck_assert_uint_eq(testDataSize, receivedTestDataPos);
  303. ck_assert(checkTestData(true, testData, receivedTestData, testDataSize));
  304. }
  305. END_TEST
  306. START_TEST(Client_HistorizingReadRawTwoInv)
  307. {
  308. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  309. &outNodeId,
  310. receiveCallback,
  311. TESTDATA_STOP_TIME,
  312. TESTDATA_START_TIME,
  313. UA_STRING_NULL,
  314. false,
  315. 2,
  316. UA_TIMESTAMPSTORETURN_BOTH,
  317. (void*)true);
  318. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  319. ck_assert_uint_eq(testDataSize, receivedTestDataPos);
  320. ck_assert(checkTestData(true, testData, receivedTestData, testDataSize));
  321. }
  322. END_TEST
  323. START_TEST(Client_HistorizingInsertRawSuccess)
  324. {
  325. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  326. &outNodeId,
  327. receiveCallback,
  328. TESTDATA_START_TIME,
  329. TESTDATA_STOP_TIME,
  330. UA_STRING_NULL,
  331. false,
  332. 100,
  333. UA_TIMESTAMPSTORETURN_BOTH,
  334. (void*)false);
  335. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  336. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  337. resetReceiveBuffer();
  338. // insert values to the database
  339. for (size_t i = 0; i < testInsertDataSuccessSize; ++i) {
  340. UA_DataValue value;
  341. fillInt64DataValue(testInsertDataSuccess[i], 0, &value);
  342. ret = UA_Client_HistoryUpdate_insert(client, &outNodeId, &value);
  343. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  344. UA_DataValue_deleteMembers(&value);
  345. }
  346. // check result
  347. ret = UA_Client_HistoryRead_raw(client,
  348. &outNodeId,
  349. receiveCallback,
  350. TESTDATA_START_TIME,
  351. TESTDATA_STOP_TIME,
  352. UA_STRING_NULL,
  353. false,
  354. 100,
  355. UA_TIMESTAMPSTORETURN_BOTH,
  356. (void*)false);
  357. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  358. ck_assert_uint_eq(receivedTestDataPos, testInsertResultDataSize);
  359. ck_assert(checkTestData(false, testInsertResultData, receivedTestData, receivedTestDataPos));
  360. ck_assert(checkModifiedData(testInsertDataSuccess, testInsertDataSuccessSize, receivedTestData, receivedTestDataPos));
  361. }
  362. END_TEST
  363. START_TEST(Client_HistorizingReplaceRawSuccess)
  364. {
  365. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  366. &outNodeId,
  367. receiveCallback,
  368. TESTDATA_START_TIME,
  369. TESTDATA_STOP_TIME,
  370. UA_STRING_NULL,
  371. false,
  372. 100,
  373. UA_TIMESTAMPSTORETURN_BOTH,
  374. (void*)false);
  375. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  376. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  377. resetReceiveBuffer();
  378. // replace values to the database
  379. for (size_t i = 0; i < testReplaceDataSuccessSize; ++i) {
  380. UA_DataValue value;
  381. fillInt64DataValue(testReplaceDataSuccess[i], 0, &value);
  382. ret = UA_Client_HistoryUpdate_replace(client, &outNodeId, &value);
  383. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  384. UA_DataValue_deleteMembers(&value);
  385. }
  386. // check result
  387. ret = UA_Client_HistoryRead_raw(client,
  388. &outNodeId,
  389. receiveCallback,
  390. TESTDATA_START_TIME,
  391. TESTDATA_STOP_TIME,
  392. UA_STRING_NULL,
  393. false,
  394. 100,
  395. UA_TIMESTAMPSTORETURN_BOTH,
  396. (void*)false);
  397. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  398. ck_assert_uint_eq(receivedTestDataPos, testDataSize);
  399. ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
  400. ck_assert(checkModifiedData(testReplaceDataSuccess, testReplaceDataSuccessSize, receivedTestData, receivedTestDataPos));
  401. }
  402. END_TEST
  403. START_TEST(Client_HistorizingUpdateRawSuccess)
  404. {
  405. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  406. &outNodeId,
  407. receiveCallback,
  408. TESTDATA_START_TIME,
  409. TESTDATA_STOP_TIME,
  410. UA_STRING_NULL,
  411. false,
  412. 100,
  413. UA_TIMESTAMPSTORETURN_BOTH,
  414. (void*)false);
  415. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  416. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  417. resetReceiveBuffer();
  418. // insert values to the database
  419. for (size_t i = 0; i < testInsertDataSuccessSize; ++i) {
  420. UA_DataValue value;
  421. fillInt64DataValue(testInsertDataSuccess[i], 0, &value);
  422. ret = UA_Client_HistoryUpdate_update(client, &outNodeId, &value);
  423. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOODENTRYINSERTED));
  424. UA_DataValue_deleteMembers(&value);
  425. }
  426. // replace values to the database
  427. for (size_t i = 0; i < testReplaceDataSuccessSize; ++i) {
  428. UA_DataValue value;
  429. fillInt64DataValue(testReplaceDataSuccess[i], 0, &value);
  430. ret = UA_Client_HistoryUpdate_update(client, &outNodeId, &value);
  431. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOODENTRYREPLACED));
  432. UA_DataValue_deleteMembers(&value);
  433. }
  434. // check result
  435. ret = UA_Client_HistoryRead_raw(client,
  436. &outNodeId,
  437. receiveCallback,
  438. TESTDATA_START_TIME,
  439. TESTDATA_STOP_TIME,
  440. UA_STRING_NULL,
  441. false,
  442. 100,
  443. UA_TIMESTAMPSTORETURN_BOTH,
  444. (void*)false);
  445. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  446. ck_assert_uint_eq(receivedTestDataPos, testInsertResultDataSize);
  447. ck_assert(checkTestData(false, testInsertResultData, receivedTestData, receivedTestDataPos));
  448. }
  449. END_TEST
  450. START_TEST(Client_HistorizingDeleteRaw)
  451. {
  452. for (size_t i = 0; i < testDeleteRangeDataSize; ++i) {
  453. fprintf(stderr, "Client_HistorizingDeleteRaw: Testing %lu: {%lld, %lld, %lu, %s}\n",
  454. (unsigned long)i,
  455. (long long)testDeleteRangeData[i].start,
  456. (long long)testDeleteRangeData[i].end,
  457. (unsigned long)testDeleteRangeData[i].historySize,
  458. UA_StatusCode_name(testDeleteRangeData[i].statusCode));
  459. resetReceiveBuffer();
  460. serverBackend.removeDataValue(server,
  461. serverBackend.context,
  462. NULL,
  463. NULL,
  464. &outNodeId,
  465. TESTDATA_START_TIME,
  466. TESTDATA_STOP_TIME);
  467. fillHistoricalDataBackend(serverBackend);
  468. // check result
  469. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  470. &outNodeId,
  471. receiveCallback,
  472. TESTDATA_START_TIME,
  473. TESTDATA_STOP_TIME,
  474. UA_STRING_NULL,
  475. false,
  476. 100,
  477. UA_TIMESTAMPSTORETURN_BOTH,
  478. (void*)false);
  479. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  480. ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
  481. resetReceiveBuffer();
  482. ret = UA_Client_HistoryUpdate_deleteRaw(client,
  483. &outNodeId,
  484. testDeleteRangeData[i].start,
  485. testDeleteRangeData[i].end);
  486. if (ret != testDeleteRangeData[i].statusCode)
  487. fprintf(stderr, "Error: ret %s != statusCode%s\n", UA_StatusCode_name(ret), UA_StatusCode_name(testDeleteRangeData[i].statusCode));
  488. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(testDeleteRangeData[i].statusCode));
  489. // check result
  490. ret = UA_Client_HistoryRead_raw(client,
  491. &outNodeId,
  492. receiveCallback,
  493. TESTDATA_START_TIME,
  494. TESTDATA_STOP_TIME,
  495. UA_STRING_NULL,
  496. false,
  497. 100,
  498. UA_TIMESTAMPSTORETURN_BOTH,
  499. (void*)false);
  500. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  501. if (receivedTestDataPos != testDeleteRangeData[i].historySize)
  502. fprintf(stderr, "Error: receivedTestDataPos != testDeleteRangeData[i].historySize\n");
  503. ck_assert_uint_eq(receivedTestDataPos, testDeleteRangeData[i].historySize);
  504. }
  505. }
  506. END_TEST
  507. START_TEST(Client_HistorizingInsertRawFail)
  508. {
  509. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  510. &outNodeId,
  511. receiveCallback,
  512. TESTDATA_START_TIME,
  513. TESTDATA_STOP_TIME,
  514. UA_STRING_NULL,
  515. false,
  516. 100,
  517. UA_TIMESTAMPSTORETURN_BOTH,
  518. (void*)false);
  519. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  520. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  521. resetReceiveBuffer();
  522. // insert values to the database
  523. for (size_t i = 0; i < testReplaceDataSuccessSize; ++i) {
  524. UA_DataValue value;
  525. fillInt64DataValue(testReplaceDataSuccess[i], 0, &value);
  526. ret = UA_Client_HistoryUpdate_insert(client, &outNodeId, &value);
  527. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_BADENTRYEXISTS));
  528. UA_DataValue_deleteMembers(&value);
  529. }
  530. // check result
  531. ret = UA_Client_HistoryRead_raw(client,
  532. &outNodeId,
  533. receiveCallback,
  534. TESTDATA_START_TIME,
  535. TESTDATA_STOP_TIME,
  536. UA_STRING_NULL,
  537. false,
  538. 100,
  539. UA_TIMESTAMPSTORETURN_BOTH,
  540. (void*)false);
  541. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  542. ck_assert_uint_eq(receivedTestDataPos, testDataSize);
  543. ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
  544. ck_assert(checkModifiedData(NULL, 0, receivedTestData, receivedTestDataPos));
  545. }
  546. END_TEST
  547. START_TEST(Client_HistorizingReplaceRawFail)
  548. {
  549. UA_StatusCode ret = UA_Client_HistoryRead_raw(client,
  550. &outNodeId,
  551. receiveCallback,
  552. TESTDATA_START_TIME,
  553. TESTDATA_STOP_TIME,
  554. UA_STRING_NULL,
  555. false,
  556. 100,
  557. UA_TIMESTAMPSTORETURN_BOTH,
  558. (void*)false);
  559. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  560. ck_assert(checkTestData(false, testData, receivedTestData, testDataSize));
  561. resetReceiveBuffer();
  562. // replace values to the database
  563. for (size_t i = 0; i < testInsertDataSuccessSize; ++i) {
  564. UA_DataValue value;
  565. fillInt64DataValue(testInsertDataSuccess[i], 0, &value);
  566. ret = UA_Client_HistoryUpdate_replace(client, &outNodeId, &value);
  567. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_BADNOENTRYEXISTS));
  568. UA_DataValue_deleteMembers(&value);
  569. }
  570. // check result
  571. ret = UA_Client_HistoryRead_raw(client,
  572. &outNodeId,
  573. receiveCallback,
  574. TESTDATA_START_TIME,
  575. TESTDATA_STOP_TIME,
  576. UA_STRING_NULL,
  577. false,
  578. 100,
  579. UA_TIMESTAMPSTORETURN_BOTH,
  580. (void*)false);
  581. ck_assert_str_eq(UA_StatusCode_name(ret), UA_StatusCode_name(UA_STATUSCODE_GOOD));
  582. ck_assert_uint_eq(receivedTestDataPos, testDataSize);
  583. ck_assert(checkTestData(false, testData, receivedTestData, receivedTestDataPos));
  584. ck_assert(checkModifiedData(NULL, 0, receivedTestData, receivedTestDataPos));
  585. }
  586. END_TEST
  587. #endif /*UA_ENABLE_HISTORIZING*/
  588. static Suite* testSuite_Client(void)
  589. {
  590. Suite *s = suite_create("Client Historical Data");
  591. TCase *tc_client = tcase_create("Client Historical Data read_raw");
  592. tcase_add_checked_fixture(tc_client, setup, teardown);
  593. #ifdef UA_ENABLE_HISTORIZING
  594. tcase_add_test(tc_client, Client_HistorizingReadRawAll);
  595. tcase_add_test(tc_client, Client_HistorizingReadRawOne);
  596. tcase_add_test(tc_client, Client_HistorizingReadRawTwo);
  597. tcase_add_test(tc_client, Client_HistorizingReadRawAllInv);
  598. tcase_add_test(tc_client, Client_HistorizingReadRawOneInv);
  599. tcase_add_test(tc_client, Client_HistorizingReadRawTwoInv);
  600. tcase_add_test(tc_client, Client_HistorizingInsertRawSuccess);
  601. tcase_add_test(tc_client, Client_HistorizingReplaceRawSuccess);
  602. tcase_add_test(tc_client, Client_HistorizingUpdateRawSuccess);
  603. tcase_add_test(tc_client, Client_HistorizingDeleteRaw);
  604. tcase_add_test(tc_client, Client_HistorizingInsertRawFail);
  605. tcase_add_test(tc_client, Client_HistorizingReplaceRawFail);
  606. #endif /* UA_ENABLE_HISTORIZING */
  607. suite_add_tcase(s, tc_client);
  608. return s;
  609. }
  610. int main(void)
  611. {
  612. Suite *s = testSuite_Client();
  613. SRunner *sr = srunner_create(s);
  614. srunner_set_fork_status(sr, CK_NOFORK);
  615. srunner_run_all(sr,CK_NORMAL);
  616. int number_failed = srunner_ntests_failed(sr);
  617. srunner_free(sr);
  618. return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  619. }