Additional tests for <clinit> rewriting

Bug: 67468748
Change-Id: I05a6efaf207e3520a1cee2d2103e53791d3f6db5
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index dde13ae..645bf2b 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -289,6 +289,13 @@
   /**
    * Run application on Art with the specified main class.
    */
+  protected String runOnArt(AndroidApp app, String mainClass) throws IOException {
+    return runOnArtRaw(app, mainClass).stdout;
+  }
+
+  /**
+   * Run application on Art with the specified main class.
+   */
   protected String runOnArt(AndroidApp app, Class mainClass) throws IOException {
     return runOnArtRaw(app, mainClass).stdout;
   }
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
index 8f3ace3..0db6991 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
@@ -24,12 +24,18 @@
 
   public static class ClassBuilder {
     public final String name;
+    public final String superName;
     private final List<String> methods = new ArrayList<>();
     private final List<String> fields = new ArrayList<>();
     private boolean makeInit = false;
 
     public ClassBuilder(String name) {
+      this(name, "java/lang/Object");
+    }
+
+    public ClassBuilder(String name, String superName) {
       this.name = name;
+      this.superName = superName;
     }
 
     public MethodSignature addVirtualMethod(
@@ -105,14 +111,14 @@
       StringBuilder builder = new StringBuilder();
       builder.append(".source ").append(name).append(".j\n");
       builder.append(".class public ").append(name).append("\n");
-      builder.append(".super java/lang/Object\n");
+      builder.append(".super ").append(superName).append("\n");
       if (makeInit) {
         builder
             .append(".method public <init>()V\n")
             .append(".limit locals 1\n")
             .append(".limit stack 1\n")
             .append("  aload 0\n")
-            .append("  invokespecial java/lang/Object/<init>()V\n")
+            .append("  invokespecial ").append(superName).append("/<init>()V\n")
             .append("  return\n")
             .append(".end method\n");
       }
@@ -136,6 +142,12 @@
     return builder;
   }
 
+  public ClassBuilder addClass(String name, String superName) {
+    ClassBuilder builder = new ClassBuilder(name, superName);
+    classes.add(builder);
+    return builder;
+  }
+
   public ImmutableList<ClassBuilder> getClasses() {
     return ImmutableList.copyOf(classes);
   }
diff --git a/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java b/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java
index 6d9f582..e27b5b9 100644
--- a/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java
+++ b/src/test/java/com/android/tools/r8/rewrite/staticvalues/B67468748.java
@@ -17,7 +17,42 @@
 public class B67468748 extends JasminTestBase {
 
   @Test
-  public void jarInput() throws Exception {
+  public void initializeStaticFieldInSuper() throws Exception {
+    final String SUPER_NAME = "Super";
+    final String CLASS_NAME = "Test";
+
+    JasminBuilder builder = new JasminBuilder();
+
+    // Simple super class with just a static field.
+    JasminBuilder.ClassBuilder zuper = builder.addClass(SUPER_NAME);
+    zuper.addStaticField("intField", "I", null);
+
+    JasminBuilder.ClassBuilder clazz = builder.addClass(CLASS_NAME, SUPER_NAME);
+
+    // The static field Test/intField is actually defined on the super class.
+    clazz.addStaticMethod("<clinit>", ImmutableList.of(), "V",
+        ".limit stack 1",
+        ".limit locals 1",
+        "iconst_1",
+        "putstatic Test/intField I",
+        "return");
+
+    clazz.addMainMethod(
+        ".limit stack 2",
+        ".limit locals 1",
+        "getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "getstatic Test/intField I",
+        "invokevirtual java/io/PrintStream/print(I)V",
+        "return");
+
+    // Run in release mode to turn on initializer defaults rewriting.
+    AndroidApp application = compileWithD8(builder, options -> options.debug = false);
+    String result = runOnArt(application, CLASS_NAME);
+    assertEquals("1", result);
+  }
+
+  @Test
+  public void invalidCode() throws Exception {
     final String CLASS_NAME = "Test";
 
     JasminBuilder builder = new JasminBuilder();
diff --git a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
index 1d26039..4d1d619 100644
--- a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
@@ -574,7 +574,42 @@
   }
 
   @Test
-  public void b67468748() throws Exception {
+  public void b67468748InitializeStaticFieldInSuper() throws Exception {
+    final String SUPER_NAME = "Super";
+    final String CLASS_NAME = "Test";
+
+    SmaliBuilder builder = new SmaliBuilder();
+    builder.addClass(SUPER_NAME);
+    builder.addStaticField("intField", "I");
+
+    // The static field LTest;->intField:I is not defined even though it is written in the
+    // <clinit> code. This class cannot load, but we can still process it to output which still
+    // cannot load.
+    builder.addClass(CLASS_NAME, SUPER_NAME);
+    builder.addStaticInitializer(
+        2,
+        "const               v0, 3",
+        "sput                v0, LTest;->intField:I",
+        "return-void"
+    );
+    builder.addMainMethod(
+        3,
+        "sget-object         v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
+        "sget                v1, LTest;->intField:I",
+        "invoke-virtual      { v0, v1 }, Ljava/io/PrintStream;->print(I)V",
+        "return-void"
+    );
+
+    AndroidApp application = builder.build();
+
+    // Run in release mode to turn on initializer defaults rewriting.
+    application = compileWithD8(application, options -> options.debug = false);
+    String result = runOnArt(application, CLASS_NAME);
+    assertEquals(result, "3");
+  }
+
+  @Test
+  public void b67468748InvalidCode() throws Exception {
     final String CLASS_NAME = "Test";
 
     SmaliBuilder builder = new SmaliBuilder(CLASS_NAME);
@@ -592,7 +627,7 @@
         3,
         "sget-object         v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
         "sget                v1, LTest;->intField:I",
-        "invoke-virtual      { v0, v1 }, Ljava/io/PrintStream;->println(I)V",
+        "invoke-virtual      { v0, v1 }, Ljava/io/PrintStream;->print(I)V",
         "return-void"
     );