| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdlib.h> |
| #include <string> |
| #include <sstream> |
| |
| #include <gtest/gtest.h> |
| |
| #include "../linked_list.h" |
| |
| namespace { |
| |
| bool alloc_called = false; |
| bool free_called = false; |
| |
| class LinkedListTestAllocator { |
| public: |
| typedef LinkedListEntry<const char> entry_t; |
| |
| static entry_t* alloc() { |
| alloc_called = true; |
| return reinterpret_cast<entry_t*>(::malloc(sizeof(entry_t))); |
| } |
| |
| static void free(entry_t* p) { |
| free_called = true; |
| ::free(p); |
| } |
| private: |
| DISALLOW_IMPLICIT_CONSTRUCTORS(LinkedListTestAllocator); |
| }; |
| |
| typedef LinkedList<const char, LinkedListTestAllocator> test_list_t; |
| |
| std::string test_list_to_string(test_list_t& list) { |
| std::stringstream ss; |
| list.for_each([&] (const char* c) { |
| ss << c; |
| }); |
| |
| return ss.str(); |
| } |
| |
| }; |
| |
| TEST(linked_list, simple) { |
| alloc_called = free_called = false; |
| test_list_t list; |
| ASSERT_EQ("", test_list_to_string(list)); |
| ASSERT_TRUE(!alloc_called); |
| ASSERT_TRUE(!free_called); |
| list.push_front("a"); |
| ASSERT_TRUE(alloc_called); |
| ASSERT_TRUE(!free_called); |
| ASSERT_EQ("a", test_list_to_string(list)); |
| list.push_front("b"); |
| ASSERT_EQ("ba", test_list_to_string(list)); |
| list.push_front("c"); |
| list.push_front("d"); |
| ASSERT_EQ("dcba", test_list_to_string(list)); |
| ASSERT_TRUE(alloc_called); |
| ASSERT_TRUE(!free_called); |
| alloc_called = free_called = false; |
| list.remove_if([] (const char* c) { |
| return *c == 'c'; |
| }); |
| |
| ASSERT_TRUE(!alloc_called); |
| ASSERT_TRUE(free_called); |
| |
| ASSERT_EQ("dba", test_list_to_string(list)); |
| alloc_called = free_called = false; |
| list.remove_if([] (const char* c) { |
| return *c == '2'; |
| }); |
| ASSERT_TRUE(!alloc_called); |
| ASSERT_TRUE(!free_called); |
| ASSERT_EQ("dba", test_list_to_string(list)); |
| list.clear(); |
| ASSERT_TRUE(!alloc_called); |
| ASSERT_TRUE(free_called); |
| ASSERT_EQ("", test_list_to_string(list)); |
| } |
| |
| TEST(linked_list, push_pop) { |
| test_list_t list; |
| list.push_front("b"); |
| list.push_front("a"); |
| ASSERT_EQ("ab", test_list_to_string(list)); |
| list.push_back("c"); |
| ASSERT_EQ("abc", test_list_to_string(list)); |
| ASSERT_STREQ("a", list.pop_front()); |
| ASSERT_EQ("bc", test_list_to_string(list)); |
| ASSERT_STREQ("b", list.pop_front()); |
| ASSERT_EQ("c", test_list_to_string(list)); |
| ASSERT_STREQ("c", list.pop_front()); |
| ASSERT_EQ("", test_list_to_string(list)); |
| ASSERT_TRUE(list.pop_front() == nullptr); |
| list.push_back("r"); |
| ASSERT_EQ("r", test_list_to_string(list)); |
| ASSERT_STREQ("r", list.pop_front()); |
| ASSERT_TRUE(list.pop_front() == nullptr); |
| } |
| |
| TEST(linked_list, remove_if_then_pop) { |
| test_list_t list; |
| list.push_back("a"); |
| list.push_back("b"); |
| list.push_back("c"); |
| list.push_back("d"); |
| list.remove_if([](const char* c) { |
| return *c == 'b' || *c == 'c'; |
| }); |
| |
| ASSERT_EQ("ad", test_list_to_string(list)); |
| ASSERT_STREQ("a", list.pop_front()); |
| ASSERT_EQ("d", test_list_to_string(list)); |
| ASSERT_STREQ("d", list.pop_front()); |
| ASSERT_TRUE(list.pop_front() == nullptr); |
| } |
| |
| TEST(linked_list, remove_if_last_then_push_back) { |
| test_list_t list; |
| |
| list.push_back("a"); |
| list.push_back("b"); |
| list.push_back("c"); |
| list.push_back("d"); |
| |
| list.remove_if([](const char* c) { |
| return *c == 'c' || *c == 'd'; |
| }); |
| |
| ASSERT_EQ("ab", test_list_to_string(list)); |
| list.push_back("d"); |
| ASSERT_EQ("abd", test_list_to_string(list)); |
| } |
| |
| TEST(linked_list, copy_to_array) { |
| test_list_t list; |
| const size_t max_size = 128; |
| const char* buf[max_size]; |
| memset(buf, 0, sizeof(buf)); |
| |
| ASSERT_EQ(0U, list.copy_to_array(buf, max_size)); |
| ASSERT_EQ(nullptr, buf[0]); |
| |
| list.push_back("a"); |
| list.push_back("b"); |
| list.push_back("c"); |
| list.push_back("d"); |
| |
| memset(buf, 0, sizeof(buf)); |
| ASSERT_EQ(2U, list.copy_to_array(buf, 2)); |
| ASSERT_STREQ("a", buf[0]); |
| ASSERT_STREQ("b", buf[1]); |
| ASSERT_EQ(nullptr, buf[2]); |
| |
| ASSERT_EQ(4U, list.copy_to_array(buf, max_size)); |
| ASSERT_STREQ("a", buf[0]); |
| ASSERT_STREQ("b", buf[1]); |
| ASSERT_STREQ("c", buf[2]); |
| ASSERT_STREQ("d", buf[3]); |
| ASSERT_EQ(nullptr, buf[4]); |
| |
| memset(buf, 0, sizeof(buf)); |
| list.remove_if([](const char* c) { |
| return *c != 'c'; |
| }); |
| ASSERT_EQ(1U, list.copy_to_array(buf, max_size)); |
| ASSERT_STREQ("c", buf[0]); |
| ASSERT_EQ(nullptr, buf[1]); |
| |
| memset(buf, 0, sizeof(buf)); |
| |
| list.remove_if([](const char* c) { |
| return *c == 'c'; |
| }); |
| |
| ASSERT_EQ(0U, list.copy_to_array(buf, max_size)); |
| ASSERT_EQ(nullptr, buf[0]); |
| } |
| |
| TEST(linked_list, test_visit) { |
| test_list_t list; |
| list.push_back("a"); |
| list.push_back("b"); |
| list.push_back("c"); |
| list.push_back("d"); |
| |
| int visits = 0; |
| std::stringstream ss; |
| bool result = list.visit([&](const char* c) { |
| ++visits; |
| ss << c; |
| return true; |
| }); |
| |
| ASSERT_TRUE(result); |
| ASSERT_EQ(4, visits); |
| ASSERT_EQ("abcd", ss.str()); |
| |
| visits = 0; |
| ss.str(std::string()); |
| |
| result = list.visit([&](const char* c) { |
| if (++visits == 3) { |
| return false; |
| } |
| |
| ss << c; |
| return true; |
| }); |
| |
| ASSERT_TRUE(!result); |
| ASSERT_EQ(3, visits); |
| ASSERT_EQ("ab", ss.str()); |
| } |
| |