check_client_historical_data.c 30 KB

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