handle.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*! ========================================================================
  2. ** Extended Template and Library Test Suite
  3. ** Handle Template Class Test
  4. **
  5. ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
  6. **
  7. ** This package is free software; you can redistribute it and/or
  8. ** modify it under the terms of the GNU General Public License as
  9. ** published by the Free Software Foundation; either version 2 of
  10. ** the License, or (at your option) any later version.
  11. **
  12. ** This package is distributed in the hope that it will be useful,
  13. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. ** General Public License for more details.
  16. **
  17. ** === N O T E S ===========================================================
  18. **
  19. ** ========================================================================= */
  20. #include <ETL/handle>
  21. #include <list>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string>
  25. #include <map>
  26. #include <vector>
  27. #define NUMBER_OF_OBJECTS 40000
  28. using namespace std;
  29. struct my_test_obj : public etl::rshared_object {
  30. static int instance_count;
  31. int my_id;
  32. my_test_obj(int my_id = 0): my_id(my_id)
  33. {
  34. instance_count++;
  35. }
  36. virtual ~my_test_obj()
  37. {
  38. if (instance_count == 0) {
  39. printf("Error, instance count is going past zero!\n");
  40. }
  41. instance_count--;
  42. }
  43. bool operator<(const my_test_obj &rhs)const
  44. {
  45. return my_id < rhs.my_id;
  46. }
  47. };
  48. struct my_other_test_obj : public my_test_obj {
  49. static int instance_count;
  50. my_other_test_obj(int my_id = 0): my_test_obj(my_id)
  51. {
  52. instance_count++;
  53. }
  54. virtual ~my_other_test_obj()
  55. {
  56. if (instance_count == 0) {
  57. printf("Error, instance count is going past zero!\n");
  58. }
  59. instance_count--;
  60. }
  61. };
  62. int my_test_obj::instance_count = 0;
  63. int my_other_test_obj::instance_count = 0;
  64. typedef etl::handle<my_test_obj> obj_handle;
  65. typedef etl::rhandle<my_test_obj> robj_handle;
  66. typedef etl::handle<my_other_test_obj> other_obj_handle;
  67. typedef list< obj_handle > obj_list;
  68. typedef list< other_obj_handle > other_obj_list;
  69. typedef list< robj_handle > robj_list;
  70. int handle_basic_test()
  71. {
  72. printf("handle: Size of a handle: %u\n", (unsigned int)sizeof(etl::handle<int>));
  73. printf("handle: Size of a loose_handle: %u\n", (unsigned int)sizeof(etl::loose_handle<int>));
  74. printf("handle: Size of a rhandle: %u\n", (unsigned int)sizeof(etl::rhandle<int>));
  75. printf("handle: Size of a shared_object: %u\n", (unsigned int)sizeof(etl::shared_object));
  76. printf("handle: Size of a rshared_object: %u\n", (unsigned int)sizeof(etl::rshared_object));
  77. printf("handle: Basic test: ");
  78. my_test_obj::instance_count = 0;
  79. {
  80. etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
  81. }
  82. if (my_test_obj::instance_count != 0) {
  83. printf("FAILED!\n");
  84. printf(__FILE__":%d: on create/destroy, instance count=%d, should be zero.\n", __LINE__, my_test_obj::instance_count);
  85. return 1;
  86. }
  87. {
  88. map<string, etl::handle<my_test_obj> > my_map;
  89. etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
  90. my_map["bleh"] = obj_handle;
  91. }
  92. if (my_test_obj::instance_count != 0) {
  93. printf("FAILED!\n");
  94. printf(__FILE__":%d: on create/destroy, instance count=%d, should be zero.\n", __LINE__, my_test_obj::instance_count);
  95. return 1;
  96. }
  97. etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
  98. if (obj_handle != obj_handle.constant()) {
  99. printf("FAILED!\n");
  100. printf(__FILE__":%d: on call to handle<>::constant().\n", __LINE__);
  101. return 1;
  102. }
  103. printf("PASSED\n");
  104. return 0;
  105. }
  106. int handle_general_use_test(void)
  107. {
  108. printf("handle: General-use test: ");
  109. my_test_obj::instance_count = 0;
  110. obj_list my_list, my_other_list;
  111. int i;
  112. for (i = 0; i < NUMBER_OF_OBJECTS; i++) {
  113. my_list.push_back(obj_handle(new my_test_obj(rand())));
  114. }
  115. my_other_list = my_list;
  116. if (my_test_obj::instance_count != NUMBER_OF_OBJECTS) {
  117. printf("FAILED!\n");
  118. printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n", __LINE__, my_test_obj::instance_count, NUMBER_OF_OBJECTS);
  119. return 1;
  120. }
  121. my_list.sort();
  122. if (my_test_obj::instance_count != NUMBER_OF_OBJECTS) {
  123. printf("FAILED!\n");
  124. printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n", __LINE__, my_test_obj::instance_count, NUMBER_OF_OBJECTS);
  125. return 1;
  126. }
  127. my_list.clear();
  128. if (my_test_obj::instance_count != NUMBER_OF_OBJECTS) {
  129. printf("FAILED!\n");
  130. printf(__FILE__":%d: On copy's clear, instance count=%d, should be %d.\n", __LINE__, my_test_obj::instance_count, NUMBER_OF_OBJECTS);
  131. return 1;
  132. }
  133. {
  134. obj_handle a(new my_test_obj(27)), b(new my_test_obj(42));
  135. a.swap(b);
  136. if (a->my_id != 42 || b->my_id != 27) {
  137. printf("FAILED!\n");
  138. printf(__FILE__":%d: On swap (27,42) gave (%d,%d), should be (42,27).\n", __LINE__, a->my_id, b->my_id);
  139. return 1;
  140. }
  141. }
  142. my_other_list.clear();
  143. if (my_test_obj::instance_count) {
  144. printf("FAILED!\n");
  145. printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n", __LINE__, my_test_obj::instance_count);
  146. return 1;
  147. }
  148. printf("PASSED\n");
  149. return 0;
  150. }
  151. struct ListItem {
  152. robj_handle obj;
  153. int bleh;
  154. int blah;
  155. ListItem(robj_handle obj, int bleh = 1, int blah = 2):
  156. obj(obj), bleh(bleh), blah(blah) { }
  157. };
  158. int rhandle_general_use_test(void)
  159. {
  160. printf("rhandle: General-use test: ");
  161. my_test_obj::instance_count = 0;
  162. robj_list my_list;
  163. int i;
  164. robj_handle obj = new my_test_obj(rand());
  165. for (i = 0; i < NUMBER_OF_OBJECTS; i++) {
  166. my_list.push_back(obj);
  167. }
  168. obj_list my_other_list(my_list.begin(), my_list.end());
  169. if (obj.count() != NUMBER_OF_OBJECTS * 2 + 1) {
  170. printf("FAILED!\n");
  171. printf(__FILE__":%d: On copy, handle count=%d, should be %d.\n", __LINE__, obj.count(), NUMBER_OF_OBJECTS * 2 + 1);
  172. return 1;
  173. }
  174. if (obj.rcount() != NUMBER_OF_OBJECTS + 1) {
  175. printf("FAILED!\n");
  176. printf(__FILE__":%d: On copy, rhandle count=%d, should be %d.\n", __LINE__, obj.rcount(), NUMBER_OF_OBJECTS + 1);
  177. return 1;
  178. }
  179. my_list.sort();
  180. if (obj.rcount() != NUMBER_OF_OBJECTS + 1) {
  181. printf("FAILED!\n");
  182. printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n", __LINE__, obj.rcount(), NUMBER_OF_OBJECTS + 1);
  183. return 1;
  184. }
  185. {
  186. robj_handle bleh(obj);
  187. }
  188. if (obj.rcount() != NUMBER_OF_OBJECTS + 1) {
  189. printf("FAILED!\n");
  190. printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n", __LINE__, obj.rcount(), NUMBER_OF_OBJECTS + 1);
  191. return 1;
  192. }
  193. my_other_list.clear();
  194. if (obj.rcount() != obj.count()) {
  195. printf("FAILED!\n");
  196. printf(__FILE__":%d: On copy's clear, handle count (%d) != rhandle count (%d)\n", __LINE__, obj.count(), obj.rcount());
  197. return 1;
  198. }
  199. if (obj.rcount() != NUMBER_OF_OBJECTS + 1) {
  200. printf("FAILED!\n");
  201. printf(__FILE__":%d: On copy's clear, instance count=%d, should be %d.\n", __LINE__, obj.rcount(), NUMBER_OF_OBJECTS + 1);
  202. return 1;
  203. }
  204. robj_handle new_obj = new my_test_obj(rand());
  205. int replacements = obj.replace(new_obj);
  206. if (replacements != NUMBER_OF_OBJECTS + 1) {
  207. printf("FAILED!\n");
  208. printf(__FILE__":%d: Only managed to replace %d, should have replaced %d\n", __LINE__, replacements, NUMBER_OF_OBJECTS + 1);
  209. return 1;
  210. }
  211. if (obj != new_obj) {
  212. printf("FAILED!\n");
  213. printf(__FILE__":%d: On replace, handles should be equal.\n", __LINE__);
  214. return 1;
  215. }
  216. {
  217. robj_handle bleh(obj);
  218. robj_handle blah(obj.get());
  219. }
  220. my_list.clear();
  221. obj.detach();
  222. new_obj.detach();
  223. if (my_test_obj::instance_count) {
  224. printf("FAILED!\n");
  225. printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n", __LINE__, my_test_obj::instance_count);
  226. return 1;
  227. }
  228. std::vector<ListItem> my_item_list;
  229. for (i = 0; i < NUMBER_OF_OBJECTS; i++) {
  230. my_item_list.push_back(ListItem(new my_test_obj(rand()), 3, 4));
  231. }
  232. for (i = 0; i < 100; i++) {
  233. int src, dest;
  234. src = rand() % NUMBER_OF_OBJECTS;
  235. dest = rand() % NUMBER_OF_OBJECTS;
  236. ListItem tmp(my_item_list[src]);
  237. assert(tmp.obj.rcount() >= 2);
  238. my_item_list.erase(my_item_list.begin() + src);
  239. assert(tmp.obj.rcount() >= 1);
  240. my_item_list.insert(my_item_list.begin() + dest, tmp);
  241. assert(tmp.obj.rcount() >= 2);
  242. }
  243. my_item_list.clear();
  244. if (my_test_obj::instance_count) {
  245. printf("FAILED!\n");
  246. printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n", __LINE__, my_test_obj::instance_count);
  247. return 1;
  248. }
  249. printf("PASSED\n");
  250. return 0;
  251. }
  252. int handle_inheritance_test(void)
  253. {
  254. printf("handle: Inheritance test: ");
  255. my_test_obj::instance_count = 0;
  256. my_other_test_obj::instance_count = 0;
  257. other_obj_list my_other_list;
  258. int i;
  259. for (i = 0; i < NUMBER_OF_OBJECTS; i++) {
  260. my_other_list.push_back(other_obj_handle(new my_other_test_obj(rand())));
  261. }
  262. obj_list my_list(my_other_list.begin(), my_other_list.end());
  263. if (my_test_obj::instance_count != NUMBER_OF_OBJECTS) {
  264. printf("FAILED!\n");
  265. printf(__FILE__":%d: On copy, instance count=%d, should be %d.\n", __LINE__, my_test_obj::instance_count, NUMBER_OF_OBJECTS);
  266. return 1;
  267. }
  268. for (i = 0; i < NUMBER_OF_OBJECTS; i++) {
  269. my_list.push_back(other_obj_handle(new my_other_test_obj(rand())));
  270. }
  271. if (my_other_test_obj::instance_count != NUMBER_OF_OBJECTS * 2 ||
  272. my_test_obj::instance_count != my_other_test_obj::instance_count) {
  273. printf("FAILED!\n");
  274. printf(__FILE__":%d: On inherited copy, instance count=%d, should be %d.\n", __LINE__, my_test_obj::instance_count, NUMBER_OF_OBJECTS * 2);
  275. return 1;
  276. }
  277. my_list.sort();
  278. my_other_list.sort();
  279. if (my_test_obj::instance_count != NUMBER_OF_OBJECTS * 2) {
  280. printf("FAILED!\n");
  281. printf(__FILE__":%d: On sort, instance count=%d, should be %d.\n", __LINE__, my_test_obj::instance_count, NUMBER_OF_OBJECTS * 2);
  282. return 1;
  283. }
  284. my_list.clear();
  285. if (my_test_obj::instance_count != NUMBER_OF_OBJECTS) {
  286. printf("FAILED!\n");
  287. printf(__FILE__":%d: On clear, instance count=%d, should be %d.\n", __LINE__, my_test_obj::instance_count, NUMBER_OF_OBJECTS);
  288. return 1;
  289. }
  290. my_other_list.clear();
  291. if (my_test_obj::instance_count) {
  292. printf("FAILED!\n");
  293. printf(__FILE__":%d: On clear, instance count=%d, should be zero.\n", __LINE__, my_test_obj::instance_count);
  294. return 1;
  295. }
  296. printf("PASSED\n");
  297. return 0;
  298. }
  299. void test_func(etl::handle<my_test_obj> handle)
  300. {
  301. if (handle) {
  302. int i = handle.count();
  303. i++;
  304. }
  305. }
  306. int loose_handle_test(void)
  307. {
  308. printf("handle: loose_handle test: ");
  309. my_test_obj::instance_count = 0;
  310. etl::loose_handle<my_test_obj> obj_handle_loose;
  311. etl::handle<my_test_obj> obj_handle2;
  312. {
  313. etl::handle<my_test_obj> obj_handle(new my_test_obj(rand()));
  314. if (my_test_obj::instance_count != 1) {
  315. printf("FAILED!\n");
  316. printf(__FILE__":%d: on handle assignment from new object, instance count=%d, should be 1.\n", __LINE__, my_test_obj::instance_count);
  317. return 1;
  318. }
  319. obj_handle_loose = obj_handle;
  320. if (obj_handle != obj_handle_loose) {
  321. printf("FAILED!\n");
  322. printf(__FILE__":%d: on loose_handle assignment\n", __LINE__);
  323. return 1;
  324. }
  325. obj_handle2 = obj_handle_loose;
  326. if (my_test_obj::instance_count != 1) {
  327. printf("FAILED!\n");
  328. printf(__FILE__":%d: on handle assignment from loose_handle, instance count=%d, should be 1.\n", __LINE__, my_test_obj::instance_count);
  329. return 1;
  330. }
  331. test_func(obj_handle_loose);
  332. if (my_test_obj::instance_count != 1) {
  333. printf("FAILED!\n");
  334. printf(__FILE__":%d: on handle assignment from loose_handle, instance count=%d, should be 1.\n", __LINE__, my_test_obj::instance_count);
  335. return 1;
  336. }
  337. }
  338. {
  339. etl::loose_handle<my_test_obj> a(new my_test_obj(27)), b(new my_test_obj(42));
  340. a.swap(b);
  341. if (a->my_id != 42 || b->my_id != 27) {
  342. printf("FAILED!\n");
  343. printf(__FILE__":%d: on loose_handle swap (27,42) gave (%d,%d), should be (42,27).\n", __LINE__, a->my_id, b->my_id);
  344. return 1;
  345. }
  346. }
  347. if (my_test_obj::instance_count != 3) {
  348. printf("FAILED!\n");
  349. printf(__FILE__":%d: on create/destroy, instance count=%d, should be 3.\n", __LINE__, my_test_obj::instance_count);
  350. return 1;
  351. }
  352. printf("PASSED\n");
  353. return 0;
  354. }
  355. int handle_cast_test()
  356. {
  357. printf("handle: casting test: ");
  358. etl::handle<my_test_obj> obj;
  359. etl::handle<my_other_test_obj> other_obj;
  360. etl::loose_handle<my_other_test_obj> loose_obj;
  361. other_obj.spawn();
  362. loose_obj = other_obj;
  363. obj = etl::handle<my_test_obj>::cast_dynamic(loose_obj);
  364. if (obj != other_obj) {
  365. printf("FAILED!\n");
  366. printf(__FILE__":%d: on handle assignment from loose_handle.\n", __LINE__);
  367. return 1;
  368. }
  369. printf("PASSED\n");
  370. return 0;
  371. }
  372. int main()
  373. {
  374. int error = 0;
  375. error += handle_basic_test();
  376. error += handle_cast_test();
  377. error += handle_general_use_test();
  378. error += handle_inheritance_test();
  379. error += loose_handle_test();
  380. error += rhandle_general_use_test();
  381. return error;
  382. }