ctf: better enum and variant verification
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 4 Dec 2013 14:01:34 +0000 (09:01 -0500)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Fri, 6 Dec 2013 21:56:44 +0000 (16:56 -0500)
Check if enums are valid integers
Check if variants are not using unspecified tags
Check for variant tags recursively
Check for out of range variants
Check for non-intersection between variant and tag

Change-Id: Idd6a98673d8bb3b0a7a1649893a2e21f230a1bcc
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/19410
Reviewed-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
IP-Clean: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
Tested-by: Hudson CI
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/event/types/EnumDeclaration.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/event/types/VariantDefinition.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/StreamInputPacketReader.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/internal/ctf/core/event/metadata/IOStructGen.java

index d820c3db1851233bd0c86d29d17779901b5050dd..c9b9d8dc32da7338f3b5ce29bb2856a4d8db19ab 100644 (file)
 
 package org.eclipse.linuxtools.ctf.core.event.types;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * A CTF enum declaration.
  *
- * The definition of a enum point basic data type. It will take the data
- * from a trace and store it (and make it fit) as an integer and a string.
+ * The definition of a enum point basic data type. It will take the data from a
+ * trace and store it (and make it fit) as an integer and a string.
  *
  * @version 1.0
  * @author Matthew Khouzam
@@ -31,8 +34,9 @@ public class EnumDeclaration implements IDeclaration {
     // Attributes
     // ------------------------------------------------------------------------
 
-    private final EnumTable table = new EnumTable();
-    private IntegerDeclaration containerType = null;
+    private final EnumTable fTable = new EnumTable();
+    private final IntegerDeclaration fContainerType;
+    private final Set<String> fLabels = new HashSet<String>();
 
     // ------------------------------------------------------------------------
     // Constructors
@@ -48,7 +52,7 @@ public class EnumDeclaration implements IDeclaration {
      *            you are wasting space.
      */
     public EnumDeclaration(IntegerDeclaration containerType) {
-        this.containerType = containerType;
+        fContainerType = containerType;
     }
 
     // ------------------------------------------------------------------------
@@ -60,7 +64,7 @@ public class EnumDeclaration implements IDeclaration {
      * @return The container type
      */
     public IntegerDeclaration getContainerType() {
-        return containerType;
+        return fContainerType;
     }
 
     @Override
@@ -79,40 +83,60 @@ public class EnumDeclaration implements IDeclaration {
     }
 
     /**
-     * Add a value. Do not overlap, this is <i><u><b>not</i></u></b> an interval tree.
-     * @param low lowest value that this int can be to have label as a return string
-     * @param high highest value that this int can be to have label as a return string
-     * @param label the name of the value.
+     * Add a value. Do not overlap, this is <i><u><b>not</i></u></b> an interval
+     * tree.
+     *
+     * @param low
+     *            lowest value that this int can be to have label as a return
+     *            string
+     * @param high
+     *            highest value that this int can be to have label as a return
+     *            string
+     * @param label
+     *            the name of the value.
      * @return was the value be added? true == success
      */
     public boolean add(long low, long high, String label) {
-        return table.add(low, high, label);
+        fLabels.add(label);
+        return fTable.add(low, high, label);
     }
 
     /**
-     * Check if the label for a value (enum a{day=0,night=1} would return "day" for query(0)
-     * @param value the value to lookup
+     * Check if the label for a value (enum a{day=0,night=1} would return "day"
+     * for query(0)
+     *
+     * @param value
+     *            the value to lookup
      * @return the label of that value, can be null
      */
     public String query(long value) {
-        return table.query(value);
+        return fTable.query(value);
+    }
+
+    /**
+     * Gets a set of labels of the enum
+     *
+     * @return A set of labels of the enum, can be empty but not null
+     */
+    public Set<String> getLabels() {
+        return Collections.unmodifiableSet(fLabels);
     }
 
     /*
      * Maps integer range -> string. A simple list for now, but feel free to
      * optimize it. Babeltrace suggests an interval tree.
      */
-    private static class EnumTable {
+    private class EnumTable {
 
-        private List<Range> ranges = new LinkedList<Range>();
+        private final List<LabelAndRange> ranges = new LinkedList<LabelAndRange>();
 
         public EnumTable() {
         }
 
         public boolean add(long low, long high, String label) {
-            Range newRange = new Range(low, high, label);
+            LabelAndRange newRange = new LabelAndRange(low, high, label);
 
-            for (Range r : ranges) {
+            for (LabelAndRange r : ranges) {
                 if (r.intersects(newRange)) {
                     return false;
                 }
@@ -125,37 +149,40 @@ public class EnumDeclaration implements IDeclaration {
 
         /**
          * Return the first label that matches a value
-         * @param value the value to query
+         *
+         * @param value
+         *            the value to query
          * @return the label corresponding to that value
          */
         public String query(long value) {
-            for (Range r : ranges) {
+            for (LabelAndRange r : ranges) {
                 if (r.intersects(value)) {
-                    return r.str;
+                    return r.fLabel;
                 }
             }
             return null;
         }
 
-        private static class Range {
+    }
 
-            private long low, high;
-            private String str;
+    private class LabelAndRange {
 
-            public Range(long low, long high, String str) {
-                this.low = low;
-                this.high = high;
-                this.str = str;
-            }
+        private final long low, high;
+        private final String fLabel;
 
-            public boolean intersects(long i) {
-                return (i >= this.low) && (i <= this.high);
-            }
+        public LabelAndRange(long low, long high, String str) {
+            this.low = low;
+            this.high = high;
+            this.fLabel = str;
+        }
 
-            public boolean intersects(Range other) {
-                return this.intersects(other.low)
-                        || this.intersects(other.high);
-            }
+        public boolean intersects(long i) {
+            return (i >= this.low) && (i <= this.high);
+        }
+
+        public boolean intersects(LabelAndRange other) {
+            return this.intersects(other.low)
+                    || this.intersects(other.high);
         }
     }
 
index ca81529db8d3d7ff53a08b50e84d00666ad58655..c3c313cd427f7a63d6e5451c8a400a09d7017cce 100644 (file)
@@ -152,7 +152,9 @@ public class VariantDefinition extends Definition implements IDefinitionScope {
         currentField = tagDefinition.getValue();
 
         Definition field = definitions.get(currentField);
-
+        if (field == null) {
+            throw new CTFReaderException("Variant was not defined for: "+ currentField); //$NON-NLS-1$
+        }
         field.read(input);
     }
 
index ca847195e612ffa251c27051d0d50eca152d1065..f0a5d46bbf21d8d5d7dbfd7eaa6fabe6f4f71702 100644 (file)
@@ -324,7 +324,7 @@ public class StreamInputPacketReader implements IDefinitionScope {
             if (idDef instanceof SimpleDatatypeDefinition) {
                 eventID = ((SimpleDatatypeDefinition) idDef).getIntegerValue();
             } else if (idDef != null) {
-                throw new CTFReaderException("Incorrect event id : " + eventID);
+                throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
             }
 
             /*
index 91064543349a5d3d9e4330e80f90adf42f0bb9d2..195ac07ce05f2d2004571e00149cf7c733223b7a 100644 (file)
@@ -21,8 +21,10 @@ import java.math.BigInteger;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 
 import org.antlr.runtime.tree.CommonTree;
@@ -2031,6 +2033,20 @@ public class IOStructGen {
 
         if (hasTag) {
             variantDeclaration.setTag(variantTag);
+
+            IDeclaration decl = getCurrentScope().lookupIdentifierRecursive(variantTag);
+            if (decl == null) {
+                throw new ParseException("Variant tag not found: " + variantTag); //$NON-NLS-1$
+            }
+            if (!(decl instanceof EnumDeclaration)) {
+                throw new ParseException("Variant tag must be an enum: " + variantTag); //$NON-NLS-1$
+            }
+            EnumDeclaration tagDecl = (EnumDeclaration) decl;
+            Set<String> intersection = new HashSet<String>(tagDecl.getLabels());
+            intersection.retainAll(variantDeclaration.getFields().keySet());
+            if (intersection.isEmpty()) {
+                throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$
+            }
         }
 
         return variantDeclaration;
@@ -2307,7 +2323,7 @@ public class IOStructGen {
      * @param unaryInteger
      *            An unary integer node.
      * @return The integer value.
-     * @throws CTFReaderException
+     * @throws ParseException on an invalid integer format ("bob" for example)
      */
     private static long parseUnaryInteger(CommonTree unaryInteger) throws ParseException {
 
This page took 0.057895 seconds and 5 git commands to generate.