/CSipSimple/jni/webrtc/sources/system_wrappers/source/list_unittest.cc

https://bitbucket.org/bohlooli/csipsimple2 · C++ · 479 lines · 406 code · 43 blank · 30 comment · 90 complexity · 9a4dff992d2cda4eebf9e6dc8deb4190 MD5 · raw file

  1. /*
  2. * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include "gtest/gtest.h"
  11. #include "system_wrappers/interface/list_wrapper.h"
  12. #include "system_wrappers/interface/scoped_ptr.h"
  13. using ::webrtc::ListWrapper;
  14. using ::webrtc::ListItem;
  15. using ::webrtc::scoped_ptr;
  16. // Note: kNumberOfElements needs to be even.
  17. const unsigned int kNumberOfElements = 10;
  18. // An opaque implementation of dynamic or statically allocated unsigned ints.
  19. // This class makes it possible to use the exact same code for testing of both
  20. // the dynamic and static implementation of ListWrapper.
  21. // Clarification: ListWrapper has two versions of PushBack(..). It takes an
  22. // unsigned integer or a void pointer. The integer implementation takes care
  23. // of memory management. The void pointer version expect the caller to manage
  24. // the memory associated with the void pointer.
  25. // This class works like the integer version but can be implemented on top of
  26. // either the integer version or void pointer version of ListWrapper.
  27. // Note: the non-virtual fuctions behave the same for both versions.
  28. class ListWrapperSimple {
  29. public:
  30. static ListWrapperSimple* Create(bool static_allocation);
  31. virtual ~ListWrapperSimple() {}
  32. // These three functions should be used for manipulating ListItems so that
  33. // they are the type corresponding to the underlying implementation.
  34. virtual unsigned int GetUnsignedItem(
  35. const ListItem* item) const = 0;
  36. virtual ListItem* CreateListItem(unsigned int item_id) = 0;
  37. unsigned int GetSize() const {
  38. return list_.GetSize();
  39. }
  40. virtual int PushBack(const unsigned int item_id) = 0;
  41. virtual int PushFront(const unsigned int item_id) = 0;
  42. virtual int PopFront() = 0;
  43. virtual int PopBack() = 0;
  44. bool Empty() const {
  45. return list_.Empty();
  46. }
  47. ListItem* First() const {
  48. return list_.First();
  49. }
  50. ListItem* Last() const {
  51. return list_.Last();
  52. }
  53. ListItem* Next(ListItem* item) const {
  54. return list_.Next(item);
  55. }
  56. ListItem* Previous(ListItem* item) const {
  57. return list_.Previous(item);
  58. }
  59. virtual int Erase(ListItem* item) = 0;
  60. int Insert(ListItem* existing_previous_item,
  61. ListItem* new_item) {
  62. const int retval = list_.Insert(existing_previous_item, new_item);
  63. if (retval != 0) {
  64. EXPECT_TRUE(DestroyListItem(new_item));
  65. }
  66. return retval;
  67. }
  68. int InsertBefore(ListItem* existing_next_item,
  69. ListItem* new_item) {
  70. const int retval = list_.InsertBefore(existing_next_item, new_item);
  71. if (retval != 0) {
  72. EXPECT_TRUE(DestroyListItem(new_item));
  73. }
  74. return retval;
  75. }
  76. protected:
  77. ListWrapperSimple() {}
  78. virtual bool DestroyListItemContent(ListItem* item) = 0;
  79. bool DestroyListItem(ListItem* item) {
  80. const bool retval = DestroyListItemContent(item);
  81. delete item;
  82. return retval;
  83. }
  84. ListWrapper list_;
  85. };
  86. void ClearList(ListWrapperSimple* list_wrapper) {
  87. if (list_wrapper == NULL) {
  88. return;
  89. }
  90. ListItem* list_item = list_wrapper->First();
  91. while (list_item != NULL) {
  92. EXPECT_EQ(list_wrapper->Erase(list_item), 0);
  93. list_item = list_wrapper->First();
  94. }
  95. }
  96. class ListWrapperStatic : public ListWrapperSimple {
  97. public:
  98. ListWrapperStatic() {}
  99. virtual ~ListWrapperStatic() {
  100. ClearList(this);
  101. }
  102. virtual unsigned int GetUnsignedItem(const ListItem* item) const {
  103. return item->GetUnsignedItem();
  104. }
  105. virtual ListItem* CreateListItem(unsigned int item_id) {
  106. return new ListItem(item_id);
  107. }
  108. virtual bool DestroyListItemContent(ListItem* item) {
  109. return true;
  110. }
  111. virtual int PushBack(const unsigned int item_id) {
  112. return list_.PushBack(item_id);
  113. }
  114. virtual int PushFront(const unsigned int item_id) {
  115. return list_.PushFront(item_id);
  116. }
  117. virtual int PopFront() {
  118. return list_.PopFront();
  119. }
  120. virtual int PopBack() {
  121. return list_.PopBack();
  122. }
  123. virtual int Erase(ListItem* item) {
  124. return list_.Erase(item);
  125. }
  126. };
  127. class ListWrapperDynamic : public ListWrapperSimple {
  128. public:
  129. ListWrapperDynamic() {}
  130. virtual ~ListWrapperDynamic() {
  131. ClearList(this);
  132. }
  133. virtual unsigned int GetUnsignedItem(const ListItem* item) const {
  134. const unsigned int* return_value_pointer =
  135. reinterpret_cast<unsigned int*> (item->GetItem());
  136. if (return_value_pointer == NULL) {
  137. return -1;
  138. }
  139. return *return_value_pointer;
  140. }
  141. virtual ListItem* CreateListItem(unsigned int item_id) {
  142. unsigned int* item_id_pointer = new unsigned int;
  143. if (item_id_pointer == NULL) {
  144. return NULL;
  145. }
  146. *item_id_pointer = item_id;
  147. ListItem* return_value = new ListItem(
  148. reinterpret_cast<void*>(item_id_pointer));
  149. if (return_value == NULL) {
  150. delete item_id_pointer;
  151. return NULL;
  152. }
  153. return return_value;
  154. }
  155. virtual bool DestroyListItemContent(ListItem* item) {
  156. if (item == NULL) {
  157. return false;
  158. }
  159. bool return_value = false;
  160. unsigned int* item_id_ptr = reinterpret_cast<unsigned int*>(
  161. item->GetItem());
  162. if (item_id_ptr != NULL) {
  163. return_value = true;
  164. delete item_id_ptr;
  165. }
  166. return return_value;
  167. }
  168. virtual int PushBack(const unsigned int item_id) {
  169. unsigned int* item_id_ptr = new unsigned int;
  170. if (item_id_ptr == NULL) {
  171. return -1;
  172. }
  173. *item_id_ptr = item_id;
  174. const int return_value = list_.PushBack(
  175. reinterpret_cast<void*>(item_id_ptr));
  176. if (return_value != 0) {
  177. delete item_id_ptr;
  178. }
  179. return return_value;
  180. }
  181. virtual int PushFront(const unsigned int item_id) {
  182. unsigned int* item_id_ptr = new unsigned int;
  183. if (item_id_ptr == NULL) {
  184. return -1;
  185. }
  186. *item_id_ptr = item_id;
  187. const int return_value = list_.PushFront(
  188. reinterpret_cast<void*>(item_id_ptr));
  189. if (return_value != 0) {
  190. delete item_id_ptr;
  191. }
  192. return return_value;
  193. }
  194. virtual int PopFront() {
  195. return Erase(list_.First());
  196. }
  197. virtual int PopBack() {
  198. return Erase(list_.Last());
  199. }
  200. virtual int Erase(ListItem* item) {
  201. if (item == NULL) {
  202. return -1;
  203. }
  204. int retval = 0;
  205. if (!DestroyListItemContent(item)) {
  206. retval = -1;
  207. ADD_FAILURE();
  208. }
  209. if (list_.Erase(item) != 0) {
  210. retval = -1;
  211. }
  212. return retval;
  213. }
  214. };
  215. ListWrapperSimple* ListWrapperSimple::Create(bool static_allocation) {
  216. if(static_allocation)
  217. {
  218. return new ListWrapperStatic();
  219. }
  220. return new ListWrapperDynamic();
  221. }
  222. ListWrapperSimple* CreateAscendingList(bool static_allocation) {
  223. ListWrapperSimple* return_value = ListWrapperSimple::Create(
  224. static_allocation);
  225. if (return_value == NULL) {
  226. return NULL;
  227. }
  228. for (unsigned int i = 0; i < kNumberOfElements; ++i) {
  229. if (return_value->PushBack(i) == -1) {
  230. ClearList(return_value);
  231. delete return_value;
  232. return NULL;
  233. }
  234. }
  235. return return_value;
  236. }
  237. ListWrapperSimple* CreateDescendingList(bool static_allocation) {
  238. ListWrapperSimple* return_value = ListWrapperSimple::Create(
  239. static_allocation);
  240. if (return_value == NULL) {
  241. return NULL;
  242. }
  243. for (unsigned int i = 0; i < kNumberOfElements; ++i) {
  244. if (return_value->PushBack(kNumberOfElements - i - 1) == -1) {
  245. ClearList(return_value);
  246. delete return_value;
  247. return NULL;
  248. }
  249. }
  250. return return_value;
  251. }
  252. // [0,kNumberOfElements - 1,1,kNumberOfElements - 2,...] (this is why
  253. // kNumberOfElements need to be even)
  254. ListWrapperSimple* CreateInterleavedList(bool static_allocation) {
  255. ListWrapperSimple* return_value = ListWrapperSimple::Create(
  256. static_allocation);
  257. if (return_value == NULL) {
  258. return NULL;
  259. }
  260. unsigned int uneven_count = 0;
  261. unsigned int even_count = 0;
  262. for (unsigned int i = 0; i < kNumberOfElements; i++) {
  263. unsigned int push_value = 0;
  264. if ((i % 2) == 0) {
  265. push_value = even_count;
  266. even_count++;
  267. } else {
  268. push_value = kNumberOfElements - uneven_count - 1;
  269. uneven_count++;
  270. }
  271. if (return_value->PushBack(push_value) == -1) {
  272. ClearList(return_value);
  273. delete return_value;
  274. return NULL;
  275. }
  276. }
  277. return return_value;
  278. }
  279. void PrintList(const ListWrapperSimple* list) {
  280. ListItem* list_item = list->First();
  281. printf("[");
  282. while (list_item != NULL)
  283. {
  284. printf("%3u", list->GetUnsignedItem(list_item));
  285. list_item = list->Next(list_item);
  286. }
  287. printf("]\n");
  288. }
  289. bool CompareLists(const ListWrapperSimple* lhs, const ListWrapperSimple* rhs) {
  290. const unsigned int list_size = lhs->GetSize();
  291. if (lhs->GetSize() != rhs->GetSize()) {
  292. return false;
  293. }
  294. if (lhs->Empty()) {
  295. return rhs->Empty();
  296. }
  297. unsigned int i = 0;
  298. ListItem* lhs_item = lhs->First();
  299. ListItem* rhs_item = rhs->First();
  300. while (i < list_size) {
  301. if (lhs_item == NULL) {
  302. return false;
  303. }
  304. if (rhs_item == NULL) {
  305. return false;
  306. }
  307. if (lhs->GetUnsignedItem(lhs_item) != rhs->GetUnsignedItem(rhs_item)) {
  308. return false;
  309. }
  310. i++;
  311. lhs_item = lhs->Next(lhs_item);
  312. rhs_item = rhs->Next(rhs_item);
  313. }
  314. return true;
  315. }
  316. TEST(ListWrapperTest,ReverseNewIntList) {
  317. // Create a new temporary list with elements reversed those of
  318. // new_int_list_
  319. const scoped_ptr<ListWrapperSimple> descending_list(
  320. CreateDescendingList(rand()%2));
  321. ASSERT_FALSE(descending_list.get() == NULL);
  322. ASSERT_FALSE(descending_list->Empty());
  323. ASSERT_EQ(kNumberOfElements,descending_list->GetSize());
  324. const scoped_ptr<ListWrapperSimple> ascending_list(
  325. CreateAscendingList(rand()%2));
  326. ASSERT_FALSE(ascending_list.get() == NULL);
  327. ASSERT_FALSE(ascending_list->Empty());
  328. ASSERT_EQ(kNumberOfElements,ascending_list->GetSize());
  329. scoped_ptr<ListWrapperSimple> list_to_reverse(
  330. ListWrapperSimple::Create(rand()%2));
  331. // Reverse the list using PushBack and Previous.
  332. for (ListItem* item = ascending_list->Last(); item != NULL;
  333. item = ascending_list->Previous(item)) {
  334. list_to_reverse->PushBack(ascending_list->GetUnsignedItem(item));
  335. }
  336. ASSERT_TRUE(CompareLists(descending_list.get(), list_to_reverse.get()));
  337. scoped_ptr<ListWrapperSimple> list_to_un_reverse(
  338. ListWrapperSimple::Create(rand()%2));
  339. ASSERT_FALSE(list_to_un_reverse.get() == NULL);
  340. // Reverse the reversed list using PushFront and Next.
  341. for (ListItem* item = list_to_reverse->First(); item != NULL;
  342. item = list_to_reverse->Next(item)) {
  343. list_to_un_reverse->PushFront(list_to_reverse->GetUnsignedItem(item));
  344. }
  345. ASSERT_TRUE(CompareLists(ascending_list.get(), list_to_un_reverse.get()));
  346. }
  347. TEST(ListWrapperTest,PopTest) {
  348. scoped_ptr<ListWrapperSimple> ascending_list(CreateAscendingList(rand()%2));
  349. ASSERT_FALSE(ascending_list.get() == NULL);
  350. ASSERT_FALSE(ascending_list->Empty());
  351. EXPECT_EQ(0, ascending_list->PopFront());
  352. EXPECT_EQ(1U, ascending_list->GetUnsignedItem(ascending_list->First()));
  353. EXPECT_EQ(0, ascending_list->PopBack());
  354. EXPECT_EQ(kNumberOfElements - 2, ascending_list->GetUnsignedItem(
  355. ascending_list->Last()));
  356. EXPECT_EQ(kNumberOfElements - 2, ascending_list->GetSize());
  357. }
  358. // Use Insert to interleave two lists.
  359. TEST(ListWrapperTest,InterLeaveTest) {
  360. scoped_ptr<ListWrapperSimple> interleave_list(
  361. CreateAscendingList(rand()%2));
  362. ASSERT_FALSE(interleave_list.get() == NULL);
  363. ASSERT_FALSE(interleave_list->Empty());
  364. scoped_ptr<ListWrapperSimple> descending_list(
  365. CreateDescendingList(rand()%2));
  366. ASSERT_FALSE(descending_list.get() == NULL);
  367. for (unsigned int i = 0; i < kNumberOfElements/2; ++i) {
  368. ASSERT_EQ(0, interleave_list->PopBack());
  369. ASSERT_EQ(0, descending_list->PopBack());
  370. }
  371. ASSERT_EQ(kNumberOfElements/2, interleave_list->GetSize());
  372. ASSERT_EQ(kNumberOfElements/2, descending_list->GetSize());
  373. unsigned int insert_position = kNumberOfElements/2;
  374. ASSERT_EQ(insert_position * 2, kNumberOfElements);
  375. while (!descending_list->Empty())
  376. {
  377. ListItem* item = descending_list->Last();
  378. ASSERT_FALSE(item == NULL);
  379. const unsigned int item_id = descending_list->GetUnsignedItem(item);
  380. ASSERT_EQ(0, descending_list->Erase(item));
  381. ListItem* insert_item = interleave_list->CreateListItem(item_id);
  382. ASSERT_FALSE(insert_item == NULL);
  383. item = interleave_list->First();
  384. ASSERT_FALSE(item == NULL);
  385. for (unsigned int j = 0; j < insert_position - 1; ++j) {
  386. item = interleave_list->Next(item);
  387. ASSERT_FALSE(item == NULL);
  388. }
  389. EXPECT_EQ(0, interleave_list->Insert(item, insert_item));
  390. --insert_position;
  391. }
  392. scoped_ptr<ListWrapperSimple> interleaved_list(
  393. CreateInterleavedList(rand()%2));
  394. ASSERT_FALSE(interleaved_list.get() == NULL);
  395. ASSERT_FALSE(interleaved_list->Empty());
  396. ASSERT_TRUE(CompareLists(interleaved_list.get(), interleave_list.get()));
  397. }
  398. // Use InsertBefore to interleave two lists.
  399. TEST(ListWrapperTest,InterLeaveTestII) {
  400. scoped_ptr<ListWrapperSimple> interleave_list(
  401. CreateDescendingList(rand()%2));
  402. ASSERT_FALSE(interleave_list.get() == NULL);
  403. ASSERT_FALSE(interleave_list->Empty());
  404. scoped_ptr<ListWrapperSimple> ascending_list(CreateAscendingList(rand()%2));
  405. ASSERT_FALSE(ascending_list.get() == NULL);
  406. for (unsigned int i = 0; i < kNumberOfElements/2; ++i) {
  407. ASSERT_EQ(0, interleave_list->PopBack());
  408. ASSERT_EQ(0, ascending_list->PopBack());
  409. }
  410. ASSERT_EQ(kNumberOfElements/2, interleave_list->GetSize());
  411. ASSERT_EQ(kNumberOfElements/2, ascending_list->GetSize());
  412. unsigned int insert_position = kNumberOfElements/2;
  413. ASSERT_EQ(insert_position * 2, kNumberOfElements);
  414. while (!ascending_list->Empty())
  415. {
  416. ListItem* item = ascending_list->Last();
  417. ASSERT_FALSE(item == NULL);
  418. const unsigned int item_id = ascending_list->GetUnsignedItem(item);
  419. ASSERT_EQ(0,ascending_list->Erase(item));
  420. ListItem* insert_item = interleave_list->CreateListItem(item_id);
  421. ASSERT_FALSE(insert_item == NULL);
  422. item = interleave_list->First();
  423. ASSERT_FALSE(item == NULL);
  424. for (unsigned int j = 0; j < insert_position - 1; ++j) {
  425. item = interleave_list->Next(item);
  426. ASSERT_FALSE(item == NULL);
  427. }
  428. EXPECT_EQ(interleave_list->InsertBefore(item, insert_item), 0);
  429. --insert_position;
  430. }
  431. scoped_ptr<ListWrapperSimple> interleaved_list(
  432. CreateInterleavedList(rand()%2));
  433. ASSERT_FALSE(interleaved_list.get() == NULL);
  434. ASSERT_FALSE(interleaved_list->Empty());
  435. ASSERT_TRUE(CompareLists(interleaved_list.get(), interleave_list.get()));
  436. }