/* * 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()); }