Merge "[534409] Failure running collections test under Java 9"
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KeySetCollectionExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KeySetCollectionExtractor.java
new file mode 100644
index 0000000..94907e8
--- /dev/null
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KeySetCollectionExtractor.java
@@ -0,0 +1,52 @@
+/*******************************************************************************

+ * Copyright (c) 2018 IBM Corporation.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    IBM Corporation/Andrew Johnson - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.mat.internal.collectionextract;

+

+import java.util.Map.Entry;

+

+import org.eclipse.mat.SnapshotException;

+import org.eclipse.mat.collect.ArrayInt;

+import org.eclipse.mat.inspections.collectionextract.ExtractedMap;

+import org.eclipse.mat.inspections.collectionextract.IMapExtractor;

+import org.eclipse.mat.snapshot.model.IObject;

+import org.eclipse.mat.snapshot.model.IObjectArray;

+

+public class KeySetCollectionExtractor extends WrapperMapExtractor

+{

+    public KeySetCollectionExtractor(String field)

+    {

+        super(field);

+    }

+

+    public int[] extractEntryIds(IObject coll) throws SnapshotException

+    {

+        ExtractedMap em = extractMap(coll);

+        ArrayInt a = new ArrayInt();

+        if (em != null)

+        {

+            for (Entry<IObject,IObject>en : em)

+            {

+                a.add(en.getKey().getObjectId());

+            }

+        }

+        return a.toArray();

+    }

+

+    public boolean hasExtractableArray()

+    {

+        return false;

+    }

+    

+    public IObjectArray extractEntries(IObject coll) throws SnapshotException

+    {

+        throw new UnsupportedOperationException();

+    }

+}

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java
index bc7a9f4..9d68510 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java
@@ -37,7 +37,7 @@
     private static CollectionExtractionInfo[] knownCollections = new CollectionExtractionInfo[] {
                     // these are always empty
                     new CollectionExtractionInfo("java.util.Collections$EmptyList", new EmptyCollectionExtractor()), //$NON-NLS-1$
-                    new CollectionExtractionInfo("java.util.Collections$EmptySet", new EmptyCollectionExtractor()), //$NON-NLS-1$
+                    new CollectionExtractionInfo("java.util.Collections$EmptySet", new EmptyMapExtractor()), //$NON-NLS-1$
                     new CollectionExtractionInfo("java.util.Collections$EmptyMap", new EmptyMapExtractor()), //$NON-NLS-1$
                     new CollectionExtractionInfo("com.sap.engine.lib.util.AbstractDataStructure", new EmptyCollectionExtractor()), //$NON-NLS-1$
                     new CollectionExtractionInfo("java.util.concurrent.SynchronousQueue", new EmptyCollectionExtractor()), //$NON-NLS-1$
@@ -81,10 +81,16 @@
                     new CollectionExtractionInfo("java.util.IdentityHashMap", JdkVersion.except(IBM14, IBM15, IBM16), new IdentityHashMapCollectionExtractor("size", "table")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.IdentityHashMap", JdkVersion.of(IBM14, IBM15), new IdentityHashMapCollectionExtractor("size", "table")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.IdentityHashMap", IBM16, new IdentityHashMapCollectionExtractor("size", "elementData")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                    new CollectionExtractionInfo("java.util.IdentityHashMap$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.IdentityHashMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // hash maps
                     new CollectionExtractionInfo("java.util.HashMap", JdkVersion.except(IBM16), new HashMapCollectionExtractor("size", "table", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.HashMap", IBM16, new HashMapCollectionExtractor("elementCount", "elementData", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+                    new CollectionExtractionInfo("java.util.HashMap$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.HashMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.LinkedHashMap$LinkedKeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.LinkedHashMap$LinkedValues", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // Some Java 5 PHD files don't have superclass info so add
                     // LinkedHashMap to list
@@ -123,6 +129,8 @@
                     new CollectionExtractionInfo("java.util.Hashtable", JdkVersion.except(IBM15, IBM16), new HashMapCollectionExtractor("count", "table", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.Hashtable", JdkVersion.of(IBM15, IBM16), // //$NON-NLS-1$
                                     new HashMapCollectionExtractor("elementCount", "elementData", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                    new CollectionExtractionInfo("java.util.Hashtable$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.Hashtable$ValueCollection", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // Some Java 5 PHD files don't have superclass info so add
                     // Properties to list
@@ -132,6 +140,9 @@
 
                     new CollectionExtractionInfo("java.util.WeakHashMap", JdkVersion.except(IBM16), new HashMapCollectionExtractor("size", "table", "referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.WeakHashMap", IBM16, new HashMapCollectionExtractor("elementCount", "elementData", "referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+                    new CollectionExtractionInfo("java.util.WeakHashMap$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.WeakHashMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("sun.awt.WeakIdentityHashMap",  new HashMapCollectionExtractor("map.size", "map.table", "key.referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
 
                     new CollectionExtractionInfo("java.lang.ThreadLocal$ThreadLocalMap", // //$NON-NLS-1$
                                     new HashMapCollectionExtractor("size", "table", "referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -142,17 +153,23 @@
                     // small maps.
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap", JdkVersion.of(JAVA18, IBM18, JAVA19, IBM19), new HashMapCollectionExtractor("baseCount", "table", "key", "val")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap", JdkVersion.except(JAVA18, IBM18, JAVA19, IBM19), new ConcurrentHashMapCollectionExtractor("segments", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$KeySetView", new KeySetCollectionExtractor("map")),
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$ValuesView", new ValuesCollectionExtractor("map")),
 
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListSet", //$NON-NLS-1$
                                     new ConcurrentSkipListSetCollectionExtractor("m.head.node", "key", "value")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap", //$NON-NLS-1$
                                     new ConcurrentSkipListCollectionExtractor("head.node", "key", "value")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap$KeySet", new KeySetCollectionExtractor("map")),
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap$Values", new ValuesCollectionExtractor("map")),
 
                     // tree maps
                     new CollectionExtractionInfo("java.util.TreeMap", JdkVersion.except(IBM16), new TreeMapCollectionExtractor("size", "key", "value")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                     new CollectionExtractionInfo("java.util.TreeMap", IBM16, new TreeMapCollectionExtractor("size", "keys[]", "values[]")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                     new CollectionExtractionInfo("java.util.TreeSet", JdkVersion.except(IBM16), new TreeSetCollectionExtractor("m.size", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                     new CollectionExtractionInfo("java.util.TreeSet", IBM16, new TreeSetCollectionExtractor("backingMap.size", "keys[]", "values[]")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                    new CollectionExtractionInfo("java.util.TreeMap$KeySet", new KeySetCollectionExtractor("m")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.TreeMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // wrappers
                     // also works for SynchronizedSet, SynchronizedSortedSet,
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/ValuesCollectionExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/ValuesCollectionExtractor.java
new file mode 100644
index 0000000..3214c06
--- /dev/null
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/ValuesCollectionExtractor.java
@@ -0,0 +1,57 @@
+package org.eclipse.mat.internal.collectionextract;

+

+import java.util.Map.Entry;

+

+import org.eclipse.mat.SnapshotException;

+import org.eclipse.mat.collect.ArrayInt;

+import org.eclipse.mat.inspections.collectionextract.ExtractedMap;

+import org.eclipse.mat.inspections.collectionextract.ICollectionExtractor;

+import org.eclipse.mat.snapshot.model.IObject;

+import org.eclipse.mat.snapshot.model.IObjectArray;

+

+/*******************************************************************************

+ * Copyright (c) 2018 IBM Corporation.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    IBM Corporation/Andrew Johnson - initial API and implementation

+ *******************************************************************************/

