Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Johnson2018-11-17 20:59:27 +0000
committerAndrew Johnson2018-11-17 21:04:55 +0000
commitd6dfde22ff326ebad0eb3aac56dfb2859bb012af (patch)
tree7cf5048886731573958296c0e742b010dc7fd54a
parent6d4ebc00331521a2ce447253da8e8762581c5168 (diff)
downloadorg.eclipse.mat-d6dfde22ff326ebad0eb3aac56dfb2859bb012af.tar.gz
org.eclipse.mat-d6dfde22ff326ebad0eb3aac56dfb2859bb012af.tar.xz
org.eclipse.mat-d6dfde22ff326ebad0eb3aac56dfb2859bb012af.zip
[541245] Exceptions with result filtering
Extra numeric filters, fix bugs for incomplete filters and Bytes type. Change-Id: Idc72b65002baf804d51d6aae095341d6321d68d1
-rw-r--r--plugins/org.eclipse.mat.report/src/org/eclipse/mat/query/refined/Filter.java69
-rw-r--r--plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/Params.java16
-rw-r--r--plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/messages.properties3
-rw-r--r--plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/snapshot/QueriesTest.java532
-rw-r--r--plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.dita3
-rw-r--r--plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.html68
6 files changed, 644 insertions, 47 deletions
diff --git a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/query/refined/Filter.java b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/query/refined/Filter.java
index eb90b54b..67ae144c 100644
--- a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/query/refined/Filter.java
+++ b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/query/refined/Filter.java
@@ -7,7 +7,7 @@
*
* Contributors:
* SAP AG - initial API and implementation
- * IBM Corporation/Andrew Johnson - Javadoc updates
+ * IBM Corporation/Andrew Johnson - Javadoc updates and Bytes + filters
*******************************************************************************/
package org.eclipse.mat.query.refined;
@@ -17,6 +17,7 @@ import java.text.ParsePosition;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import org.eclipse.mat.query.Bytes;
import org.eclipse.mat.query.Column;
import org.eclipse.mat.report.internal.Messages;
import org.eclipse.mat.util.MessageUtil;
@@ -128,14 +129,16 @@ public abstract class Filter
@Override
boolean accept(Object value)
{
- if (value == null)
- return false;
-
- double doubleValue = value instanceof Number ? ((Number) value).doubleValue() : Double.NaN;
+ // Experiment: Let null values be converted here to NaN, which will normally fail the accept() test
+ double doubleValue = value instanceof Bytes ? ((Bytes)value).getValue() : value instanceof Number ? ((Number) value).doubleValue() : Double.NaN;
if (converter != null)
doubleValue = converter.convert(doubleValue);
- return test.accept(doubleValue);
+ Test currentTest = test;
+ // If the filter is cleared while filtering it is possible for 'test' to go null
+ if (currentTest == null)
+ return true;
+ return currentTest.accept(doubleValue);
}
@Override
@@ -175,7 +178,9 @@ public abstract class Filter
int indexOfDots = criteria.indexOf(".."); //$NON-NLS-1$
if (indexOfDots >= 0)
{
- Double lowerBound = number(criteria.substring(0, indexOfDots).trim());
+ // Invert of range (universal set difference from range)
+ int st = criteria.startsWith("U\\") ? 2 : 0; //$NON-NLS-1$
+ Double lowerBound = number(criteria.substring(st, indexOfDots).trim());
int lastIndexOfDots = criteria.lastIndexOf(".."); //$NON-NLS-1$
Double upperBound = number(criteria.substring(lastIndexOfDots + 2).trim());
@@ -186,21 +191,30 @@ public abstract class Filter
newTest = new LowerEqualBoundary(lowerBound.doubleValue());
else if (upperBound != null)
newTest = new UpperEqualBoundary(upperBound.doubleValue());
+ else
+ lowerBound = number(criteria); // cause an error
+ if (criteria.startsWith("U\\")) //$NON-NLS-1$
+ newTest = new NotTest(newTest);
}
else
{
- if (criteria.charAt(0) == '>')
+ // Check lengths are enough for the condition and at least one character for the number
+ if (criteria.charAt(0) == '>' && criteria.length() >= 2)
{
- if (criteria.charAt(1) == '=')
+ if (criteria.length() >= 3 && criteria.charAt(1) == '=')
newTest = new LowerEqualBoundary(number(criteria.substring(2)).doubleValue());
else
newTest = new LowerBoundary(number(criteria.substring(1)).doubleValue());
}
- else if (criteria.charAt(0) == '<')
- if (criteria.charAt(1) == '=')
+ else if (criteria.charAt(0) == '<' && criteria.length() >= 2)
+ if (criteria.length() >= 3 && criteria.charAt(1) == '=')
newTest = new UpperEqualBoundary(number(criteria.substring(2)).doubleValue());
+ else if (criteria.length() >= 3 && criteria.charAt(1) == '>')
+ newTest = new NotEqualsTest(number(criteria.substring(2)).doubleValue());
else
newTest = new UpperBoundary(number(criteria.substring(1)).doubleValue());
+ else if (criteria.charAt(0) == '!' && criteria.length() >= 3 && criteria.charAt(1) == '=')
+ newTest = new NotEqualsTest(number(criteria.substring(2)).doubleValue());
else
newTest = new EqualsTest(number(criteria).doubleValue());
}
@@ -330,7 +344,24 @@ public abstract class Filter
public boolean accept(double value)
{
- return this.value == value;
+ // Not standard, but want =NaN to find NaN
+ return this.value == value || Double.isNaN(this.value) && Double.isNaN(value);
+ }
+ }
+
+ static class NotEqualsTest implements Test
+ {
+ double value;
+
+ NotEqualsTest(double value)
+ {
+ this.value = value;
+ }
+
+ public boolean accept(double value)
+ {
+ // Not standard, but want !=NaN not to find NaN
+ return this.value != value && !(Double.isNaN(this.value) && Double.isNaN(value));
}
}
@@ -350,6 +381,20 @@ public abstract class Filter
return a.accept(value) && b.accept(value);
}
}
+
+ static class NotTest implements Test
+ {
+ Test a;
+ private NotTest(Test t)
+ {
+ a = t;
+ }
+
+ public boolean accept(double value)
+ {
+ return !a.accept(value);
+ }
+ }
}
private static class PercentageFilter extends NumericFilter
diff --git a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/Params.java b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/Params.java
index d5c48b8e..f5a01372 100644
--- a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/Params.java
+++ b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/Params.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2010 SAP AG.
+ * Copyright (c) 2008, 2018 SAP AG and 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
@@ -7,6 +7,7 @@
*
* Contributors:
* SAP AG - initial API and implementation
+ * Andrew Johnson/IBM Corporation - documentation
*******************************************************************************/
package org.eclipse.mat.report;
@@ -111,7 +112,14 @@ public interface Params
*/
String PATTERN = "rendering.pattern";
+ /**
+ * Possible value for key given by {@link #PATTERN}.
+ */
String PATTERN_OVERVIEW_DETAILS = "overview_details";
+
+ /**
+ * Possible value for key given by {@link #PATTERN}.
+ */
String PATTERN_SEQUENTIAL = "sequential";
/**
@@ -120,6 +128,8 @@ public interface Params
String SORT_COLUMN = "sort_column";
/**
* filter1=criteria,filter2=criteria
+ * filter1 etc. is a column specified by name or #0, #1, #2 etc.
+ * criteria is a numeric or string filter such as >100, 10..200, com\.*
*/
String FILTER = "filter";
/**
@@ -134,8 +144,8 @@ public interface Params
/**
* Controls the calculation of the derived column.
* For example for retained sizes
- * _default_=APPROXIMATE
- * _default_=PRECISE
+ * _default_=APPROXIMATE {@link org.eclipse.mat.snapshot.query#APPROXIMATE}
+ * _default_=PRECISE {@link org.eclipse.mat.snapshot.query#PRECISE}
*/
String DERIVED_DATA_COLUMN = "derived_data_column";
}
diff --git a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/messages.properties b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/messages.properties
index 6195e587..cd7606c7 100644
--- a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/messages.properties
+++ b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/messages.properties
@@ -31,7 +31,8 @@ Converters_Error_InvalidEnumValue=Must be one of {0}
DisplayFileResult_Label_NoFile=<no file>
Filter_Error_IllegalCharacters=Illegal characters: {0}
Filter_Error_InvalidRegex=Invalid regular expression:
-Filter_Error_Parsing=Error parsing the filter expression.\n\nUse one of the following:\nIntervals: 1000..10000 1%..10%\nUpper Boundary: <=10000 <1%\nLower Boundary: >1000 >=5%\n\n
+Filter_Error_Parsing=Error parsing the filter expression.\n\nUse one of the following:\nIntervals: 1000..10000 1%..10%\nUpper Boundary: <=10000 <1% ..100\nLower Boundary: >1000 >=5% 100..\nEquality: 1000 10%\n\
+Inequality !=1000 <>1000 !=10%\nComplement of interval U\\-100..200 U\\1000..10000 U\\1%..10%\n\n
Filter_Label_Numeric=<Numeric>
Filter_Label_Regex=<Regex>
HtmlOutputter_Error_MovingFile=Error moving file {0} to {1}
diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/snapshot/QueriesTest.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/snapshot/QueriesTest.java
index 370155b5..d730e6ea 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/snapshot/QueriesTest.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/snapshot/QueriesTest.java
@@ -14,7 +14,16 @@ package org.eclipse.mat.tests.snapshot;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;
+import static org.hamcrest.number.OrderingComparison.greaterThan;
+import static org.hamcrest.number.OrderingComparison.lessThanOrEqualTo;
+import static org.hamcrest.number.OrderingComparison.lessThan;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.core.AllOf.allOf;
import java.io.File;
import java.io.FileOutputStream;
@@ -26,6 +35,7 @@ import java.util.Collections;
import org.eclipse.core.runtime.Platform;
import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.query.Bytes;
import org.eclipse.mat.query.Column;
import org.eclipse.mat.query.IContextObject;
import org.eclipse.mat.query.IResult;
@@ -142,7 +152,527 @@ public class QueriesTest
assertTrue(val instanceof Number);
}
}
-
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering2() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, ">");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering3() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, ">=");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering4() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, "<=");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering5() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, "<");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering6() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, "<>");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering7() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, "!=");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering8() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, "..");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testOQLFiltering9() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse(OQL_MIXED_RESULT, snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ builder.setFilter(0, "!");
+ }
+
+ /**
+ * Test for filtering of sizes of items
+ * @throws SnapshotException
+ */
+ @Test
+ public void testOQLFiltering10() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ builder.setFilter(2, ">=0");
+ RefinedTable table = (RefinedTable) builder.build();
+
+ int found = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ assertTrue("Type: "+val.getClass(), val instanceof Number || val instanceof Bytes);
+ ++found;
+ }
+ assertEquals("All entries should have a size >= 0", table.getRowCount(), found);
+ }
+
+ /**
+ * Test for filtering of incompatible items
+ * @throws SnapshotException
+ */
+ @Test
+ public void testOQLFiltering11ge() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, ">="+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eq = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz + 1;
+ assertThat(v, greaterThanOrEqualTo(sz));
+ ++found;
+ if (v == sz)
+ ++eq;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eq, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11gt() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, ">"+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz + 1;
+ assertThat(v, greaterThan(sz));
+ ++found;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11lt() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, "<"+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz - 1;
+ assertThat(v, lessThan(sz));
+ ++found;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11le() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, "<="+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eq = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz - 1;
+ assertThat(v, lessThanOrEqualTo(sz));
+ ++found;
+ if (v == sz)
+ ++eq;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eq, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11eq() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, ""+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz;
+ assertThat(v, equalTo(sz));
+ ++found;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11ne() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, "!="+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz;
+ assertThat(v, not(equalTo(sz)));
+ ++found;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11ne2() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, "<>"+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz;
+ assertThat(v, not(equalTo(sz)));
+ ++found;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11rangea() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, sz+"..");
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eq = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz + 1;
+ assertThat(v, greaterThanOrEqualTo(sz));
+ ++found;
+ if (v == sz)
+ ++eq;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eq, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11rangeb() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, ".."+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eq = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz;
+ assertThat(v, lessThanOrEqualTo(sz));
+ ++found;
+ if (v == sz)
+ ++eq;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eq, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11rangeab() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sza = 32;
+ long szb = 256;
+ builder.setFilter(2, sza+".."+szb);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eqa = 0;
+ int eqb = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sza+1;
+ assertThat(v, greaterThanOrEqualTo(sza));
+ assertThat(v, lessThanOrEqualTo(szb));
+ ++found;
+ if (v == sza)
+ ++eqa;
+ if (v == szb)
+ ++eqb;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eqa, greaterThanOrEqualTo(1));
+ assertThat(eqb, greaterThanOrEqualTo(1));
+ }
+
+ @Test
+ public void testOQLFiltering11urangea() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, "U\\"+sz+"..");
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eq = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz + 1;
+ assertThat(v, not(greaterThanOrEqualTo(sz)));
+ ++found;
+ if (v == sz)
+ ++eq;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eq, equalTo(0));
+ }
+
+ @Test
+ public void testOQLFiltering11urangeb() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sz = 32;
+ builder.setFilter(2, "U\\.."+sz);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eq = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sz;
+ assertThat(v, not(lessThanOrEqualTo(sz)));
+ ++found;
+ if (v == sz)
+ ++eq;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eq, equalTo(0));
+ }
+
+
+ @Test
+ public void testOQLFiltering11urangeab() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+ long sza = 32;
+ long szb = 256;
+ builder.setFilter(2, "U\\"+sza+".."+szb);
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ int eqa = 0;
+ int eqb = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 2);
+ // Check no non-numeric item
+ long v;
+ if (val instanceof Number)
+ v = ((Number)val).longValue();
+ else if (val instanceof Bytes)
+ v = ((Bytes)val).getValue();
+ else
+ v = sza+1;
+ assertThat(v, not(allOf(greaterThanOrEqualTo(sza), lessThanOrEqualTo(szb))));
+ ++found;
+ if (v == sza)
+ ++eqa;
+ if (v == szb)
+ ++eqb;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ assertThat(eqa, equalTo(0));
+ assertThat(eqb, equalTo(0));
+ }
+
+ @Test
+ public void testOQLFiltering11regex() throws SnapshotException
+ {
+ SnapshotQuery query = SnapshotQuery.parse("histogram", snapshot);
+ RefinedResultBuilder builder = query.refine(new VoidProgressListener());
+ // Check size is filterable
+
+ builder.setFilter(0, "java.lang");
+ RefinedTable table = (RefinedTable) builder.build();
+ int found = 0;
+ for (int i = 0; i < table.getRowCount(); ++i)
+ {
+ Object row = table.getRow(i);
+ Object val = table.getColumnValue(row, 0);
+ assertThat(val.toString(), containsString("java.lang"));
+ ++found;
+ }
+ assertThat(found, greaterThanOrEqualTo(1));
+ }
/**
* Test for sorting of incompatible items
diff --git a/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.dita b/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.dita
index 2b336916..d242e13a 100644
--- a/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.dita
+++ b/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.dita
@@ -71,6 +71,9 @@
<li>Intervals: 1000..10000 1%..10%</li>
<li>Upper Boundary: &lt;=10000 &lt;1%</li>
<li>Lower Boundary: &gt;1000 &gt;=5%</li>
+ <li>Equality: 1000 5% NaN &#8734;</li>
+ <li>Inequality: !=1000 &lt;&gt;5% !=NaN<note type="restriction">Experimental</note></li>
+ <li>Complement of interval: U\1000..10000 U\1%..10% (all values except those in the interval [universal set difference from])<note type="restriction">Experimental</note></li>
</ul>
</p>
<image href="../mimes/filter.png" align="left" placement="break" />
diff --git a/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.html b/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.html
index 45760d7d..9e32b1ba 100644
--- a/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.html
+++ b/plugins/org.eclipse.mat.ui.help/reference/tipsandtricks.html
@@ -32,15 +32,15 @@
</p>
<table cellpadding="4" cellspacing="0" summary="" id="ref_tips__tips_table" border="1" class="simpletable"><tr class="sthead">
- <th valign="bottom" align="left" id="d7665e33" class="stentry" width="20%">Tip</th>
+ <th valign="bottom" align="left" id="d7690e33" class="stentry" width="20%">Tip</th>
- <th valign="bottom" align="left" id="d7665e36" class="stentry" width="80%">Description</th>
+ <th valign="bottom" align="left" id="d7690e36" class="stentry" width="80%">Description</th>
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Shortcuts</td>
+ <td valign="top" headers="d7690e33" class="stentry">Shortcuts</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
<p class="p">Ctrl-Q - Opens the Query Browser</p>
<p class="p">Ctrl-H - Opens the history of executed queries.</p>
@@ -51,9 +51,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Quick Search</td>
+ <td valign="top" headers="d7690e33" class="stentry">Quick Search</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
Just start to type while you are in the heap editor, all the
matches will be highlighted. This quick search starts is activated
when 3 or more letters are provided.
@@ -62,9 +62,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Filter</td>
+ <td valign="top" headers="d7690e33" class="stentry">Filter</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
To show only rows of a table or tree matching a filter,
click the top row, or press enter when the top row is selected.
Then type the required filter for the column. Multiple filters can be used.
@@ -83,6 +83,14 @@
<li class="li">Lower Boundary: &gt;1000 &gt;=5%</li>
+ <li class="li">Equality: 1000 5% NaN ∞</li>
+
+ <li class="li">Inequality: !=1000 &lt;&gt;5% !=NaN<div class="note restriction"><span class="restrictiontitle">Restriction:</span> Experimental</div>
+</li>
+
+ <li class="li">Complement of interval: U\1000..10000 U\1%..10% (all values except those in the interval [universal set difference from])<div class="note restriction"><span class="restrictiontitle">Restriction:</span> Experimental</div>
+</li>
+
</ul>
</div>
@@ -98,9 +106,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Resize and reorder columns</td>
+ <td valign="top" headers="d7690e33" class="stentry">Resize and reorder columns</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
To resize or rearrange columns using the keyboard select a filter entry
for the column as above.
<ul class="ul">
@@ -118,9 +126,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Keyboard navigation of trees</td>
+ <td valign="top" headers="d7690e33" class="stentry">Keyboard navigation of trees</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
<ul class="ul">
<li class="li">Use &lt;Numpad plus&gt; or &lt;enter&gt; to expand a row.</li>
@@ -136,9 +144,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Notes, Hyperlinks in Notes View</td>
+ <td valign="top" headers="d7690e33" class="stentry">Notes, Hyperlinks in Notes View</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
Notes View recognizes and highlights object addresses. Activating
the hyperlink brings up a context menu which contains actions for
this particular object. Activate the hyperlink using the control key
@@ -148,9 +156,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Undo/redo in Notes View, OQL Pane</td>
+ <td valign="top" headers="d7690e33" class="stentry">Undo/redo in Notes View, OQL Pane</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
There is undo/redo using Ctrl-Z / Ctrl-Y in the Notes View and
the OQL Pane. The navigator pane can also be used to retrieve
previous OQL statements.
@@ -158,9 +166,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Copy To Clipboard</td>
+ <td valign="top" headers="d7690e33" class="stentry">Copy To Clipboard</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
Use Ctrl-C to copy the selection to the clipboard. The data will
keep its structure:
<br/><div class="imageleft"><img class="image imageleft" src="../mimes/1af34c1.png"/></div><br/>
@@ -168,9 +176,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry"> Manage the history of opened heap dumps</td>
+ <td valign="top" headers="d7690e33" class="stentry"> Manage the history of opened heap dumps</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
Heap Dump History view offers a set of context menu actions to
manage the history of opened heap dumps:
<br/><div class="imageleft"><img class="image imageleft" src="../mimes/691a2594.png"/></div><br/>
@@ -186,9 +194,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Manage editor tabs</td>
+ <td valign="top" headers="d7690e33" class="stentry">Manage editor tabs</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
Right click on the Heap Editor tab will open a context menu to
manage the tabs. It might be very helpful when many tabs are open.
<br/><div class="imageleft"><img class="image imageleft" src="../mimes/7df38219.png"/></div><br/>
@@ -196,9 +204,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry"> Link Inspector View with Heap Editor</td>
+ <td valign="top" headers="d7690e33" class="stentry"> Link Inspector View with Heap Editor</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
Object Inspector View shows the details for the single selected
object. The view updates itself with every change in the
selection. Sometimes it is interesting to compare two or more
@@ -212,9 +220,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Value tab in Inspector View</td>
+ <td valign="top" headers="d7690e33" class="stentry">Value tab in Inspector View</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
The Object Inspector View shows the details for the single selected
object. The value tab shows the value as given by the
<a class="xref" href="../doc/org_eclipse_mat_api_nameResolver.html">
@@ -224,9 +232,9 @@
</tr>
<tr class="strow">
- <td valign="top" headers="d7665e33" class="stentry">Context menu for totals row</td>
+ <td valign="top" headers="d7690e33" class="stentry">Context menu for totals row</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
The totals row now represents all the additional entries in a tree or table.
If the totals row is selected then the context menu will operate on all the unshown
entries in the tree or table. If all the rows are selected, for example using Ctrl-A,
@@ -239,9 +247,9 @@
</tr>
<tr class="strow">
- <td valign="top" id="oqlcompletion" headers="d7665e33" class="stentry">OQL autocompletion</td>
+ <td valign="top" id="oqlcompletion" headers="d7690e33" class="stentry">OQL autocompletion</td>
- <td valign="top" headers="d7665e36" class="stentry">
+ <td valign="top" headers="d7690e36" class="stentry">
The Object Query Language (OQL) pane has syntax highlighting for OQL
keywords. It also offers suggestions for class names for the
<span class="keyword">SELECT</span> <span class="keyword">FROM</span> clause, both simple class names and regular expressions.

Back to the top