Bug 1078979 - Add more testing of dmd.py. r=erahm.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 09 Oct 2014 16:50:12 -0700
changeset 209849 1c7a61385d1718fd13f1d1a59a41254923b554ae
parent 209848 367b155c5b5e07683a4a4fd3208ab91401d162bb
child 209850 fb7198e662d9e9d5a0585961623af0664db66798
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerserahm
bugs1078979
milestone35.0a1
Bug 1078979 - Add more testing of dmd.py. r=erahm.
memory/replace/dmd/DMD.cpp
memory/replace/dmd/dmd.py
memory/replace/dmd/test/full-heap-empty-expected.txt
memory/replace/dmd/test/full-heap-expected1.txt
memory/replace/dmd/test/full-heap-expected2.txt
memory/replace/dmd/test/full-heap-expected3.txt
memory/replace/dmd/test/full-heap-expected4.txt
memory/replace/dmd/test/full-heap-sampled-expected.txt
memory/replace/dmd/test/full-heap-unsampled1-expected.txt
memory/replace/dmd/test/full-heap-unsampled2-expected.txt
memory/replace/dmd/test/full-reports-empty-expected.txt
memory/replace/dmd/test/full-reports-expected1.txt
memory/replace/dmd/test/full-reports-expected2.txt
memory/replace/dmd/test/full-reports-expected3.txt
memory/replace/dmd/test/full-reports-expected4.txt
memory/replace/dmd/test/full-reports-sampled-expected.txt
memory/replace/dmd/test/full-reports-unsampled1-expected.txt
memory/replace/dmd/test/full-reports-unsampled2-expected.txt
memory/replace/dmd/test/script-ignore-alloc-fns-expected.txt
memory/replace/dmd/test/script-ignore-alloc-fns.json
memory/replace/dmd/test/script-max-frames-1-expected.txt
memory/replace/dmd/test/script-max-frames-3-expected.txt
memory/replace/dmd/test/script-max-frames-8-expected.txt
memory/replace/dmd/test/script-max-frames.json
memory/replace/dmd/test/script-show-all-block-sizes-expected.txt
memory/replace/dmd/test/script-show-all-block-sizes.json
memory/replace/dmd/test/script-sort-by-req-expected.txt
memory/replace/dmd/test/script-sort-by-slop-expected.txt
memory/replace/dmd/test/script-sort-by-usable-expected.txt
memory/replace/dmd/test/script-sort-by.json
memory/replace/dmd/test/test_dmd.js
memory/replace/dmd/test/xpcshell.ini
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -1442,20 +1442,20 @@ Init(const malloc_table_t* aMallocTable)
   if (gOptions->IsTestMode()) {
     // Do all necessary allocations before setting gIsDMDRunning so those
     // allocations don't show up in our results.  Once gIsDMDRunning is set we
     // are intercepting malloc et al. in earnest.
     //
     // These files are written to $CWD. It would probably be better to write
     // them to "TmpD" using the directory service, but that would require
     // linking DMD with XPCOM.
-    auto f1 = MakeUnique<FpWriteFunc>(OpenOutputFile("full1.json"));
-    auto f2 = MakeUnique<FpWriteFunc>(OpenOutputFile("full2.json"));
-    auto f3 = MakeUnique<FpWriteFunc>(OpenOutputFile("full3.json"));
-    auto f4 = MakeUnique<FpWriteFunc>(OpenOutputFile("full4.json"));
+    auto f1 = MakeUnique<FpWriteFunc>(OpenOutputFile("full-empty.json"));
+    auto f2 = MakeUnique<FpWriteFunc>(OpenOutputFile("full-unsampled1.json"));
+    auto f3 = MakeUnique<FpWriteFunc>(OpenOutputFile("full-unsampled2.json"));
+    auto f4 = MakeUnique<FpWriteFunc>(OpenOutputFile("full-sampled.json"));
     gIsDMDRunning = true;
 
     StatusMsg("running test mode...\n");
     RunTestMode(Move(f1), Move(f2), Move(f3), Move(f4));
     StatusMsg("finished test mode; DMD is now disabled again\n");
 
     // Continue running so that the xpcshell test can complete, but DMD no
     // longer needs to be running.
--- a/memory/replace/dmd/dmd.py
+++ b/memory/replace/dmd/dmd.py
@@ -17,17 +17,19 @@ import re
 import shutil
 import sys
 import tempfile
 
 # The DMD output version this script handles.
 outputVersion = 1
 
 # If --ignore-alloc-fns is specified, stack frames containing functions that
-# match these strings will be removed.
+# match these strings will be removed from the *start* of stack traces. (Once
+# we hit a non-matching frame, any subsequent frames won't be removed even if
+# they do match.)
 allocatorFns = [
     'replace_malloc',
     'replace_calloc',
     'replace_realloc',
     'replace_memalign',
     'replace_posix_memalign',
     'moz_xmalloc',
     'moz_xcalloc',
@@ -43,16 +45,20 @@ allocatorFns = [
     'vpx_realloc',
     'vpx_memalign',
     'js_malloc',
     'js_calloc',
     'js_realloc',
     'pod_malloc',
     'pod_calloc',
     'pod_realloc',
+    # This one necessary to fully filter some sequences of allocation functions
+    # that happen in practice. Note that ??? entries that follow non-allocation
+    # functions won't be stripped, as explained above.
+    '???',
 ]
 
 class Record(object):
     def __init__(self):
         self.numBlocks = 0
         self.reqSize = 0
         self.slopSize = 0
         self.usableSize = 0
rename from memory/replace/dmd/test/full-heap-expected1.txt
rename to memory/replace/dmd/test/full-heap-empty-expected.txt
rename from memory/replace/dmd/test/full-heap-expected4.txt
rename to memory/replace/dmd/test/full-heap-sampled-expected.txt
rename from memory/replace/dmd/test/full-heap-expected2.txt
rename to memory/replace/dmd/test/full-heap-unsampled1-expected.txt
rename from memory/replace/dmd/test/full-heap-expected3.txt
rename to memory/replace/dmd/test/full-heap-unsampled2-expected.txt
rename from memory/replace/dmd/test/full-reports-expected1.txt
rename to memory/replace/dmd/test/full-reports-empty-expected.txt
rename from memory/replace/dmd/test/full-reports-expected4.txt
rename to memory/replace/dmd/test/full-reports-sampled-expected.txt
rename from memory/replace/dmd/test/full-reports-expected2.txt
rename to memory/replace/dmd/test/full-reports-unsampled1-expected.txt
rename from memory/replace/dmd/test/full-reports-expected3.txt
rename to memory/replace/dmd/test/full-reports-unsampled2-expected.txt
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-ignore-alloc-fns-expected.txt
@@ -0,0 +1,56 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 2500
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  1 block in heap block record 1 of 4
+  1,048,576 bytes (1,048,576 requested / 0 slop)
+  93.22% of the heap (93.22% cumulative)
+  Allocated at {
+    #01: A (A.cpp:99)
+  }
+}
+
+Live {
+  1 block in heap block record 2 of 4
+  65,536 bytes (65,536 requested / 0 slop)
+  5.83% of the heap (99.05% cumulative)
+  Allocated at {
+    #01: js::jit::JitRuntime::initialize(JSContext*) (Ion.cpp:301)
+  }
+}
+
+Live {
+  1 block in heap block record 3 of 4
+  8,192 bytes (8,000 requested / 192 slop)
+  0.73% of the heap (99.78% cumulative)
+  Allocated at {
+    #01: mozilla::Vector::growStorageBy(unsigned long) (Vector.h:802)
+    #02: D (D.cpp:99)
+  }
+}
+
+Live {
+  ~1 block in heap block record 4 of 4
+  ~2,500 bytes (~2,500 requested / ~0 slop)
+  0.22% of the heap (100.00% cumulative)
+  Allocated at {
+    #01: g_type_create_instance (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0)
+    #02: not_an_alloc_function_so_alloc_functions_below_here_will_not_be_stripped (blah)
+    #03: replace_posix_memalign (replace_malloc.h:120)
+    #04: ??? (/lib/x86_64-linux-gnu/libglib-2.0.so.0)
+    #05: another_non_alloc_function (blah)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: ~1,124,804 bytes in ~4 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-ignore-alloc-fns.json
@@ -0,0 +1,46 @@
+{
+ "version": 1,
+ "invocation": {
+  "dmdEnvVar": "1",
+  "sampleBelowSize": 2500
+ },
+ "blockList": [
+  {"req": 1048576,           "alloc": "A"},
+  {"req": 65536,             "alloc": "B"},
+  {"req": 8000, "slop": 192, "alloc": "C"},
+  {                          "alloc": "D"}
+ ],
+ "traceTable": {
+  "A": ["AA", "AB", "AC", "AD"],
+  "B": ["BA", "BB", "BC"],
+  "C": ["CA", "CB", "CC", "CD"],
+  "D": ["DA", "DB", "DD", "DD", "DE", "DF", "DG", "DH", "DI", "DJ"]
+ },
+ "frameTable": {
+  "AA": "#00: replace_malloc (DMD.cpp:1106)",
+  "AB": "#00: moz_xmalloc (mozalloc.cpp:68)",
+  "AC": "#00: operator new(unsigned long) (mozalloc.h:208)",
+  "AD": "#00: A (A.cpp:99)",
+
+  "BA": "#00: replace_calloc (DMD.cpp:1125)",
+  "BB": "#00: js_calloc(unsigned long) (Utility.h:107)",
+  "BC": "#06: js::jit::JitRuntime::initialize(JSContext*) (Ion.cpp:301)",
+
+  "CA": "#00: replace_realloc (DMD.cpp:1153)",
+  "CB": "#00: bool* mozilla::MallocAllocPolicy::pod_realloc<bool>(bool*, unsigned long, unsigned long) (AllocPolicy.h:74)",
+  "CC": "#00: mozilla::Vector::growStorageBy(unsigned long) (Vector.h:802)",
+  "CD": "#00: D (D.cpp:99)",
+
+  "DA": "#00: replace_memalign (DMD.cpp:1181)",
+  "DB": "#00: replace_posix_memalign (replace_malloc.h:120)",
+  "DC": "#00: ??? (/lib/x86_64-linux-gnu/libglib-2.0.so.0)",
+  "DD": "#00: g_slice_alloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0)",
+  "DE": "#00: g_slice_alloc0 (/lib/x86_64-linux-gnu/libglib-2.0.so.0)",
+  "DF": "#00: g_type_create_instance (/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0)",
+  "DG": "#00: not_an_alloc_function_so_alloc_functions_below_here_will_not_be_stripped (blah)",
+  "DH": "#00: replace_posix_memalign (replace_malloc.h:120)",
+  "DI": "#00: ??? (/lib/x86_64-linux-gnu/libglib-2.0.so.0)",
+  "DJ": "#00: another_non_alloc_function (blah)"
+ }
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-max-frames-1-expected.txt
@@ -0,0 +1,24 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 1
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  4 blocks in heap block record 1 of 1
+  4,416 bytes (4,404 requested / 12 slop)
+  100.00% of the heap (100.00% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: 4,416 bytes in 4 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-max-frames-3-expected.txt
@@ -0,0 +1,46 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 1
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  2 blocks in heap block record 1 of 3
+  4,224 bytes (4,224 requested / 0 slop)
+  95.65% of the heap (95.65% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+    #02: F (F.cpp:99)
+    #03: G (G.cpp:99)
+  }
+}
+
+Live {
+  1 block in heap block record 2 of 3
+  112 bytes (100 requested / 12 slop)
+  2.54% of the heap (98.19% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+    #02: X (X.cpp:99)
+    #03: Y (Y.cpp:99)
+  }
+}
+
+Live {
+  1 block in heap block record 3 of 3
+  80 bytes (80 requested / 0 slop)
+  1.81% of the heap (100.00% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: 4,416 bytes in 4 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-max-frames-8-expected.txt
@@ -0,0 +1,68 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 1
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  1 block in heap block record 1 of 4
+  4,096 bytes (4,096 requested / 0 slop)
+  92.75% of the heap (92.75% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+    #02: F (F.cpp:99)
+    #03: G (G.cpp:99)
+    #04: H (H.cpp:99)
+    #05: I (I.cpp:99)
+    #06: J (J.cpp:99)
+    #07: K (K.cpp:99)
+    #08: L (L.cpp:99)
+  }
+}
+
+Live {
+  1 block in heap block record 2 of 4
+  128 bytes (128 requested / 0 slop)
+  2.90% of the heap (95.65% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+    #02: F (F.cpp:99)
+    #03: G (G.cpp:99)
+    #04: R (R.cpp:99)
+    #05: S (S.cpp:99)
+    #06: T (T.cpp:99)
+    #07: U (U.cpp:99)
+    #08: V (V.cpp:99)
+  }
+}
+
+Live {
+  1 block in heap block record 3 of 4
+  112 bytes (100 requested / 12 slop)
+  2.54% of the heap (98.19% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+    #02: X (X.cpp:99)
+    #03: Y (Y.cpp:99)
+    #04: Z (Z.cpp:99)
+  }
+}
+
+Live {
+  1 block in heap block record 4 of 4
+  80 bytes (80 requested / 0 slop)
+  1.81% of the heap (100.00% cumulative)
+  Allocated at {
+    #01: E (E.cpp:99)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: 4,416 bytes in 4 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-max-frames.json
@@ -0,0 +1,43 @@
+{
+ "version": 1,
+ "invocation": {
+  "dmdEnvVar": "1",
+  "sampleBelowSize": 1
+ },
+ "blockList": [
+  {"req": 4096, "alloc": "A"},
+  {"req": 128, "alloc": "B"},
+  {"req": 100, "slop":12, "alloc": "C"},
+  {"req": 80, "alloc": "D"}
+ ],
+ "traceTable": {
+  "A": ["E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P"],
+  "B": ["E", "F", "G", "R", "S", "T", "U", "V"],
+  "C": ["E", "X", "Y", "Z"],
+  "D": ["E"]
+ },
+ "frameTable": {
+  "E": "#00: E (E.cpp:99)",
+  "F": "#00: F (F.cpp:99)",
+  "G": "#00: G (G.cpp:99)",
+  "H": "#00: H (H.cpp:99)",
+  "I": "#00: I (I.cpp:99)",
+  "J": "#00: J (J.cpp:99)",
+  "K": "#00: K (K.cpp:99)",
+  "L": "#00: L (L.cpp:99)",
+  "M": "#00: M (M.cpp:99)",
+  "N": "#00: N (N.cpp:99)",
+  "O": "#00: O (O.cpp:99)",
+  "P": "#00: P (P.cpp:99)",
+  "Q": "#00: Q (Q.cpp:99)",
+  "R": "#00: R (R.cpp:99)",
+  "S": "#00: S (S.cpp:99)",
+  "T": "#00: T (T.cpp:99)",
+  "U": "#00: U (U.cpp:99)",
+  "V": "#00: V (V.cpp:99)",
+  "W": "#00: W (W.cpp:99)",
+  "X": "#00: X (X.cpp:99)",
+  "Y": "#00: Y (Y.cpp:99)",
+  "Z": "#00: Z (Z.cpp:99)"
+ }
+}
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-show-all-block-sizes-expected.txt
@@ -0,0 +1,25 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 4093
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  ~15 blocks in heap block record 1 of 1
+  ~1,343,470 bytes (~1,342,313 requested / ~1,157 slop)
+  100.00% of the heap (100.00% cumulative)
+  Individual block sizes: 1,048,576; 65,536 x 3; 40,960; 8,192 x 4; ~4,093 x 6
+  Allocated at {
+    #01: A (A.cpp:99)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: ~1,343,470 bytes in ~15 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-show-all-block-sizes.json
@@ -0,0 +1,35 @@
+{
+ "version": 1,
+ "invocation": {
+  "dmdEnvVar": "1",
+  "sampleBelowSize": 4093
+ },
+ "blockList": [
+  {"req": 1048576, "alloc": "A"},
+
+  {"req": 65536,            "alloc": "A"},
+  {"req": 65535, "slop": 1, "alloc": "A"},
+  {"req": 65534, "slop": 2, "alloc": "A"},
+
+  {"req": 40000, "slop": 960, "alloc": "A"},
+
+  {"req": 8192,              "alloc": "A"},
+  {"req": 8192,              "alloc": "A"},
+  {"req": 8190, "slop":   2, "alloc": "A"},
+  {"req": 8000, "slop": 192, "alloc": "A"},
+
+  {"alloc": "A"},
+  {"alloc": "A"},
+  {"alloc": "A"},
+  {"alloc": "A"},
+  {"alloc": "A"},
+  {"alloc": "A"}
+ ],
+ "traceTable": {
+  "A": ["AA"]
+ },
+ "frameTable": {
+  "AA": "#00: A (A.cpp:99)"
+ }
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-sort-by-req-expected.txt
@@ -0,0 +1,42 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 1
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  5 blocks in heap block record 1 of 3
+  16,392 bytes (16,392 requested / 0 slop)
+  33.33% of the heap (33.33% cumulative)
+  Allocated at {
+    #01: A (A.cpp:99)
+  }
+}
+
+Live {
+  5 blocks in heap block record 2 of 3
+  16,400 bytes (12,016 requested / 4,384 slop)
+  33.35% of the heap (66.68% cumulative)
+  Allocated at {
+    #01: B (B.cpp:99)
+  }
+}
+
+Live {
+  4 blocks in heap block record 3 of 3
+  16,384 bytes (8,196 requested / 8,188 slop)
+  33.32% of the heap (100.00% cumulative)
+  Allocated at {
+    #01: C (C.cpp:99)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: 49,176 bytes in 14 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-sort-by-slop-expected.txt
@@ -0,0 +1,42 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 1
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  4 blocks in heap block record 1 of 3
+  16,384 bytes (8,196 requested / 8,188 slop)
+  33.32% of the heap (33.32% cumulative)
+  Allocated at {
+    #01: C (C.cpp:99)
+  }
+}
+
+Live {
+  5 blocks in heap block record 2 of 3
+  16,400 bytes (12,016 requested / 4,384 slop)
+  33.35% of the heap (66.67% cumulative)
+  Allocated at {
+    #01: B (B.cpp:99)
+  }
+}
+
+Live {
+  5 blocks in heap block record 3 of 3
+  16,392 bytes (16,392 requested / 0 slop)
+  33.33% of the heap (100.00% cumulative)
+  Allocated at {
+    #01: A (A.cpp:99)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: 49,176 bytes in 14 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-sort-by-usable-expected.txt
@@ -0,0 +1,42 @@
+#-----------------------------------------------------------------
+
+Invocation {
+  $DMD = '1'
+  Sample-below size = 1
+}
+
+#-----------------------------------------------------------------
+
+Live {
+  5 blocks in heap block record 1 of 3
+  16,400 bytes (12,016 requested / 4,384 slop)
+  33.35% of the heap (33.35% cumulative)
+  Allocated at {
+    #01: B (B.cpp:99)
+  }
+}
+
+Live {
+  5 blocks in heap block record 2 of 3
+  16,392 bytes (16,392 requested / 0 slop)
+  33.33% of the heap (66.68% cumulative)
+  Allocated at {
+    #01: A (A.cpp:99)
+  }
+}
+
+Live {
+  4 blocks in heap block record 3 of 3
+  16,384 bytes (8,196 requested / 8,188 slop)
+  33.32% of the heap (100.00% cumulative)
+  Allocated at {
+    #01: C (C.cpp:99)
+  }
+}
+
+#-----------------------------------------------------------------
+
+Summary {
+  Total: 49,176 bytes in 14 blocks
+}
+
new file mode 100644
--- /dev/null
+++ b/memory/replace/dmd/test/script-sort-by.json
@@ -0,0 +1,35 @@
+{
+ "version": 1,
+ "invocation": {
+  "dmdEnvVar": "1",
+  "sampleBelowSize": 1
+ },
+ "blockList": [
+  {"req": 4096, "alloc": "A"},
+  {"req": 4096, "alloc": "A"},
+  {"req": 4096, "alloc": "A"},
+  {"req": 4096, "alloc": "A"},
+  {"req": 8,    "alloc": "A"},
+
+  {"req": 3000, "slop": 1096, "alloc": "B"},
+  {"req": 3000, "slop": 1096, "alloc": "B"},
+  {"req": 3000, "slop": 1096, "alloc": "B"},
+  {"req": 3000, "slop": 1096, "alloc": "B"},
+  {"req": 16,                 "alloc": "B"},
+
+  {"req": 2049, "slop": 2047, "alloc": "C"},
+  {"req": 2049, "slop": 2047, "alloc": "C"},
+  {"req": 2049, "slop": 2047, "alloc": "C"},
+  {"req": 2049, "slop": 2047, "alloc": "C"}
+ ],
+ "traceTable": {
+  "A": ["AA"],
+  "B": ["BB"],
+  "C": ["CC"]
+ },
+ "frameTable": {
+  "AA": "#00: A (A.cpp:99)",
+  "BB": "#00: B (B.cpp:99)",
+  "CC": "#00: C (C.cpp:99)"
+ }
+}
--- a/memory/replace/dmd/test/test_dmd.js
+++ b/memory/replace/dmd/test/test_dmd.js
@@ -1,14 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-*/
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
+"use strict";
+
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components
 
 Cu.import("resource://gre/modules/FileUtils.jsm");
 
 // The xpcshell test harness sets PYTHON so we can read it here.
 let gEnv = Cc["@mozilla.org/process/environment;1"]
              .getService(Ci.nsIEnvironment);
 let gPythonName = gEnv.get("PYTHON");
@@ -20,25 +22,21 @@ if (!gDmdScriptFile.exists()) {
   gDmdScriptFile = FileUtils.getFile("CurWorkD", []);
   while (gDmdScriptFile.path.contains("xpcshell")) {
     gDmdScriptFile = gDmdScriptFile.parent;
   }
   gDmdScriptFile.append("bin");
   gDmdScriptFile.append("dmd.py");
 }
 
-function test(aJsonFile, aKind, aOptions, aN) {
+function test(aJsonFile, aPrefix, aOptions) {
   // DMD writes the JSON files to CurWorkD, so we do likewise here with
   // |actualFile| for consistency. It is removed once we've finished.
-  let expectedFile =
-    FileUtils.getFile("CurWorkD",
-                      ["full-" + aKind + "-expected" + aN + ".txt"]);
-  let actualFile =
-    FileUtils.getFile("CurWorkD",
-                      ["full-" + aKind + "-actual"   + aN + ".txt"]);
+  let expectedFile = FileUtils.getFile("CurWorkD", [aPrefix + "-expected.txt"]);
+  let actualFile   = FileUtils.getFile("CurWorkD", [aPrefix + "-actual.txt"]);
 
   // Run dmd.py on the JSON file, producing |actualFile|.
 
   let pythonFile = new FileUtils.File(gPythonName);
   let pythonProcess = Cc["@mozilla.org/process/util;1"]
                         .createInstance(Components.interfaces.nsIProcess);
   pythonProcess.init(pythonFile);
 
@@ -59,29 +57,65 @@ function test(aJsonFile, aKind, aOptions
   let diffProcess = Cc["@mozilla.org/process/util;1"]
                       .createInstance(Components.interfaces.nsIProcess);
   // XXX: this doesn't work on Windows (bug 1076446).
   diffProcess.init(diffFile);
 
   args = ["-u", expectedFile.path, actualFile.path];
   diffProcess.run(/* blocking = */true, args, args.length);
   let success = diffProcess.exitValue == 0;
-  ok(success, aKind + " " + aN);
+  ok(success, aPrefix);
 
   actualFile.remove(true);
 }
 
 function run_test() {
+  let jsonFile;
+
   // These tests do full end-to-end testing of DMD, i.e. both the C++ code that
   // generates the JSON output, and the script that post-processes that output.
   // The test relies on DMD's test mode executing beforehand, in order to
   // produce the relevant JSON files.
   //
   // Run these synchronously, because test() updates the full*.json files
   // in-place (to fix stacks) when it runs dmd.py, and that's not safe to do
   // asynchronously.
-  for (let i = 1; i <= 4; i++) {
-      let jsonFile = FileUtils.getFile("CurWorkD", ["full" + i + ".json"]);
-      test(jsonFile, "heap", ["--ignore-reports"], i);
-      test(jsonFile, "reports", [], i);
+  let fullTestNames = ["empty", "unsampled1", "unsampled2", "sampled"];
+  for (let i = 0; i < fullTestNames.length; i++) {
+      let name = fullTestNames[i];
+      jsonFile = FileUtils.getFile("CurWorkD", ["full-" + name + ".json"]);
+      test(jsonFile, "full-heap-" + name, ["--ignore-reports"])
+      test(jsonFile, "full-reports-" + name, [])
       jsonFile.remove(true);
   }
+
+  // These tests only test the post-processing script. They use hand-written
+  // JSON files as input. Ideally the JSON files would contain comments
+  // explaining how they work, but JSON doesn't allow comments, so I've put
+  // explanations here.
+
+  // This just tests that stack traces of various lengths are truncated
+  // appropriately. The number of records in the output is different for each
+  // of the tested values.
+  jsonFile = FileUtils.getFile("CurWorkD", ["script-max-frames.json"]);
+  test(jsonFile, "script-max-frames-8", ["-r", "--max-frames=8"]);
+  test(jsonFile, "script-max-frames-3", ["-r", "--max-frames=3",
+                                         "--no-fix-stacks"]);
+  test(jsonFile, "script-max-frames-1", ["-r", "--max-frames=1"]);
+
+  // This test has three records that are shown in a different order for each
+  // of the different sort values.
+  jsonFile = FileUtils.getFile("CurWorkD", ["script-sort-by.json"]);
+  test(jsonFile, "script-sort-by-usable", ["-r", "--sort-by=usable"]);
+  test(jsonFile, "script-sort-by-req",    ["-r", "--sort-by=req",
+                                           "--no-fix-stacks"]);
+  test(jsonFile, "script-sort-by-slop",   ["-r", "--sort-by=slop"]);
+
+  // This test has several real stack traces taken from Firefox execution, each
+  // of which tests a different allocator function (or functions).
+  jsonFile = FileUtils.getFile("CurWorkD", ["script-ignore-alloc-fns.json"]);
+  test(jsonFile, "script-ignore-alloc-fns", ["-r", "--ignore-alloc-fns"]);
+
+  // This test has numerous allocations of different sizes, some repeated, some
+  // sampled, that all end up in the same record.
+  jsonFile = FileUtils.getFile("CurWorkD", ["script-show-all-block-sizes.json"]);
+  test(jsonFile, "script-show-all-block-sizes", ["-r", "--show-all-block-sizes"]);
 }
--- a/memory/replace/dmd/test/xpcshell.ini
+++ b/memory/replace/dmd/test/xpcshell.ini
@@ -1,16 +1,28 @@
 [DEFAULT]
 support-files =
-  full-heap-expected1.txt
-  full-heap-expected2.txt
-  full-heap-expected3.txt
-  full-heap-expected4.txt
-  full-reports-expected1.txt
-  full-reports-expected2.txt
-  full-reports-expected3.txt
-  full-reports-expected4.txt
+  full-heap-empty-expected.txt
+  full-heap-unsampled1-expected.txt
+  full-heap-unsampled2-expected.txt
+  full-heap-sampled-expected.txt
+  full-reports-empty-expected.txt
+  full-reports-unsampled1-expected.txt
+  full-reports-unsampled2-expected.txt
+  full-reports-sampled-expected.txt
+  script-max-frames.json
+  script-max-frames-8-expected.txt
+  script-max-frames-3-expected.txt
+  script-max-frames-1-expected.txt
+  script-sort-by.json
+  script-sort-by-usable-expected.txt
+  script-sort-by-req-expected.txt
+  script-sort-by-slop-expected.txt
+  script-ignore-alloc-fns.json
+  script-ignore-alloc-fns-expected.txt
+  script-show-all-block-sizes.json
+  script-show-all-block-sizes-expected.txt
 
 # Bug 1077230 explains why this test is disabled on Mac 10.6.
 # Bug 1076446 is open for getting this test working on on Windows.
 [test_dmd.js]
 dmd = true
 run-if = os == 'linux' || os == 'mac' && os_version != '10.6'