You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
6.3 KiB
245 lines
6.3 KiB
/* |
|
* Copyright (C) 2013 The Android Open Source Project |
|
* All rights reserved. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions |
|
* are met: |
|
* * Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* * Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in |
|
* the documentation and/or other materials provided with the |
|
* distribution. |
|
* |
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
* SUCH DAMAGE. |
|
*/ |
|
|
|
#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()); |
|
} |
|
|
|
|