check_client_historical_data.c 30 KB

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