Bug 986160 - Create unit tests for the Gecko Profiler. r=benwa
☠☠ backed out by 5fa70bd90a8b ☠ ☠
authorViktor Stanchev <vstanchev@mozilla.com>
Fri, 04 Apr 2014 10:11:41 +0800
changeset 177056 1e38b4aa888918c67c71de6e2dd3661f76b88ec5
parent 177055 2ac8fe9a90c51994b83e4a7fddbb9489b5b6c6bb
child 177057 0713dda3631803a75d3b5de46e85b8136ef8d785
push idunknown
push userunknown
push dateunknown
reviewersbenwa
bugs986160
milestone31.0a1
Bug 986160 - Create unit tests for the Gecko Profiler. r=benwa
tools/profiler/ProfileEntry.h
tools/profiler/moz.build
tools/profiler/tests/gtest/ThreadProfileTest.cpp
tools/profiler/tests/gtest/moz.build
--- a/tools/profiler/ProfileEntry.h
+++ b/tools/profiler/ProfileEntry.h
@@ -7,16 +7,17 @@
 #ifndef MOZ_PROFILE_ENTRY_H
 #define MOZ_PROFILE_ENTRY_H
 
 #include <ostream>
 #include "GeckoProfiler.h"
 #include "platform.h"
 #include "ProfilerBacktrace.h"
 #include "mozilla/Mutex.h"
