Ongoing improvements in java fuzz testing

Added --device option to runner to define target in case
        multiple devices are attached

Added more cases to JavaFuzz, removed a few cases that
are likely to hang the program (such as changing loop
variables) since throughput is more important for fuzzing

Test: run_java_fuzz_test.py

BUG=30610121

Change-Id: I0cd6f5d3b7fb35ddb91d91c0c0c00afaf83218d8
diff --git a/tools/javafuzz/javafuzz.cc b/tools/javafuzz/javafuzz.cc
index 4e6e978..161ae0a 100644
--- a/tools/javafuzz/javafuzz.cc
+++ b/tools/javafuzz/javafuzz.cc
@@ -53,7 +53,9 @@
  * to preserve the property that a given version of JavaFuzz yields the same
  * fuzzed Java program for a deterministic random seed.
  */
-const char* VERSION = "1.0";
+const char* VERSION = "1.1";
+
+static const uint32_t MAX_DIMS[11] = { 0, 1000, 32, 10, 6, 4, 3, 3, 2, 2, 2 };
 
 /**
  * A class that generates a random Java program that compiles correctly. The program
@@ -83,8 +85,8 @@
         fuzz_loop_nest_(loop_nest),
         return_type_(randomType()),
         array_type_(randomType()),
-        array_dim_(random1(3)),
-        array_size_(random1(10)),
+        array_dim_(random1(10)),
+        array_size_(random1(MAX_DIMS[array_dim_])),
         indentation_(0),
         expr_depth_(0),
         stmt_length_(0),
@@ -169,7 +171,7 @@
   // Emit an unary operator (same type in-out).
   void emitUnaryOp(Type tp) {
     if (tp == kBoolean) {
-      fputs("!", out_);
+      fputc('!', out_);
     } else if (isInteger(tp)) {
       EMIT(kIntUnaryOps);
     } else {  // isFP(tp)
@@ -239,16 +241,21 @@
         case 6: fputs("(long)(int)(long)",   out_); return kLong;
       }
     } else if (tp == kFloat) {
-      switch (random1(3)) {
+      switch (random1(4)) {
         case 1: fputs("(float)", out_); return kInt;
         case 2: fputs("(float)", out_); return kLong;
         case 3: fputs("(float)", out_); return kDouble;
+        // Narrowing-widening.
+        case 4: fputs("(float)(int)(float)", out_); return kFloat;
       }
     } else if (tp == kDouble) {
-      switch (random1(3)) {
+      switch (random1(5)) {
         case 1: fputs("(double)", out_); return kInt;
         case 2: fputs("(double)", out_); return kLong;
         case 3: fputs("(double)", out_); return kFloat;
+        // Narrowing-widening.
+        case 4: fputs("(double)(int)(double)",   out_); return kDouble;
+        case 5: fputs("(double)(float)(double)", out_); return kDouble;
       }
     }
     return tp;  // nothing suitable, just keep type
@@ -273,15 +280,17 @@
   // Emit an unary intrinsic (out type given, new suitable in type picked).
   Type emitIntrinsic1(Type tp) {
     if (tp == kBoolean) {
-      switch (random1(4)) {
+      switch (random1(6)) {
         case 1: fputs("Float.isNaN",       out_); return kFloat;
-        case 2: fputs("Float.isInfinite",  out_); return kFloat;
-        case 3: fputs("Double.isNaN",      out_); return kDouble;
-        case 4: fputs("Double.isInfinite", out_); return kDouble;
+        case 2: fputs("Float.isFinite",    out_); return kFloat;
+        case 3: fputs("Float.isInfinite",  out_); return kFloat;
+        case 4: fputs("Double.isNaN",      out_); return kDouble;
+        case 5: fputs("Double.isFinite",   out_); return kDouble;
+        case 6: fputs("Double.isInfinite", out_); return kDouble;
       }
     } else if (isInteger(tp)) {
       const char* prefix = tp == kLong ? "Long" : "Integer";
-      switch (random1(9)) {
+      switch (random1(13)) {
         case 1: fprintf(out_, "%s.highestOneBit",         prefix); break;
         case 2: fprintf(out_, "%s.lowestOneBit",          prefix); break;
         case 3: fprintf(out_, "%s.numberOfLeadingZeros",  prefix); break;
@@ -290,15 +299,27 @@
         case 6: fprintf(out_, "%s.signum",                prefix); break;
         case 7: fprintf(out_, "%s.reverse",               prefix); break;
         case 8: fprintf(out_, "%s.reverseBytes",          prefix); break;
-        case 9: fputs("Math.abs", out_);                           break;
+        case 9:  fputs("Math.incrementExact", out_); break;
+        case 10: fputs("Math.decrementExact", out_); break;
+        case 11: fputs("Math.negateExact",    out_); break;
+        case 12: fputs("Math.abs",            out_); break;
+        case 13: fputs("Math.round", out_);
+                 return tp == kLong ? kDouble : kFloat;
       }
     } else {  // isFP(tp)
-      switch (random1(5)) {
+      switch (random1(6)) {
         case 1: fputs("Math.abs",      out_); break;
         case 2: fputs("Math.ulp",      out_); break;
         case 3: fputs("Math.signum",   out_); break;
         case 4: fputs("Math.nextUp",   out_); break;
         case 5: fputs("Math.nextDown", out_); break;
+        case 6: if (tp == kDouble) {
+                  fputs("Double.longBitsToDouble", out_);
+                  return kLong;
+                } else {
+                  fputs("Float.intBitsToFloat", out_);
+                  return kInt;
+                }
       }
     }
     return tp;  // same type in-out
@@ -314,15 +335,27 @@
       }
     } else if (isInteger(tp)) {
       const char* prefix = tp == kLong ? "Long" : "Integer";
-      switch (random1(3)) {
+      switch (random1(11)) {
         case 1: fprintf(out_, "%s.compare", prefix); break;
-        case 2: fputs("Math.min", out_); break;
-        case 3: fputs("Math.max", out_); break;
+        case 2: fprintf(out_, "%s.sum",     prefix); break;
+        case 3: fprintf(out_, "%s.min",     prefix); break;
+        case 4: fprintf(out_, "%s.max",     prefix); break;
+        case 5:  fputs("Math.min",           out_); break;
+        case 6:  fputs("Math.max",           out_); break;
+        case 7:  fputs("Math.floorDiv",      out_); break;
+        case 8:  fputs("Math.floorMod",      out_); break;
+        case 9:  fputs("Math.addExact",      out_); break;
+        case 10: fputs("Math.subtractExact", out_); break;
+        case 11: fputs("Math.multiplyExact", out_); break;
       }
     } else {  // isFP(tp)
-      switch (random1(2)) {
-        case 1: fputs("Math.min", out_); break;
-        case 2: fputs("Math.max", out_); break;
+      const char* prefix = tp == kDouble ? "Double" : "Float";
+      switch (random1(5)) {
+        case 1: fprintf(out_, "%s.sum", prefix); break;
+        case 2: fprintf(out_, "%s.min", prefix); break;
+        case 3: fprintf(out_, "%s.max", prefix); break;
+        case 4: fputs("Math.min", out_); break;
+        case 5: fputs("Math.max", out_); break;
       }
     }
     return tp;  // same type in-out
@@ -358,12 +391,24 @@
 
   // Emit miscellaneous constructs.
   void emitMisc(Type tp) {
-    switch (tp) {
-      case kBoolean: fputs("this instanceof Test", out_); break;
-      case kInt:     fputs("mArray.length",    out_); break;
-      case kLong:    fputs("Long.MAX_VALUE",   out_); break;
-      case kFloat:   fputs("Float.MAX_VALUE",  out_); break;
-      case kDouble:  fputs("Double.MAX_VALUE", out_); break;
+    if (tp == kBoolean) {
+      fputs("this instanceof Test", out_);
+    } else if (isInteger(tp)) {
+      const char* prefix = tp == kLong ? "Long" : "Integer";
+      switch (random1(2)) {
+        case 1: fprintf(out_, "%s.MIN_VALUE", prefix); break;
+        case 2: fprintf(out_, "%s.MAX_VALUE", prefix); break;
+      }
+    } else {  // isFP(tp)
+      const char* prefix = tp == kDouble ? "Double" : "Float";
+      switch (random1(6)) {
+        case 1: fprintf(out_, "%s.MIN_NORMAL", prefix);        break;
+        case 2: fprintf(out_, "%s.MIN_VALUE", prefix);         break;
+        case 3: fprintf(out_, "%s.MAX_VALUE", prefix);         break;
+        case 4: fprintf(out_, "%s.POSITIVE_INFINITY", prefix); break;
+        case 5: fprintf(out_, "%s.NEGATIVE_INFINITY", prefix); break;
+        case 6: fprintf(out_, "%s.NaN", prefix);               break;
+      }
     }
   }
 
@@ -412,10 +457,10 @@
   void emitLiteral(Type tp) {
     switch (tp) {
       case kBoolean: fputs(random1(2) == 1 ? "true" : "false", out_); break;
-      case kInt:     fprintf(out_, "%d",    random0(100)); break;
-      case kLong:    fprintf(out_, "%dL",   random0(100)); break;
-      case kFloat:   fprintf(out_, "%d.0f", random0(100)); break;
-      case kDouble:  fprintf(out_, "%d.0",  random0(100)); break;
+      case kInt:     fprintf(out_, "%d",    random()); break;
+      case kLong:    fprintf(out_, "%dL",   random()); break;
+      case kFloat:   fprintf(out_, "%d.0f", random()); break;
+      case kDouble:  fprintf(out_, "%d.0",  random()); break;
     }
   }
 
@@ -433,17 +478,6 @@
     return false;
   }
 
-  // Emit a loop variable, if available.
-  bool emitLoopVariable(Type tp) {
-    if (tp == kInt) {
-      if (loop_nest_ > 0) {
-        fprintf(out_, "i%u", random0(loop_nest_));
-        return true;
-      }
-    }
-    return false;
-  }
-
   // Emit a local variable, if available.
   bool emitLocalVariable(Type tp) {
     uint32_t locals = adjustLocal(tp, 0);
@@ -483,10 +517,6 @@
         if (emitLocalVariable(tp))
           return;
         // FALL-THROUGH
-      case 3:
-        if (emitLoopVariable(tp))
-          return;
-        // FALL-THROUGH
       default:
         emitFieldVariable(tp);
         break;
@@ -510,8 +540,9 @@
     fputc('(', out_);
     switch (random1(12)) {  // favor binary operations
       case 1:
-        // Unary operator: ~x
+        // Unary operator: ~ x
         emitUnaryOp(tp);
+        fputc(' ', out_);
         emitExpression(tp);
         break;
       case 2:
@@ -761,7 +792,7 @@
 
     bool mayFollow = false;
     fputs("switch (", out_);
-    emitExpression(kInt);
+    emitArrayIndex();  // restrict its range
     fputs(") {\n", out_);
 
     ++if_nest_;
@@ -771,7 +802,7 @@
     for (uint32_t i = 0; i < 2; i++) {
       emitIndentation();
       if (i == 0) {
-        fprintf(out_, "case %d: {\n", random0(100));
+        fprintf(out_, "case %u: {\n", random0(array_size_));
       } else {
         fprintf(out_, "default: {\n");
       }
@@ -977,6 +1008,11 @@
   // Random integers.
   //
 
+  // Return random integer.
+  int32_t random() {
+    return fuzz_random_engine_();
+  }
+
   // Return random integer in range [0,max).
   uint32_t random0(uint32_t max) {
     std::uniform_int_distribution<uint32_t> gen(0, max - 1);
@@ -1025,7 +1061,7 @@
   // Defaults.
   uint32_t seed = time(NULL);
   uint32_t expr_depth = 1;
-  uint32_t stmt_length = 4;
+  uint32_t stmt_length = 8;
   uint32_t if_nest = 2;
   uint32_t loop_nest = 3;