Bug 1201997 - Part 1 - Converted compiled test to gtest for nsDeque class. Added tests to test untested methods. r=froydn
authorsajitk <sajitk@rocketmail.com>
Sun, 15 Nov 2015 14:47:49 +0100
changeset 272708 5de749562392797b11790eb79c27e2f4b1fd2cf0
parent 272707 410f33dfbc895cf0ac6b69ed3279b2b641c16862
child 272709 4ff71e68e02e6102cfe1ee60d52129be2c9de1f5
push id29682
push userkwierso@gmail.com
push dateTue, 17 Nov 2015 01:21:10 +0000
treeherdermozilla-central@a2f83cbe53ac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydn
bugs1201997
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1201997 - Part 1 - Converted compiled test to gtest for nsDeque class. Added tests to test untested methods. r=froydn
testing/cppunittest.ini
xpcom/glue/tests/gtest/TestNsDeque.cpp
xpcom/glue/tests/gtest/moz.build
xpcom/tests/TestDeque.cpp
xpcom/tests/moz.build
--- a/testing/cppunittest.ini
+++ b/testing/cppunittest.ini
@@ -24,17 +24,16 @@ skip-if = os == 'b2g' || (os == 'android
 [TestCertDB]
 [TestCheckedInt]
 [TestCookie]
 [TestCountPopulation]
 [TestCountZeroes]
 [TestDeadlockDetector]
 skip-if = os == 'b2g' || (os == 'android' && debug) # Bug 1054249
 [TestDeadlockDetectorScalability]
-[TestDeque]
 [TestDllInterceptor]
 skip-if = os != 'win'
 [TestEndian]
 [TestEnumSet]
 [TestFile]
 [TestFloatingPoint]
 [TestGetURL]
 [TestHashtables]
rename from xpcom/tests/TestDeque.cpp
rename to xpcom/glue/tests/gtest/TestNsDeque.cpp
--- a/xpcom/tests/TestDeque.cpp
+++ b/xpcom/glue/tests/gtest/TestNsDeque.cpp
@@ -1,191 +1,213 @@
 /* -*- 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 "TestHarness.h"
+#include "gtest/gtest.h"
 #include "nsDeque.h"
 #include "nsCRT.h"
 #include <stdio.h>
 
 /**************************************************************
   Now define the token deallocator class...
  **************************************************************/
-class _TestDeque {
-public:
-  int Test();
-private:
-  int OriginalTest();
-  int OriginalFlaw();
-  int AssignFlaw();
-  int TestRemove();
-  int TestPushFront();
-  int TestEmpty();
-};
+namespace TestNsDeque {
+  
+  class _Dealloc: public nsDequeFunctor 
+  {
+    virtual void* operator()(void* aObject) {
+      return 0;
+    }
+  };
+
+  static bool VerifyContents(const nsDeque& aDeque, const int* aContents, int aLength) 
+  {
+    for (int i=0; i<aLength; ++i) {
+      if (*(int*)aDeque.ObjectAt(i) != aContents[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
 
-class _Dealloc: public nsDequeFunctor {
-  virtual void* operator()(void* aObject) {
-    return 0;
-  }
-};
+  class Deallocator: public nsDequeFunctor
+  {
+    virtual void* operator()(void* aObject) 
+    {
+      if (aObject) 
+      {
+        // Set value to -1, to use in test function.
+        *((int*)aObject) = -1;
+      }
+
+      return nullptr;
+    }
+  };
 
-#define TEST(aCondition, aMsg) \
-  if (!(aCondition)) { fail("TestDeque: "#aMsg); return 1; }
+  class ForEachAdder: public nsDequeFunctor
+  {
+    virtual void* operator()(void* aObject) 
+    {
+      if (aObject) 
+      {
+        sum += *(int*)aObject;
+      }
+
+      return aObject;
+    }
+
+    private:
+     int sum = 0;
+    
+    public:
+     int GetSum() { return sum; }
+    
+  };
 
 
-/**
- * conduct automated self test for this class
- *
- * @param
- * @return
- */
-int _TestDeque::Test() {
-  /* the old deque should have failed a bunch of these tests */
-  int results=0;
-  results+=OriginalTest();
-  results+=OriginalFlaw();
-  results+=AssignFlaw();
-  results+=TestRemove();
-  results+=TestPushFront();
-  results+=TestEmpty();
-  return results;
+  class NumberSevenFinder: public nsDequeFunctor
+  {
+    virtual void* operator()(void* aObject) 
+    {
+      if (aObject) 
+      {
+        int value = *(int*)aObject;
+        if (value == 7)
+        {
+          return (int*)1;
+        }
+      }
+
+      return 0;
+    }
+  };
 }
 
-int _TestDeque::OriginalTest() {
+using namespace TestNsDeque;
+
+TEST(NsDeque, OriginalTest) 
+{
   const int size = 200;
   int ints[size];
   int i=0;
   int temp;
   nsDeque theDeque(new _Dealloc); //construct a simple one...
  
   // ints = [0...199]
   for (i=0;i<size;i++) { //initialize'em
     ints[i]=i;
   }
   // queue = [0...69]
   for (i=0;i<70;i++) {
     theDeque.Push(&ints[i]);
     temp=*(int*)theDeque.Peek();
-    TEST(temp == i, "Verify end after push #1");
-    TEST(theDeque.GetSize() == i + 1, "Verify size after push #1");
+    EXPECT_EQ(i, temp) << "Verify end after push #1";
+    EXPECT_EQ(i + 1, theDeque.GetSize()) << "Verify size after push #1";
   }
-  TEST(theDeque.GetSize() == 70, "Verify overall size after pushes #1");
+
+  EXPECT_EQ(70,theDeque.GetSize()) << "Verify overall size after pushes #1";
+
   // queue = [0...14]
   for (i=1;i<=55;i++) {
     temp=*(int*)theDeque.Pop();
-    TEST(temp == 70-i, "Verify end after pop # 1");
-    TEST(theDeque.GetSize() == 70 - i, "Verify size after pop # 1");
+    EXPECT_EQ(70-i,temp) << "Verify end after pop # 1";
+    EXPECT_EQ(70 - i,theDeque.GetSize()) << "Verify size after pop # 1";
   }
-  TEST(theDeque.GetSize() == 15, "Verify overall size after pops");
+  EXPECT_EQ(15,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();
-    TEST(temp == i, "Verify end after push #2");
-    TEST(theDeque.GetSize() == i + 15 + 1, "Verify size after push # 2");
+    EXPECT_EQ(i,temp) << "Verify end after push #2";
+    EXPECT_EQ(i + 15 + 1,theDeque.GetSize()) << "Verify size after push # 2";
   }
-  TEST(theDeque.GetSize() == 70, "Verify size after end of all pushes #2");
+  EXPECT_EQ(70,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();
-    TEST(temp == 55-i, "Verify end after pop # 2");
-    TEST(theDeque.GetSize() == 70 - i, "Verify size after pop #2");
+    EXPECT_EQ(55-i,temp ) << "Verify end after pop # 2";
+    EXPECT_EQ(70 - i,theDeque.GetSize()) << "Verify size after pop #2";
   }
-  TEST(theDeque.GetSize() == 35, "Verify overall size after end of all pops #2");
+  EXPECT_EQ(35,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();
-    TEST(temp == i, "Verify end after push # 3");
-    TEST(theDeque.GetSize() == 35 + 1 + i, "Verify size after push #3");
+    EXPECT_EQ(i,temp) << "Verify end after push # 3";
+    EXPECT_EQ(35 + 1 + i,theDeque.GetSize()) << "Verify size after push #3";
   }
 
   // queue = [0...14,0...19]
   for (i=0;i<35;i++) {
     temp=*(int*)theDeque.Pop();
-    TEST(temp == 34 - i, "Verify end after pop # 3");
+    EXPECT_EQ(34 - i, temp) << "Verify end after pop # 3";
   }
 
   // queue = [0...14]
   for (i=0;i<20;i++) {
     temp=*(int*)theDeque.Pop();
-    TEST(temp == 19 - i, "Verify end after pop # 4");
+    EXPECT_EQ(19 - i,temp) << "Verify end after pop # 4";
   }
 
   // queue = []
   for (i=0;i<15;i++) {
     temp=*(int*)theDeque.Pop();
-    TEST(temp == 14 - i, "Verify end after pop # 5");
+    EXPECT_EQ(14 - i,temp) << "Verify end after pop # 5";
   }
 
-  TEST(theDeque.GetSize() == 0, "Deque should finish empty.");
-
-  return 0;
+  EXPECT_EQ(0,theDeque.GetSize()) << "Deque should finish empty.";
 }
 
-int _TestDeque::OriginalFlaw() {
+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
    */
-  printf("fill array\n");
   for (i=0; i<30; i++)
     ints[i]=i;
 
   for (i=0; i<6; i++) {
     d.Push(&ints[i]);
     temp = *(int*)d.Peek();
-    TEST(temp == i, "OriginalFlaw push #1");
+    EXPECT_EQ(i, temp) << "OriginalFlaw push #1";
   }
-  TEST(d.GetSize() == 6, "OriginalFlaw size check #1");
+  EXPECT_EQ(6, d.GetSize()) << "OriginalFlaw size check #1";
 
   for (i=0; i<4; i++) {
     temp=*(int*)d.PopFront();
-    TEST(temp == i, "PopFront test");
+    EXPECT_EQ(i, temp) << "PopFront test";
   }
   // d = [4,5]
-  TEST(d.GetSize() == 2, "OriginalFlaw size check #2");
+  EXPECT_EQ(2, 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();
-    TEST(temp == i, "OriginalFlaw empty check");
+    EXPECT_EQ(i, temp) << "OriginalFlaw empty check";
   }
-
-  return 0;
 }
 
-int _TestDeque::AssignFlaw() {
-  nsDeque src(new _Dealloc),dest(new _Dealloc);
-  return 0;
-}
+
 
-static bool VerifyContents(const nsDeque& aDeque, const int* aContents, int aLength) {
-  for (int i=0; i<aLength; ++i) {
-    if (*(int*)aDeque.ObjectAt(i) != aContents[i]) {
-      return false;
-    }
-  }
-  return true;
-}
-
-int _TestDeque::TestRemove() {
+TEST(NsDeque, TestRemove)
+{
   nsDeque d;
   const int count = 10;
   int ints[count];
   for (int i=0; i<count; i++) {
     ints[i] = i;
   }
 
   for (int i=0; i<6; i++) {
@@ -193,52 +215,50 @@ int _TestDeque::TestRemove() {
   }
   // d = [0...5]
   d.PopFront();
   d.PopFront();
 
   // d = [2,5]
   for (int i=2; i<=5; i++) {
     int t = *(int*)d.ObjectAt(i-2);
-    TEST(t == i, "Verify ObjectAt()");
+    EXPECT_EQ(i,t) << "Verify ObjectAt()";
   }
 
   d.RemoveObjectAt(1);
   // d == [2,4,5]
   static const int t1[] = {2,4,5};
-  TEST(VerifyContents(d, t1, 3), "verify contents t1");
+  EXPECT_TRUE(VerifyContents(d, t1, 3)) << "verify contents t1";
 
   d.PushFront(&ints[1]);
   d.PushFront(&ints[0]);
   d.PushFront(&ints[7]);
   d.PushFront(&ints[6]);
   //  d == [6,7,0,1,2,4,5] // (0==mOrigin)
   static const int t2[] = {6,7,0,1,2,4,5};
-  TEST(VerifyContents(d, t2, 7), "verify contents t2");
+  EXPECT_TRUE(VerifyContents(d, t2, 7)) << "verify contents t2";
 
   d.RemoveObjectAt(1);
   //  d == [6,0,1,2,4,5] // (1==mOrigin)
   static const int t3[] = {6,0,1,2,4,5};
-  TEST(VerifyContents(d, t3, 6), "verify contents t3");
+  EXPECT_TRUE(VerifyContents(d, t3, 6)) << "verify contents t3";
 
   d.RemoveObjectAt(5);
   //  d == [6,0,1,2,4] // (1==mOrigin)
   static const int t4[] = {6,0,1,2,4};
-  TEST(VerifyContents(d, t4, 5), "verify contents t4");
+  EXPECT_TRUE(VerifyContents(d, t4, 5)) << "verify contents t4";
 
   d.RemoveObjectAt(0);
   //  d == [0,1,2,4] // (2==mOrigin)
   static const int t5[] = {0,1,2,4};
-  TEST(VerifyContents(d, t5, 4), "verify contents t5");
-
-
-  return 0;
+  EXPECT_TRUE(VerifyContents(d, t5, 4)) << "verify contents t5";
 }
 
-int _TestDeque::TestPushFront() {
+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 int kMaxSizeBeforeGrowth = 8;
@@ -247,72 +267,188 @@ int _TestDeque::TestPushFront() {
   for (int i = 0; i < kPoolSize; i++) {
     pool[i] = i;
   }
 
   for (int i = 0; i < kMaxSizeBeforeGrowth; i++) {
     d.PushFront(pool + i);
   }
 
-  TEST(d.GetSize() == kMaxSizeBeforeGrowth, "verify size");
+  EXPECT_EQ(kMaxSizeBeforeGrowth, d.GetSize()) << "verify size";
 
   static const int t1[] = {7,6,5,4,3,2,1,0};
-  TEST(VerifyContents(d, t1, kMaxSizeBeforeGrowth), "verify pushfront 1");
+  EXPECT_TRUE(VerifyContents(d, t1, kMaxSizeBeforeGrowth)) << "verify pushfront 1";
 
   // Now push one more so it grows
   d.PushFront(pool + kMaxSizeBeforeGrowth);
-  TEST(d.GetSize() == kMaxSizeBeforeGrowth + 1, "verify size");
+  EXPECT_EQ(kMaxSizeBeforeGrowth + 1, d.GetSize()) << "verify size";
 
   static const int t2[] = {8,7,6,5,4,3,2,1,0};
-  TEST(VerifyContents(d, t2, kMaxSizeBeforeGrowth + 1), "verify pushfront 2");
+  EXPECT_TRUE(VerifyContents(d, t2, kMaxSizeBeforeGrowth + 1)) << "verify pushfront 2";
 
   // And one more so that it wraps again
   d.PushFront(pool + kMaxSizeBeforeGrowth + 1);
-  TEST(d.GetSize() == kMaxSizeBeforeGrowth + 2, "verify size");
+  EXPECT_EQ(kMaxSizeBeforeGrowth + 2, d.GetSize()) << "verify size";
 
   static const int t3[] = {9,8,7,6,5,4,3,2,1,0};
-  TEST(VerifyContents(d, t3, kMaxSizeBeforeGrowth + 2), "verify pushfront 3");
-
-  return 0;
+  EXPECT_TRUE(VerifyContents(d, t3, kMaxSizeBeforeGrowth + 2)) <<"verify pushfront 3";
 }
 
-int _TestDeque::TestEmpty() {
+TEST(NsDeque,TestEmpty)
+{
   // Make sure nsDeque gives sane results if it's empty.
   nsDeque d;
+  size_t numberOfEntries = 8;
 
-  TEST(d.GetSize() == 0, "Size should be 0");
-  TEST(d.Pop() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.PopFront() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.Peek() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.PeekFront() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.ObjectAt(0) == nullptr, "Invalid operation should return nullptr");
-  TEST(d.Last() == nullptr, "Invalid operation should return nullptr");
+  EXPECT_EQ(0, 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(0)) <<  "Invalid operation should return nullptr";
+  EXPECT_EQ(nullptr, d.Last())      <<  "Invalid operation should return nullptr";
 
   // Fill it up and drain it.
-  for (size_t i = 0; i < 8; i++) {
+  for (size_t i = 0; i < numberOfEntries; i++) {
     d.Push((void*)0xAA);
   }
 
-  for (size_t i = 0; i < 8; i++) {
+  EXPECT_EQ(numberOfEntries, d.GetSize());
+
+  for (size_t i = 0; i < numberOfEntries; i++) {
     (void)d.Pop();
   }
 
   // Now check it again.
-  TEST(d.GetSize() == 0, "Size should be 0");
-  TEST(d.Pop() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.PopFront() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.Peek() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.PeekFront() == nullptr, "Invalid operation should return nullptr");
-  TEST(d.ObjectAt(0) == nullptr, "Invalid operation should return nullptr");
-  TEST(d.Last() == nullptr, "Invalid operation should return nullptr");
+  EXPECT_EQ(0, 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(0)) << "Invalid operation should return nullptr";
+  EXPECT_EQ(nullptr, d.Last())      <<"Invalid operation should return nullptr";
+}
+
+TEST(NsDeque,TestEmptyMethod)
+{
+  nsDeque d;
+  size_t numberOfEntries = 8;
+
+  // Fill it up before calling Empty
+  for (size_t i = 0; i < numberOfEntries; i++) {
+    d.Push((void*)0xAA);
+  }
+
+  // Call empty
+  d.Empty();
 
-  return 0;
+  // Now check it again.
+  EXPECT_EQ(0, 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(0)) << "Invalid operation should return nullptr";
+  EXPECT_EQ(nullptr, d.Last())      <<"Invalid operation should return nullptr";
+
+  // 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.
+  EXPECT_EQ(0, 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(0)) << "Invalid operation should return nullptr";
+  EXPECT_EQ(nullptr, d.Last())      <<"Invalid operation should return nullptr";
 }
 
-int main (void) {
-  ScopedXPCOM xpcom("TestDeque");
-  NS_ENSURE_FALSE(xpcom.failed(), 1);
+TEST(NsDeque,TestEraseShouldCallDeallocator)
+{
+  nsDeque d(new Deallocator());
+  const int 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.
+  EXPECT_EQ(0, 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(0)) << "Invalid operation should return nullptr";
+  EXPECT_EQ(nullptr, d.Last())      <<"Invalid operation should return nullptr";
+  
+  for (size_t i=0; i < NumTestValues; i++)
+  {
+    EXPECT_EQ(-1, *(testArray[i])) << "Erase should call deallocator: " << *(testArray[i]);
+  }  
+}
+
+TEST(NsDeque,TestEmptyShouldNotCallDeallocator)
+{
+  nsDeque d(new Deallocator());
+  const int 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]);
+  }
 
-  _TestDeque test;
-  int result = test.Test();
-  TEST(result == 0, "All tests pass");
-  return 0;
+  d.Empty();
+
+  // Now check it again.
+  EXPECT_EQ(0, 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(0)) << "Invalid operation should return nullptr";
+  EXPECT_EQ(nullptr, d.Last())      <<"Invalid operation should return nullptr";
+
+  for (size_t i=0; i < NumTestValues; i++)
+  {
+    EXPECT_EQ(i, *(testArray[i])) << "Empty should not call deallocator";
+  }
 }
+
+TEST(NsDeque, TestForEachAndFirstThat)
+{
+  nsDeque d(new Deallocator());
+  const int 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";
+
+  NumberSevenFinder finder;
+  const int* value = (const int*)d.FirstThat(finder);
+  EXPECT_EQ(7, *value) << "FirstThat should return value matching functor";
+
+  d.Erase();
+}
--- a/xpcom/glue/tests/gtest/moz.build
+++ b/xpcom/glue/tests/gtest/moz.build
@@ -3,16 +3,17 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'TestArray.cpp',
     'TestFileUtils.cpp',
     'TestGCPostBarriers.cpp',
+    'TestNsDeque.cpp',
     'TestThreadUtils.cpp',
 ]
 
 LOCAL_INCLUDES = [
     '../..',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
--- a/xpcom/tests/moz.build
+++ b/xpcom/tests/moz.build
@@ -51,17 +51,16 @@ XPCSHELL_TESTS_MANIFESTS += ['unit/xpcsh
 
 GeckoCppUnitTests([
     'ShowAlignments',
     'TestAutoPtr',
     'TestAutoRef',
     'TestCOMArray',
     'TestCOMPtr',
     'TestCOMPtrEq',
-    'TestDeque',
     'TestFile',
     'TestHashtables',
     'TestID',
     'TestNsRefPtr',
     'TestObserverArray',
     'TestObserverService',
     'TestPipe',
     'TestStringAPI',