diff options
author | Andrew Johnson | 2018-11-17 20:59:27 +0000 |
---|---|---|
committer | Andrew Johnson | 2018-11-17 21:04:55 +0000 |
commit | d6dfde22ff326ebad0eb3aac56dfb2859bb012af (patch) | |
tree | 7cf5048886731573958296c0e742b010dc7fd54a | |
parent | 6d4ebc00331521a2ce447253da8e8762581c5168 (diff) | |
download | org.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
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: <=10000 <1%</li>
<li>Lower Boundary: >1000 >=5%</li>
+ <li>Equality: 1000 5% NaN ∞</li>
+ <li>Inequality: !=1000 <>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: >1000 >=5%</li> + <li class="li">Equality: 1000 5% NaN ∞</li> + + <li class="li">Inequality: !=1000 <>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 <Numpad plus> or <enter> 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. |