+public class ValuesCollectionExtractor extends WrapperCollectionExtractor

+{

+    public ValuesCollectionExtractor(String field)

+    {

+        this(field, null);

+    }

+

+    public ValuesCollectionExtractor(String field, ICollectionExtractor extractor)

+    {

+        super(field, extractor);

+    }

+

+    public int[] extractEntryIds(IObject coll) throws SnapshotException

+    {

+        ExtractedMap em = extractMap(coll);

+        ArrayInt a = new ArrayInt();

+        if (em != null)

+        {

+            for (Entry<IObject,IObject>en : em)

+            {

+                a.add(en.getValue().getObjectId());

+            }

+        }

+        return a.toArray();

+    }

+

+    public boolean hasExtractableArray()

+    {

+        return false;

+    }

+    

+    public IObjectArray extractEntries(IObject coll) throws SnapshotException

+    {

+        throw new UnsupportedOperationException();

+    }

+}

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java
index e298a1e..de51500 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java
@@ -11,6 +11,7 @@
  *******************************************************************************/

 package org.eclipse.mat.tests;

 

+import java.lang.reflect.Array;

 import java.lang.reflect.Constructor;

 import java.lang.reflect.InvocationTargetException;

 import java.lang.reflect.Method;

@@ -45,11 +46,16 @@
 public class CreateCollectionDump

 {

     ListCollectionTestData listCollectionTestData = new ListCollectionTestData();

+    ListCollectionTestData listCollectionTestData2;

     NonListCollectionTestData nonListCollectionTestData = new NonListCollectionTestData();

+    NonListCollectionTestData nonListCollectionTestData2;

     MapTestData mapTestData = new MapTestData();

     EmptyListCollectionTestData emptyListCollectionTestData = new EmptyListCollectionTestData();

+    EmptyListCollectionTestData emptyListCollectionTestData2;

     EmptyNonListCollectionTestData emptyNonListCollectionTestData = new EmptyNonListCollectionTestData();

+    EmptyNonListCollectionTestData emptyNonListCollectionTestData2;

     EmptyMapTestData emptyMapTestData = new EmptyMapTestData();

+

     // Add Strings for testing class specific name printing

     String s1 = "My String";

     StringBuilder sl1 = new StringBuilder(s1);

@@ -58,6 +64,56 @@
     StringBuilder sl2 = new StringBuilder(s2);

     StringBuffer sf2 = new StringBuffer(s2);

 

+    public CreateCollectionDump()

+    {

+        // Extend the collections

+        List<Collection>l0 = new ArrayList<Collection>();

+        for (Map m : mapTestData.maps)

+        {

+            Collection c = m.values();

+            if (c.size() == mapTestData.COUNT && c.iterator().next() instanceof String)

+            {

+                l0.add(c);

+            }

+        }

+        listCollectionTestData2 = new ListCollectionTestData(l0);

+

+        l0.clear();

+        for (Map m : mapTestData.maps)

+        {

+            Set s = m.keySet();

+            if (s.size() == mapTestData.COUNT && s.iterator().next() instanceof String)

+            {

+                l0.add(s);

+                //l0.add(m.entrySet());

+            }

+        }

+        nonListCollectionTestData2 = new NonListCollectionTestData(l0);

+        

+        l0.clear();

+        for (Map m : emptyMapTestData.maps)

+        {

+            Collection c = m.values();

+            if (c.size() == mapTestData.COUNT)

+            {

+                l0.add(c);

+            }

+        }

+        emptyListCollectionTestData2 = new EmptyListCollectionTestData(l0);

+        

+        l0.clear();

+        for (Map m : emptyMapTestData.maps)

+        {

+            Set s = m.keySet();

+            if (s.size() == mapTestData.COUNT)

+            {

+                l0.add(s);

+                //l0.add(m.entrySet());

+            }

+        }

+        emptyNonListCollectionTestData2 = new EmptyNonListCollectionTestData(l0);

+    }

+

     public static void main(String[] args) throws Exception

     {

         CreateCollectionDump cd = new CreateCollectionDump();

@@ -133,6 +189,11 @@
 

         public abstract boolean accept(Class<? extends Collection> c);

 

+        public CollectionTestData(Collection<Collection> cols)

+        {

+            collections = cols.toArray(new Collection[cols.size()]);

+        }

+

         public CollectionTestData()

         {

             List<Collection>cols = new ArrayList<Collection>();

@@ -439,6 +500,14 @@
             collections = cols.toArray(new Collection[cols.size()]);

         }

 

+        public void extend(List<Collection>ext)

+        {

+            List<Collection>l0 = Arrays.asList(collections);

+            ArrayList<Collection> l1 = new ArrayList<Collection>(l0);

+            l1.addAll(ext);

+            collections = l1.toArray(new Collection[l1.size()]);

+        }

+

         public String toString()

         {

             return Arrays.toString(collections);

@@ -455,6 +524,15 @@
      */

     public static class NonListCollectionTestData extends CollectionTestData

     {

+        public NonListCollectionTestData()

+        {

+            super();

+        }

+        public NonListCollectionTestData(Collection<Collection>cols)

+        {

+            super(cols);

+        }

+

         public boolean accept(Class<? extends Collection> c)

         {

             return !List.class.isAssignableFrom(c);

@@ -466,6 +544,15 @@
      */

     public static class EmptyNonListCollectionTestData extends NonListCollectionTestData

     {

+        public EmptyNonListCollectionTestData()

+        {

+            super();

+        }

+        public EmptyNonListCollectionTestData(Collection<Collection>cols)

+        {

+            super(cols);

+        }

+

         public boolean useEmpty()

         {

             return true;

@@ -477,6 +564,14 @@
      */

     public static class ListCollectionTestData extends CollectionTestData

     {

+        public ListCollectionTestData()

+        {

+            super();

+        }

+        public ListCollectionTestData(Collection<Collection>cols)

+        {

+            super(cols);

+        }

 

         public boolean accept(Class<? extends Collection> c)

         {

@@ -489,6 +584,15 @@
      */

     public static class EmptyListCollectionTestData extends ListCollectionTestData

     {

+        public EmptyListCollectionTestData()

+        {

+            super();

+        }

+        public EmptyListCollectionTestData(Collection<Collection>cols)

+        {

+            super(cols);

+        }

+

         public boolean useEmpty()

         {

             return true;

@@ -725,7 +829,13 @@
                                 try

                                 {

                                     // javax.print.attribute.standard.PrinterStateReasons

-                                    cl.put(PrinterStateReason.CONNECTING_TO_DEVICE, Severity.REPORT);

+                                    for (int i = 1; i <= COUNT; ++i)

+                                    {

+                                        PrinterStateReason r = new PrinterStateReason(i)

+                                        {

+                                        };

+                                        cl.put(r, Severity.REPORT);

+                                    }

                                 }

                                 catch (UnsupportedOperationException e)

                                 {

@@ -740,7 +850,10 @@
                                 try

                                 {

                                     // java.util.jar.Attributes

-                                    cl.put(Attributes.Name.CLASS_PATH, values[1]);

+                                    for (int i = 1; i <= COUNT; ++i)

+                                    {

+                                        cl.put(new Attributes.Name(keys[i]), values[i]);

+                                    }

                                 }

                                 catch (UnsupportedOperationException e)

                                 {

@@ -808,12 +921,20 @@
 

     public Collection[] getListCollectionTestData()

     {

-        return listCollectionTestData.getCollections();

+        List<Collection>l1 = Arrays.asList(listCollectionTestData.getCollections());

+        List<Collection>l2 = Arrays.asList(listCollectionTestData2.getCollections());

+        ArrayList<Collection>l3 = new ArrayList<Collection>(l1);

+        l3.addAll(l2);

+        return l3.toArray(new Collection[l3.size()]);

     }

 

     public Collection[] getNonListCollectionTestData()

     {

-        return nonListCollectionTestData.getCollections();

+        List<Collection>l1 = Arrays.asList(nonListCollectionTestData.getCollections());

+        List<Collection>l2 = Arrays.asList(nonListCollectionTestData2.getCollections());

+        ArrayList<Collection>l3 = new ArrayList<Collection>(l1);

+        l3.addAll(l2);

+        return l3.toArray(new Collection[l3.size()]);

     }

 

     public Map[] getMapTestData()

@@ -823,12 +944,20 @@
 

     public Collection[] getEmptyListCollectionTestData()

     {

-        return emptyListCollectionTestData.getCollections();

+        List<Collection>l1 = Arrays.asList(emptyListCollectionTestData.getCollections());

+        List<Collection>l2 = Arrays.asList(emptyListCollectionTestData2.getCollections());

+        ArrayList<Collection>l3 = new ArrayList<Collection>(l1);

+        l3.addAll(l2);

+        return l3.toArray(new Collection[l3.size()]);

     }

 

     public Collection[] getEmptyNonListCollectionTestData()

     {

-        return emptyNonListCollectionTestData.getCollections();

+        List<Collection>l1 = Arrays.asList(emptyNonListCollectionTestData.getCollections());

+        List<Collection>l2 = Arrays.asList(emptyNonListCollectionTestData2.getCollections());

+        ArrayList<Collection>l3 = new ArrayList<Collection>(l1);

+        l3.addAll(l2);

+        return l3.toArray(new Collection[l3.size()]);

     }

 

     public Map[] getEmptyMapTestData()

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java
index c41c3ed..f18f801 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java
@@ -42,7 +42,7 @@
     @Rule

     public ErrorCollector collector = new ErrorCollector();

 

-    void checkListObjects(long objAddress, int numEntries, ISnapshot snapshot) throws SnapshotException

+    void checkListObjects(long objAddress, int numEntries, boolean checkVals, ISnapshot snapshot) throws SnapshotException

     {

         IObject obj = snapshot.getObject(snapshot.mapAddressToId(objAddress));

         String prefix = obj.getTechnicalName()+": ";

@@ -70,9 +70,12 @@
                     String cv = lobj.getClassSpecificName();

                     if (cv != null)

                     {

-                        collector.checkThat(prefix + "List entry should start with the type", cv, startsWith(name));

+                        if (checkVals)

+                        {

+                            collector.checkThat(prefix + "List entry should start with the type", cv, startsWith(name));

+                        }

                         collector.checkThat(prefix + "Should end with number or aAbB: " + cv,

-                                    cv.matches(".*:([0-9]+|[aAbB]+)$"), equalTo(true));

+                                    cv.matches(".*([0-9]+|[aAbB]+)$"), equalTo(true));

                     }

                     else

                     {

@@ -94,7 +97,7 @@
      * @param snapshot

      * @throws SnapshotException

      */

-    protected void checkHashSetObjects(long objAddress, int numEntries, ISnapshot snapshot) throws SnapshotException

+    protected void checkHashSetObjects(long objAddress, int numEntries, boolean checkVals, ISnapshot snapshot) throws SnapshotException

     {

         IObject obj = snapshot.getObject(snapshot.mapAddressToId(objAddress));

         String prefix = obj.getTechnicalName()+": ";

@@ -123,9 +126,12 @@
                     String cv = cobj.getClassSpecificName();

                     if (cv != null)

                     {

-                        collector.checkThat(prefix + "Hash set entry should start with the type", cv, startsWith(name));

+                        if (checkVals)

+                        {

+                            collector.checkThat(prefix + "Hash set entry should start with the type", cv, startsWith(name));

+                        }

                         collector.checkThat(prefix + "Should end with number or aAbB: " + cv,

-                                    cv.matches(".*:([0-9]+|[aAbB]+)$"), equalTo(true));

+                                    cv.matches(".*([0-9]+|[aAbB]+)$"), equalTo(true));

                     }

                     else

                     {

@@ -254,10 +260,10 @@
         checkMapCollisionRatio(objAddress, numEntries, snapshot);

     }

 

-    protected void checkList(long objAddress, int numEntries, ISnapshot snapshot) throws SnapshotException

+    protected void checkList(long objAddress, int numEntries, boolean checkVals, ISnapshot snapshot) throws SnapshotException

     {

         checkCollectionSize(objAddress, numEntries, snapshot);

-        checkListObjects(objAddress, numEntries, snapshot);

+        checkListObjects(objAddress, numEntries, checkVals, snapshot);

     }

 

     /**

@@ -276,7 +282,8 @@
         IResultTable table2 = (IResultTable) result2;

         int rowCount2 = table2.getRowCount();

         String className = snapshot.getClassOf(snapshot.mapAddressToId(objAddress)).getName();

-        if (className.equals("java.util.TreeMap") || className.equals("java.util.concurrent.ConcurrentSkipListMap") ||

+        if (className.equals("java.util.TreeMap") || className.equals("java.util.TreeMap$KeySet") || 

+            className.equals("java.util.concurrent.ConcurrentSkipListMap") ||  className.equals("java.util.concurrent.ConcurrentSkipListMap$KeySet") ||

             className.equals("java.util.TreeSet") || className.equals("java.util.concurrent.ConcurrentSkipListSet"))

         {

             // TreeMaps and ConcurrentSkipListMap don't appear in the fill ratio report as they

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java
index ac0aee9..7bdd7c1 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java
@@ -10,6 +10,9 @@
  *******************************************************************************/

 package org.eclipse.mat.tests.collect;

 

+import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;

+import static org.junit.Assert.assertThat;

+

 import org.eclipse.mat.SnapshotException;

 import org.eclipse.mat.snapshot.ISnapshot;

 import org.eclipse.mat.snapshot.model.IArray;

@@ -45,13 +48,17 @@
      */

     public void testCollections1(ISnapshot snapshot, String onlyClass) throws SnapshotException

     {

+        int objectsFound = 0;

         for (IClass cls : snapshot.getClassesByName(org.eclipse.mat.tests.CreateCollectionDump.ListCollectionTestData.class.getName(), false)) {

             for (int o : cls.getObjectIds()) {

                 IObject oo = snapshot.getObject(o);

                 IArray a = collectionArray(oo);

+                IArray v = valueArray(oo);

+                boolean checkVals = v != null;

                 for (NamedReference nr : a.getOutboundReferences()) {

                     if (nr.getName().startsWith("<")) continue;

                     if (skipTest(nr, onlyClass)) continue;

+                    ++objectsFound;

                     long objAddress = nr.getObjectAddress();

                     Integer numEntriesI = (Integer)cls.getSuperClass().resolveValue("COUNT");

                     int numEntries;

@@ -63,10 +70,11 @@
                     String name = nr.getObject().getClazz().getName();

                     if (name.contains("Singleton"))

                         numEntries = 1;

-                    checkList(objAddress, numEntries, snapshot);

+                    checkList(objAddress, numEntries, checkVals, snapshot);

                 }

             }

         }

+        assertThat("At least 1 object found"+(onlyClass != null ? " of type "+onlyClass : ""), objectsFound, greaterThanOrEqualTo(1));

     }

 

     private IArray collectionArray(IObject obj) throws SnapshotException

@@ -74,6 +82,16 @@
         return readArrayField(obj, "collections", "java.util.Collection[]");

     }

 

+    private IArray mapArray(IObject obj) throws SnapshotException

+    {

+        return readArrayField(obj, "maps", "java.util.Map[]");

+    }

+

+    private IArray valueArray(IObject obj) throws SnapshotException

+    {

+        return readArrayField(obj, "values", "java.lang.String[]");

+    }

+

     private IArray readArrayField(IObject obj, String fieldName, String valueType) throws SnapshotException

         {

         IArray a = (IArray)obj.resolveValue(fieldName);

@@ -104,14 +122,18 @@
      */

     public void testCollections2(ISnapshot snapshot, String onlyClass) throws SnapshotException

     {

+        int objectsFound = 0;

         for (IClass cls : snapshot.getClassesByName(org.eclipse.mat.tests.CreateCollectionDump.NonListCollectionTestData.class.getName(), false))

         {

             for (int o : cls.getObjectIds()) {

                 IObject oo = snapshot.getObject(o);

                 IArray a = collectionArray(oo);

+                IArray v = valueArray(oo);

+                boolean checkVals = v != null;

                 for (NamedReference nr : a.getOutboundReferences()) {

                     if (nr.getName().startsWith("<")) continue;

                     if (skipTest(nr, onlyClass)) continue;

+                    ++objectsFound;

                     long objAddress = nr.getObjectAddress();

                     Integer numEntriesI = (Integer)cls.getSuperClass().resolveValue("COUNT");

                     int numEntries;

@@ -142,17 +164,18 @@
                         {

                             checkHashEntries(objAddress, numEntries, snapshot, false);

                             checkMapCollisionRatio(objAddress, numEntries, snapshot);

-                            checkHashSetObjects(objAddress, numEntries, snapshot);

+                            checkHashSetObjects(objAddress, numEntries, checkVals, snapshot);

                         }

                         else

                         {

                             // Other queries also work with list_entries

-                            checkList(objAddress, numEntries, snapshot);

+                            checkList(objAddress, numEntries, checkVals, snapshot);

                         }

                     }

                 }

             }

         }

+        assertThat("At least 1 object found"+(onlyClass != null ? " of type "+onlyClass : ""), objectsFound, greaterThanOrEqualTo(1));

     }

 

     /**

@@ -161,22 +184,27 @@
      */

     public void testCollections3(ISnapshot snapshot, String onlyClass) throws SnapshotException

     {

+        int objectsFound = 0;

         for (IClass cls : snapshot.getClassesByName(org.eclipse.mat.tests.CreateCollectionDump.EmptyListCollectionTestData.class.getName(), false))

         {

             for (int o : cls.getObjectIds())

             {

                 IObject oo = snapshot.getObject(o);

                 IArray a = collectionArray(oo);

+                IArray v = valueArray(oo);

+                boolean checkVals = v != null;

                 for (NamedReference nr : a.getOutboundReferences())

                 {

                     if (nr.getName().startsWith("<")) continue;

                     if (skipTest(nr, onlyClass)) continue;

+                    ++objectsFound;

                     long objAddress = nr.getObjectAddress();

                     int numEntries = 0;

-                    checkList(objAddress, numEntries, snapshot);

+                    checkList(objAddress, numEntries, checkVals, snapshot);

                 }

             }

         }

+        assertThat("At least 1 object found"+(onlyClass != null ? " of type "+onlyClass : ""), objectsFound, greaterThanOrEqualTo(1));

     }

 

     /**

@@ -185,17 +213,20 @@
      */

     public void testCollections4(ISnapshot snapshot, String onlyClass) throws SnapshotException

     {

-

+        int objectsFound = 0;

         for (IClass cls : snapshot.getClassesByName(org.eclipse.mat.tests.CreateCollectionDump.EmptyNonListCollectionTestData.class.getName(), false))

         {

             for (int o : cls.getObjectIds())

             {

                 IObject oo = snapshot.getObject(o);

                 IArray a = collectionArray(oo);

+                IArray v = valueArray(oo);

+                boolean checkVals = v != null;

                 for (NamedReference nr : a.getOutboundReferences())

                 {

                     if (nr.getName().startsWith("<")) continue;

                     if (skipTest(nr, onlyClass)) continue;

+                    ++objectsFound;

                     long objAddress = nr.getObjectAddress();

                     int numEntries = 0;

                     checkCollectionSize(objAddress, numEntries, snapshot);

@@ -205,11 +236,12 @@
                     {

                         checkCollectionFillRatio(objAddress, numEntries, snapshot);

                         checkMapCollisionRatio(objAddress, numEntries, snapshot);

-                        checkHashSetObjects(objAddress, numEntries, snapshot);

+                        checkHashSetObjects(objAddress, numEntries, checkVals, snapshot);

                     }

                 }

             }

         }

+        assertThat("At least 1 object found"+(onlyClass != null ? " of type "+onlyClass : ""), objectsFound, greaterThanOrEqualTo(1));

     }

 

     /**

@@ -218,17 +250,21 @@
      */

     public void testCollections5(ISnapshot snapshot, String onlyClass) throws SnapshotException

     {

+        int objectsFound = 0;

         for (IClass cls : snapshot.getClassesByName(org.eclipse.mat.tests.CreateCollectionDump.MapTestData.class.getName(), false))

         {

             for (int o : cls.getObjectIds())

             {

                 IObject oo = snapshot.getObject(o);

-                IArray a = readArrayField(oo, "maps", "java.util.Map[]");

+                IArray a = mapArray(oo);

+                IArray v = valueArray(oo);

+                boolean checkVals = v != null;

                 for (NamedReference nr : a.getOutboundReferences())

                 {

                     if (nr.getName().startsWith("<"))

                         continue;

                     if (skipTest(nr, onlyClass)) continue;

+                    ++objectsFound;

                     long objAddress = nr.getObjectAddress();

                     Integer numEntriesI = (Integer)cls.resolveValue("COUNT");

                     int numEntries;

@@ -243,8 +279,8 @@
                     if (nm.equals("javax.print.attribute.standard.PrinterStateReasons")

                                     || nm.equals("java.util.jar.Attributes"))

                     {

-                        // These maps just have one entry

-                        checkMap(objAddress, 1, snapshot);

+                        // These maps don't have string keys and values

+                        checkMap(objAddress, numEntries, snapshot);

                     }

                     else

                     {

@@ -254,6 +290,7 @@
                 }

             }

         }

+        assertThat("At least 1 object found"+(onlyClass != null ? " of type "+onlyClass : ""), objectsFound, greaterThanOrEqualTo(1));

     }

 

     /**

@@ -262,15 +299,19 @@
      */

     public void testCollections6(ISnapshot snapshot, String onlyClass) throws SnapshotException

     {

+        int objectsFound = 0;

         for (IClass cls : snapshot.getClassesByName(org.eclipse.mat.tests.CreateCollectionDump.EmptyMapTestData.class.getName(), false))

         {

             for (int o : cls.getObjectIds()) {

                 IObject oo = snapshot.getObject(o);

-                IArray a = readArrayField(oo, "maps", "java.util.Map[]");

+                IArray a = mapArray(oo);

+                IArray v = valueArray(oo);

+                boolean checkVals = v != null;

                 for (NamedReference nr : a.getOutboundReferences())

                 {

                     if (nr.getName().startsWith("<")) continue;

                     if (skipTest(nr, onlyClass)) continue;

+                    ++objectsFound;

                     long objAddress = nr.getObjectAddress();

                     int numEntries = 0;

                     checkHashEntries(objAddress, numEntries, snapshot, true);

@@ -278,5 +319,6 @@
                 }

             }

         }

+        assertThat("At least 1 object found"+(onlyClass != null ? " of type "+onlyClass : ""), objectsFound, greaterThanOrEqualTo(1));

     }

 }

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest3.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest3.java
index c0d27e7..9feaaeb 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest3.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest3.java
@@ -115,7 +115,7 @@
                     }

                     // List collections

                     String dmppath = dmp.getAbsolutePath();

-                    String dmpname = hdp.getClass().getSimpleName()+" "+dmp.getName();

+                    String dmpname = hdp.getClass().getName()+" "+dmp.getName();

                     for (Collection c : cdp.getListCollectionTestData())

                     {

                         Object[] objects = new Object[] { dmppath, dmpname, 1, c.getClass().getName() };

@@ -234,7 +234,7 @@
                 break;

             case 4:

                 assumeThat(type, equalTo(4));

-                testCollections3(TestSnapshots.getSnapshot(snapfile,false), classname);

+                testCollections4(TestSnapshots.getSnapshot(snapfile,false), classname);

                 break;

             case 5:

                 assumeThat(type, equalTo(5));