test/jdk/javax/management/remote/rest/json/JsonTester.java
branchjmx-rest-api
changeset 56002 60ab3b595a8e
equal deleted inserted replaced
56001:95c0323f0c1a 56002:60ab3b595a8e
       
     1 package json;
       
     2 
       
     3 import com.oracle.jmx.remote.rest.json.parser.JSONParser;
       
     4 import com.oracle.jmx.remote.rest.json.parser.ParseException;
       
     5 
       
     6 import java.util.*;
       
     7 
       
     8 /**
       
     9  * Below class tests JSON parser for a randomly generated JSON string.
       
    10  * The Json string is generated by converting a randomly generated tree into a string
       
    11  * Each node in the tree is either a json Object, array or a primitive.
       
    12  * Primitive node generates string, number, boolean or null as a string.
       
    13  * Json Number is generated according to the syntax graph as in json.org
       
    14  * Json string is generated along with all the control characters, and by escaping
       
    15  * only backslash and double quote characters.
       
    16  */
       
    17 public class JsonTester {
       
    18 
       
    19     static final Random RANDOM = new Random(System.currentTimeMillis());
       
    20     static int maxChildrenPerNode;
       
    21 
       
    22     public static void main(String[] args) throws ParseException {
       
    23 
       
    24         for(int i=0; i<100; i++) {
       
    25             maxChildrenPerNode = RANDOM.nextInt(90) + 10;
       
    26             int totalNodes = RANDOM.nextInt(90000) + 10000;
       
    27             boolean isArray = RANDOM.nextBoolean();         // Generate either a Json Array or a Json Object
       
    28             JsonNode node;
       
    29             if (isArray) {
       
    30                 node = JsonNodeGenerator.ArrayGenerator.generate(totalNodes);
       
    31             } else {
       
    32                 node = JsonNodeGenerator.ObjectGenerator.generate(totalNodes);
       
    33             }
       
    34             String str = node.toJsonString();
       
    35             JSONParser parser = new JSONParser(str);
       
    36             com.oracle.jmx.remote.rest.json.JSONElement parse = parser.parse();
       
    37             parse.toJsonString();
       
    38             System.out.println("Finished iteration : " + i + ", Node count :" + totalNodes);
       
    39         }
       
    40     }
       
    41 }
       
    42 
       
    43 
       
    44 interface JsonNode {
       
    45 
       
    46     class ObjectNode extends LinkedHashMap<String, JsonNode> implements JsonNode {
       
    47 
       
    48         @Override
       
    49         public String toJsonString() {
       
    50             if (isEmpty()) {
       
    51                 return null;
       
    52             }
       
    53 
       
    54             StringBuilder sbuild = new StringBuilder();
       
    55             sbuild.append("{");
       
    56             keySet().forEach((elem) -> sbuild.append(elem).append(": ").
       
    57                     append((get(elem) != null) ? get(elem).toJsonString() : "null").append(","));
       
    58 
       
    59             sbuild.deleteCharAt(sbuild.lastIndexOf(","));
       
    60             sbuild.append("}");
       
    61             return sbuild.toString();
       
    62         }
       
    63     }
       
    64 
       
    65     class ArrayNode extends ArrayList<JsonNode> implements JsonNode {
       
    66 
       
    67         @Override
       
    68         public String toJsonString() {
       
    69             if (isEmpty()) {
       
    70                 return null;
       
    71             }
       
    72             StringBuilder sbuild = new StringBuilder();
       
    73             sbuild.append("[");
       
    74             for (JsonNode val : this) {
       
    75                 if (val != null) {
       
    76                     sbuild.append(val.toJsonString()).append(", ");
       
    77                 } else {
       
    78                     sbuild.append("null").append(", ");
       
    79                 }
       
    80             }
       
    81 
       
    82             sbuild.deleteCharAt(sbuild.lastIndexOf(","));
       
    83             sbuild.append("]");
       
    84             return sbuild.toString();
       
    85         }
       
    86     }
       
    87 
       
    88     class PrimitiveNode implements JsonNode {
       
    89 
       
    90         private final String s;
       
    91 
       
    92         PrimitiveNode(String s) {
       
    93             this.s = s;
       
    94         }
       
    95 
       
    96         @Override
       
    97         public String toJsonString() {
       
    98             return s;
       
    99         }
       
   100     }
       
   101 
       
   102     String toJsonString();
       
   103 }
       
   104 
       
   105 interface JsonNodeGenerator {
       
   106 
       
   107     class NumberGenerator {
       
   108 
       
   109          // Node that returns the assigned label
       
   110         private static class Node {
       
   111             final private String label;
       
   112 
       
   113             Node(String label) {
       
   114                 children = new LinkedList<>();
       
   115                 this.label = label;
       
   116             }
       
   117 
       
   118             Node() {
       
   119                 this("");
       
   120             }
       
   121 
       
   122             void add(Node node) {
       
   123                 if (!children.contains(node)) {
       
   124                     children.add(node);
       
   125                 }
       
   126             }
       
   127 
       
   128             String getLabel() {
       
   129                 return label;
       
   130             }
       
   131 
       
   132             List<Node> children;
       
   133         }
       
   134 
       
   135         // Node that generates a random digit from 1-9
       
   136         private static class Digit19 extends Node {
       
   137             Digit19() {
       
   138                 super();
       
   139             }
       
   140 
       
   141             @Override
       
   142             String getLabel() {
       
   143                 return "" + (JsonTester.RANDOM.nextInt(9) + 1);
       
   144             }
       
   145         }
       
   146 
       
   147         // Node that generates a random digit from 0-9
       
   148         private static class Digits extends Node {
       
   149             Digits() {
       
   150                 super();
       
   151             }
       
   152 
       
   153             @Override
       
   154             String getLabel() {
       
   155                 return "" + (JsonTester.RANDOM.nextInt(10));
       
   156             }
       
   157         }
       
   158 
       
   159         private final static Node root;
       
   160 
       
   161         // Setup a graph for the grammar productions for JSON number as outlined in json.org
       
   162         // The graph below mimics the syntax diagram for JSON number.
       
   163         // Node "R" is the start node and "T" is the terminal node
       
   164         static {
       
   165 
       
   166             // Create all the nodes
       
   167             root = new Node("R");
       
   168             Node minus1 = new Node("-");
       
   169             Node zero = new Node("0");
       
   170             Node digit19 = new Digit19();
       
   171             Node digits1 = new Digits();
       
   172             Node dot = new Node(".");
       
   173             Node digits2 = new Digits();
       
   174             Node e = new Node("e");
       
   175             Node E = new Node("E");
       
   176             Node plus = new Node("+");
       
   177             Node minus2 = new Node("-");
       
   178             Node digits3 = new Digits();
       
   179             Node terminal = new Node("T");
       
   180 
       
   181             //set up graph
       
   182             root.add(zero);
       
   183             root.add(minus1);
       
   184             root.add(digit19);
       
   185 
       
   186             minus1.add(zero);
       
   187             minus1.add(digit19);
       
   188 
       
   189             zero.add(dot);
       
   190             zero.add(terminal);
       
   191 
       
   192             digit19.add(dot);
       
   193             digit19.add(digits1);
       
   194             digit19.add(terminal);
       
   195 
       
   196             digits1.add(dot);
       
   197             digits1.add(digits1);
       
   198             digits1.add(terminal);
       
   199 
       
   200             dot.add(digits2);
       
   201 
       
   202             digits2.add(digits2);
       
   203             digits2.add(e);
       
   204             digits2.add(E);
       
   205             digits2.add(terminal);
       
   206 
       
   207             e.add(plus);
       
   208             e.add(minus2);
       
   209             e.add(digits3);
       
   210 
       
   211             E.add(plus);
       
   212             E.add(minus2);
       
   213             E.add(digits3);
       
   214 
       
   215             plus.add(digits3);
       
   216             minus2.add(digits3);
       
   217 
       
   218             digits3.add(digits3);
       
   219             digits3.add(terminal);
       
   220         }
       
   221 
       
   222         static String generate() {
       
   223             // Get a random path from start to finish
       
   224             StringBuilder sbuf = new StringBuilder();
       
   225             Node parent = root;
       
   226             Node child = parent.children.get(JsonTester.RANDOM.nextInt(parent.children.size()));
       
   227             while (!child.getLabel().equals("T")) {
       
   228                 sbuf.append(child.getLabel());
       
   229                 parent = child;
       
   230                 child = parent.children.get(JsonTester.RANDOM.nextInt(parent.children.size()));
       
   231             }
       
   232             return sbuf.toString();
       
   233         }
       
   234     }
       
   235 
       
   236     class StringGenerator {
       
   237 
       
   238         private static final int minStringLength = 0;
       
   239         private static final int maxStringLength = 50;
       
   240 
       
   241         private static final String controlChars = "\b" + "\f" + "\n" + "\r" + "\t" + "\\b";
       
   242 //        private static final String escapedControls = "\\b" + "\\f" + "\\n" + "\\r" + "\\t" + "\\b";
       
   243 
       
   244         private static final String specials = "\\" + "\"" + controlChars;// + escapedControls;    // TODO: "\\uxxxx"
       
   245 //        private static final String alphanums = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
       
   246 
       
   247         static String generate() {
       
   248             char ch;
       
   249             StringBuilder sbuf = new StringBuilder();
       
   250             int len = minStringLength + JsonTester.RANDOM.nextInt(maxStringLength - minStringLength + 1);
       
   251             sbuf.append("\"");
       
   252             for (int i = 0; i < len; i++) {
       
   253                 if (JsonTester.RANDOM.nextInt(10) == 1) { // 1/10 chances of a control character
       
   254                     ch = specials.charAt(JsonTester.RANDOM.nextInt(specials.length()));
       
   255                 } else {
       
   256 //                ch = alphanums.charAt(JsonTester.RANDOM.nextInt(alphanums.length()));
       
   257                     ch = (char) JsonTester.RANDOM.nextInt(Character.MAX_VALUE + 1);
       
   258                 }
       
   259                 switch (ch) {
       
   260                     case '\"':
       
   261                     case '\\':
       
   262                         sbuf.append('\\');
       
   263                 }
       
   264                 sbuf.append(ch);
       
   265             }
       
   266             sbuf.append("\"");
       
   267             return sbuf.toString();
       
   268         }
       
   269     }
       
   270 
       
   271     class ArrayGenerator {
       
   272 
       
   273          static JsonNode.ArrayNode generate(int size) {
       
   274             JsonNode.ArrayNode array = new JsonNode.ArrayNode();
       
   275             if (size <= JsonTester.maxChildrenPerNode) {
       
   276                 for (int i = 0; i < size; i++) {
       
   277                     array.add(PrimtiveGenerator.generate());
       
   278                 }
       
   279             } else if (size >= JsonTester.maxChildrenPerNode) {
       
   280                 int newSize = size;
       
   281                 do {
       
   282                     int childSize = JsonTester.RANDOM.nextInt(newSize);
       
   283                     if (JsonTester.RANDOM.nextBoolean()) {
       
   284                         array.add(ArrayGenerator.generate(childSize));
       
   285                     } else {
       
   286                         array.add(ObjectGenerator.generate(childSize));
       
   287                     }
       
   288                     newSize = newSize - childSize;
       
   289                 } while (newSize > JsonTester.maxChildrenPerNode);
       
   290                 if (JsonTester.RANDOM.nextBoolean()) {
       
   291                     array.add(ArrayGenerator.generate(newSize));
       
   292                 } else {
       
   293                     array.add(ObjectGenerator.generate(newSize));
       
   294                 }
       
   295             }
       
   296             return array;
       
   297         }
       
   298     }
       
   299 
       
   300     class PrimtiveGenerator {
       
   301 
       
   302         static JsonNode.PrimitiveNode generate() {
       
   303             int primitiveTypre = JsonTester.RANDOM.nextInt(10) + 1;
       
   304             switch (primitiveTypre) {
       
   305                 case 1:
       
   306                 case 2:
       
   307                 case 3:
       
   308                 case 4:
       
   309                     return new JsonNode.PrimitiveNode(StringGenerator.generate());
       
   310                 case 5:
       
   311                 case 6:
       
   312                 case 7:
       
   313                 case 8:
       
   314                     return new JsonNode.PrimitiveNode(NumberGenerator.generate());
       
   315                 case 9:
       
   316                     return new JsonNode.PrimitiveNode(Boolean.toString(JsonTester.RANDOM.nextBoolean()));
       
   317                 case 10:
       
   318                     return null;
       
   319             }
       
   320             return null;
       
   321         }
       
   322     }
       
   323 
       
   324     class ObjectGenerator {
       
   325 
       
   326         static JsonNode.ObjectNode generate(int size) {
       
   327             JsonNode.ObjectNode jobj = new JsonNode.ObjectNode();
       
   328             if (size <= JsonTester.maxChildrenPerNode) {
       
   329                 for (int i = 0; i < size; i++) {
       
   330                     jobj.put(StringGenerator.generate(), PrimtiveGenerator.generate());
       
   331                 }
       
   332             } else {
       
   333                 int newSize = size;
       
   334                 do {
       
   335                     int childSize = JsonTester.RANDOM.nextInt(newSize);
       
   336                     if (JsonTester.RANDOM.nextBoolean()) {
       
   337                         jobj.put(StringGenerator.generate(), ArrayGenerator.generate(childSize));
       
   338                     } else {
       
   339                         jobj.put(StringGenerator.generate(), ObjectGenerator.generate(childSize));
       
   340                     }
       
   341                     newSize = newSize - childSize;
       
   342                 } while (newSize > JsonTester.maxChildrenPerNode);
       
   343                 if (JsonTester.RANDOM.nextBoolean()) {
       
   344                     jobj.put(StringGenerator.generate(), ArrayGenerator.generate(newSize));
       
   345                 } else {
       
   346                     jobj.put(StringGenerator.generate(), ObjectGenerator.generate(newSize));
       
   347                 }
       
   348             }
       
   349             return jobj;
       
   350         }
       
   351     }
       
   352 }
       
   353 
       
   354