+#include "gtest/gtest.h"
 
 class ThreadProfile;
 
 #pragma pack(push, 1)
 
 class ProfileEntry
 {
 public:
@@ -40,16 +41,21 @@ public:
   const ProfilerMarker* getMarker() {
     MOZ_ASSERT(mTagName == 'm');
     return mTagMarker;
   }
 
   char getTagName() const { return mTagName; }
 
 private:
+  FRIEND_TEST(ThreadProfile, InsertOneTag);
+  FRIEND_TEST(ThreadProfile, InsertOneTagWithTinyBuffer);
+  FRIEND_TEST(ThreadProfile, InsertTagsNoWrap);
+  FRIEND_TEST(ThreadProfile, InsertTagsWrap);
+  FRIEND_TEST(ThreadProfile, MemoryMeasure);
   friend class ThreadProfile;
   union {
     const char* mTagData;
     char        mTagChars[sizeof(void*)];
     void*       mTagPtr;
     ProfilerMarker* mTagMarker;
     double      mTagFloat;
     Address     mTagAddress;
@@ -94,16 +100,21 @@ public:
   PlatformData* GetPlatformData() { return mPlatformData; }
   int GetGenerationID() const { return mGeneration; }
   bool HasGenerationExpired(int aGenID) {
     return aGenID + 2 <= mGeneration;
   }
   void* GetStackTop() const { return mStackTop; }
   void DuplicateLastSample();
 private:
+  FRIEND_TEST(ThreadProfile, InsertOneTag);
+  FRIEND_TEST(ThreadProfile, InsertOneTagWithTinyBuffer);
+  FRIEND_TEST(ThreadProfile, InsertTagsNoWrap);
+  FRIEND_TEST(ThreadProfile, InsertTagsWrap);
+  FRIEND_TEST(ThreadProfile, MemoryMeasure);
   // Circular buffer 'Keep One Slot Open' implementation
   // for simplicity
   ProfileEntry*  mEntries;
   int            mWritePos; // points to the next entry we will write to
   int            mLastFlushPos; // points to the next entry since the last flush()
   int            mReadPos;  // points to the next entry we will read to
   int            mEntrySize;
   PseudoStack*   mPseudoStack;
--- a/tools/profiler/moz.build
+++ b/tools/profiler/moz.build
@@ -2,16 +2,19 @@
 # vim: set filetype=python:
 # 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/.
 
 if CONFIG['MOZ_ENABLE_PROFILER_SPS']:
     FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
 
+    if CONFIG['ENABLE_TESTS']:
+        DIRS += ['tests/gtest']
+
     XPIDL_MODULE = 'profiler'
     XPIDL_SOURCES += [
         'nsIProfiler.idl',
         'nsIProfileSaveEvent.idl',
     ]
     EXPORTS += [
         'GeckoProfilerFunc.h',
         'GeckoProfilerImpl.h',
new file mode 100644
--- /dev/null
+++ b/tools/profiler/tests/gtest/ThreadProfileTest.cpp
@@ -0,0 +1,69 @@
+/* -*- 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 "ProfileEntry.h"
+
+// Make sure we can initialize our ThreadProfile
+TEST(ThreadProfile, Initialization) {
+  PseudoStack stack;
+  Thread::tid_t tid = 1000;
+  ThreadProfile tp("testThread", 10, &stack, tid, nullptr, true, nullptr);
+}
+
+// Make sure we can record one tag and read it
+TEST(ThreadProfile, InsertOneTag) {
+  PseudoStack stack;
+  Thread::tid_t tid = 1000;
+  ThreadProfile tp("testThread", 10, &stack, tid, nullptr, true, nullptr);
+  tp.addTag(ProfileEntry('t', 123.1f));
+  ASSERT_TRUE(tp.mEntries != nullptr);
+  ASSERT_TRUE(tp.mEntries[tp.mReadPos].mTagName == 't');
+  ASSERT_TRUE(tp.mEntries[tp.mReadPos].mTagFloat == 123.1f);
+}
+
+// See if we can insert some tags
+TEST(ThreadProfile, InsertTagsNoWrap) {
+  PseudoStack stack;
+  Thread::tid_t tid = 1000;
+  ThreadProfile tp("testThread", 100, &stack, tid, nullptr, true, nullptr);
+  int test_size = 50;
+  for (int i = 0; i < test_size; i++) {
+    tp.addTag(ProfileEntry('t', i));
+  }
+  ASSERT_TRUE(tp.mEntries != nullptr);
+  int readPos = tp.mReadPos;
+  while (readPos != tp.mWritePos) {
+    ASSERT_TRUE(tp.mEntries[readPos].mTagName == 't');
+    ASSERT_TRUE(tp.mEntries[readPos].mTagLine == readPos);
+    readPos = (readPos + 1) % tp.mEntrySize;
+  }
+}
+
+// See if wrapping works as it should in the basic case
+TEST(ThreadProfile, InsertTagsWrap) {
+  PseudoStack stack;
+  Thread::tid_t tid = 1000;
+  // we can fit only 24 tags in this buffer because of the empty slot
+  int tags = 24;
+  int buffer_size = tags + 1;
+  ThreadProfile tp("testThread", buffer_size, &stack, tid, nullptr, true, nullptr);
+  int test_size = 43;
+  for (int i = 0; i < test_size; i++) {
+    tp.addTag(ProfileEntry('t', i));
+  }
+  ASSERT_TRUE(tp.mEntries != nullptr);
+  int readPos = tp.mReadPos;
+  int ctr = 0;
+  while (readPos != tp.mWritePos) {
+    ASSERT_TRUE(tp.mEntries[readPos].mTagName == 't');
+    // the first few tags were discarded when we wrapped
+    ASSERT_TRUE(tp.mEntries[readPos].mTagLine == ctr + (test_size - tags));
+    ctr++;
+    readPos = (readPos + 1) % tp.mEntrySize;
+  }
+}
+
new file mode 100644
--- /dev/null
+++ b/tools/profiler/tests/gtest/moz.build
@@ -0,0 +1,19 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+LIBRARY_NAME = 'profilertest'
+
+UNIFIED_SOURCES = [
+    "ThreadProfileTest.cpp",
+]
+
+EXPORT_LIBRARY = True
+
+LOCAL_INCLUDES += [
+    '/tools/profiler/',
+]
+
+FINAL_LIBRARY = 'xul-gtest'