/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gtest/gtest.h" #include "nsDeque.h" #include "nsCRT.h" #include /************************************************************** Now define the token deallocator class... **************************************************************/ namespace TestNsDeque { class _Dealloc: public nsDequeFunctor { virtual void* operator()(void* aObject) { return 0; } }; static bool VerifyContents(const nsDeque& aDeque, const int* aContents, size_t aLength) { for (size_t i=0; i(i); } // queue = [0...69] for (i=0;i<70;i++) { theDeque.Push(&ints[i]); temp=*(int*)theDeque.Peek(); EXPECT_EQ(static_cast(i), temp) << "Verify end after push #1"; EXPECT_EQ(i + 1, theDeque.GetSize()) << "Verify size after push #1"; } EXPECT_EQ(70u,theDeque.GetSize()) << "Verify overall size after pushes #1"; // queue = [0...14] for (i=1;i<=55;i++) { temp=*(int*)theDeque.Pop(); EXPECT_EQ(70-static_cast(i),temp) << "Verify end after pop # 1"; EXPECT_EQ(70u - i,theDeque.GetSize()) << "Verify size after pop # 1"; } EXPECT_EQ(15u,theDeque.GetSize()) << "Verify overall size after pops"; // queue = [0...14,0...54] for (i=0;i<55;i++) { theDeque.Push(&ints[i]); temp=*(int*)theDeque.Peek(); EXPECT_EQ(static_cast(i),temp) << "Verify end after push #2"; EXPECT_EQ(i + 15u + 1,theDeque.GetSize()) << "Verify size after push # 2"; } EXPECT_EQ(70u,theDeque.GetSize()) << "Verify size after end of all pushes #2"; // queue = [0...14,0...19] for (i=1;i<=35;i++) { temp=*(int*)theDeque.Pop(); EXPECT_EQ(55-static_cast(i),temp ) << "Verify end after pop # 2"; EXPECT_EQ(70u - i,theDeque.GetSize()) << "Verify size after pop #2"; } EXPECT_EQ(35u,theDeque.GetSize()) << "Verify overall size after end of all pops #2"; // queue = [0...14,0...19,0...34] for (i=0;i<35;i++) { theDeque.Push(&ints[i]); temp = *(int*)theDeque.Peek(); EXPECT_EQ(static_cast(i),temp) << "Verify end after push # 3"; EXPECT_EQ(35u + 1u + i,theDeque.GetSize()) << "Verify size after push #3"; } // queue = [0...14,0...19] for (i=0;i<35;i++) { temp=*(int*)theDeque.Pop(); EXPECT_EQ(34 - static_cast(i), temp) << "Verify end after pop # 3"; } // queue = [0...14] for (i=0;i<20;i++) { temp=*(int*)theDeque.Pop(); EXPECT_EQ(19 - static_cast(i),temp) << "Verify end after pop # 4"; } // queue = [] for (i=0;i<15;i++) { temp=*(int*)theDeque.Pop(); EXPECT_EQ(14 - static_cast(i),temp) << "Verify end after pop # 5"; } EXPECT_EQ(0u,theDeque.GetSize()) << "Deque should finish empty."; } TEST(NsDeque, OriginalFlaw) { int ints[200]; int i=0; int temp; nsDeque d(new _Dealloc); /** * Test 1. Origin near end, semi full, call Peek(). * you start, mCapacity is 8 */ for (i=0; i<30; i++) ints[i]=i; for (i=0; i<6; i++) { d.Push(&ints[i]); temp = *(int*)d.Peek(); EXPECT_EQ(i, temp) << "OriginalFlaw push #1"; } EXPECT_EQ(6u, d.GetSize()) << "OriginalFlaw size check #1"; for (i=0; i<4; i++) { temp=*(int*)d.PopFront(); EXPECT_EQ(i, temp) << "PopFront test"; } // d = [4,5] EXPECT_EQ(2u, d.GetSize()) << "OriginalFlaw size check #2"; for (i=0; i<4; i++) { d.Push(&ints[6 + i]); } // d = [4...9] for (i=4; i<=9; i++) { temp=*(int*)d.PopFront(); EXPECT_EQ(i, temp) << "OriginalFlaw empty check"; } } TEST(NsDeque, TestObjectAt) { nsDeque d; const int count = 10; int ints[count]; for (int i=0; i(i),t) << "Verify ObjectAt()"; } } TEST(NsDeque, TestPushFront) { // PushFront has some interesting corner cases, primarily we're interested in whether: // - wrapping around works properly // - growing works properly nsDeque d; const int kPoolSize = 10; const size_t kMaxSizeBeforeGrowth = 8; int pool[kPoolSize]; for (int i = 0; i < kPoolSize; i++) { pool[i] = i; } for (size_t i = 0; i < kMaxSizeBeforeGrowth; i++) { d.PushFront(pool + i); } EXPECT_EQ(kMaxSizeBeforeGrowth, d.GetSize()) << "verify size"; static const int t1[] = {7,6,5,4,3,2,1,0}; EXPECT_TRUE(VerifyContents(d, t1, kMaxSizeBeforeGrowth)) << "verify pushfront 1"; // Now push one more so it grows d.PushFront(pool + kMaxSizeBeforeGrowth); EXPECT_EQ(kMaxSizeBeforeGrowth + 1, d.GetSize()) << "verify size"; static const int t2[] = {8,7,6,5,4,3,2,1,0}; EXPECT_TRUE(VerifyContents(d, t2, kMaxSizeBeforeGrowth + 1)) << "verify pushfront 2"; // And one more so that it wraps again d.PushFront(pool + kMaxSizeBeforeGrowth + 1); EXPECT_EQ(kMaxSizeBeforeGrowth + 2, d.GetSize()) << "verify size"; static const int t3[] = {9,8,7,6,5,4,3,2,1,0}; EXPECT_TRUE(VerifyContents(d, t3, kMaxSizeBeforeGrowth + 2)) <<"verify pushfront 3"; } void CheckIfQueueEmpty(nsDeque& d) { EXPECT_EQ(0u, d.GetSize()) << "Size should be 0"; EXPECT_EQ(nullptr, d.Pop()) << "Invalid operation should return nullptr"; EXPECT_EQ(nullptr, d.PopFront()) << "Invalid operation should return nullptr"; EXPECT_EQ(nullptr, d.Peek()) << "Invalid operation should return nullptr"; EXPECT_EQ(nullptr, d.PeekFront()) << "Invalid operation should return nullptr"; EXPECT_EQ(nullptr, d.ObjectAt(0u)) << "Invalid operation should return nullptr"; } TEST(NsDeque,TestEmpty) { // Make sure nsDeque gives sane results if it's empty. nsDeque d; size_t numberOfEntries = 8; CheckIfQueueEmpty(d); // Fill it up and drain it. for (size_t i = 0; i < numberOfEntries; i++) { d.Push((void*)0xAA); } EXPECT_EQ(numberOfEntries, d.GetSize()); for (size_t i = 0; i < numberOfEntries; i++) { (void)d.Pop(); } // Now check it again. CheckIfQueueEmpty(d); } TEST(NsDeque,TestEraseMethod) { nsDeque d; const size_t numberOfEntries = 8; // Fill it up before calling Erase for (size_t i = 0; i < numberOfEntries; i++) { d.Push((void*)0xAA); } // Call Erase d.Erase(); // Now check it again. CheckIfQueueEmpty(d); } TEST(NsDeque,TestEraseShouldCallDeallocator) { nsDeque d(new Deallocator()); const size_t NumTestValues = 8; int* testArray[NumTestValues]; for (size_t i=0; i < NumTestValues; i++) { testArray[i] = new int(); *(testArray[i]) = i; d.Push((void*)testArray[i]); } d.Erase(); // Now check it again. CheckIfQueueEmpty(d); for (size_t i=0; i < NumTestValues; i++) { EXPECT_EQ(-1, *(testArray[i])) << "Erase should call deallocator: " << *(testArray[i]); } } TEST(NsDeque, TestForEach) { nsDeque d(new Deallocator()); const size_t NumTestValues = 8; int sum = 0; int* testArray[NumTestValues]; for (size_t i=0; i < NumTestValues; i++) { testArray[i] = new int(); *(testArray[i]) = i; sum += i; d.Push((void*)testArray[i]); } ForEachAdder adder; d.ForEach(adder); EXPECT_EQ(sum, adder.GetSum()) << "For each should iterate over values"; d.Erase(); }