check_client_historical_data.c 30 KB

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