blob: cb24cbc74b78165033b222b6d515899f18df5186 [file] [log] [blame]
// Copyright 2012 Google Inc.
//
// 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.
//
// Author: morlovich@google.com (Maksim Orlovich)
#include "pagespeed/kernel/base/inline_slist.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
namespace net_instaweb {
namespace {
class IntElement : public InlineSListElement<IntElement> {
public:
explicit IntElement(int n) : num_(n) { }
const int num() const { return num_; }
void set_num(int num) { num_ = num; }
private:
int num_;
DISALLOW_COPY_AND_ASSIGN(IntElement);
};
typedef InlineSList<IntElement> IntList;
class InlineSListTest : public testing::Test {
protected:
// Dump the list value. Assumes the list only contains small numbers,
// but is thorough in checking various iteration interfaces, as well
// as ,->, Get() and *.
GoogleString Dump() {
GoogleString dump1, dump2, dump3, dump4, dump5, dump6;
for (IntList::iterator i = ints_.begin(); i != ints_.end(); ++i) {
dump1.push_back(i->num() + '0');
}
for (IntList::iterator i = ints_.begin(); i != ints_.end(); ++i) {
dump2.push_back((*i).num() + '0');
}
for (IntList::iterator i = ints_.begin(); i != ints_.end(); ++i) {
dump3.push_back(i.Get()->num() + '0');
}
const IntList& cints = const_cast<const IntList&>(ints_);
for (IntList::const_iterator i = cints.begin(); i != cints.end(); ++i) {
dump4.push_back(i->num() + '0');
}
for (IntList::const_iterator i = cints.begin(); i != cints.end(); ++i) {
dump5.push_back((*i).num() + '0');
}
for (IntList::const_iterator i = cints.begin(); i != cints.end(); ++i) {
dump6.push_back(i.Get()->num() + '0');
}
EXPECT_EQ(dump1, dump2);
EXPECT_EQ(dump1, dump3);
EXPECT_EQ(dump1, dump4);
EXPECT_EQ(dump1, dump5);
EXPECT_EQ(dump1, dump6);
return dump1;
}
IntList ints_;
};
TEST_F(InlineSListTest, BasicOperation) {
EXPECT_TRUE(ints_.IsEmpty());
EXPECT_STREQ("", Dump());
ints_.Append(new IntElement(0));
EXPECT_FALSE(ints_.IsEmpty());
EXPECT_STREQ("0", Dump());
ints_.Append(new IntElement(1));
EXPECT_FALSE(ints_.IsEmpty());
EXPECT_STREQ("01", Dump());
ints_.Append(new IntElement(2));
EXPECT_FALSE(ints_.IsEmpty());
EXPECT_STREQ("012", Dump());
}
TEST_F(InlineSListTest, DestructEmpty) {
// Make sure ~IntList works with no elements element.
}
TEST_F(InlineSListTest, Destruct1) {
// Make sure ~IntList works with 1 element.
ints_.Append(new IntElement(0));
}
TEST_F(InlineSListTest, Remove1) {
// Remove the sole item in 1-entry list.
ints_.Append(new IntElement(0));
EXPECT_EQ(0, ints_.Last()->num());
IntList::iterator iter(ints_.begin());
EXPECT_NE(ints_.end(), iter);
ints_.Erase(&iter);
EXPECT_EQ(ints_.end(), iter);
EXPECT_TRUE(ints_.IsEmpty());
EXPECT_STREQ("", Dump());
}
TEST_F(InlineSListTest, RemoveLast) {
// Remove last item of 0,1 list.
ints_.Append(new IntElement(0));
ints_.Append(new IntElement(1));
EXPECT_EQ(1, ints_.Last()->num());
IntList::iterator iter(ints_.begin());
EXPECT_NE(ints_.end(), iter);
EXPECT_EQ(0, iter->num());
++iter;
EXPECT_NE(ints_.end(), iter);
EXPECT_EQ(1, iter->num());
ints_.Erase(&iter);
EXPECT_EQ(ints_.end(), iter);
EXPECT_STREQ("0", Dump());
EXPECT_EQ(0, ints_.Last()->num());
}
TEST_F(InlineSListTest, RemoveFirst) {
// Remove first item of 0,1 list.
ints_.Append(new IntElement(0));
ints_.Append(new IntElement(1));
IntList::iterator iter(ints_.begin());
EXPECT_NE(ints_.end(), iter);
EXPECT_EQ(0, iter->num());
ints_.Erase(&iter);
EXPECT_NE(ints_.end(), iter);
EXPECT_EQ(1, iter->num());
++iter;
EXPECT_EQ(ints_.end(), iter);
EXPECT_STREQ("1", Dump());
}
TEST_F(InlineSListTest, RemoveOdd) {
for (int i = 0; i < 10; ++i) {
ints_.Append(new IntElement(i));
}
EXPECT_STREQ("0123456789", Dump());
IntList::iterator iter(ints_.begin());
while (iter != ints_.end()) {
if ((iter->num() % 2) == 1) {
ints_.Erase(&iter);
} else {
++iter;
}
}
EXPECT_STREQ("02468", Dump());
}
} // namespace
} // namespace net_instaweb