Class Linker: Implement default interface verification ordering.

We ensure that default interface verification failure is propagated to
the implementing class so that the compiler is able to properly handle
verification failures. Furthermore we ensure that default interfaces
are verified at the same time their implementing classes are.

This does not add additional support for default methods to the verifier.

This adds a basic test of this functionality.

Previously assumptions made about the order of verification in our
code could cause a check failure during compilation. Our old code
assumed that all code that would be run during a classes
initialization had been verified before any of it was run. The default
interfaces broke this assumption. Now we will simply verify default
interfaces with any classes that implement them.

Bug: 24618811

Change-Id: Ia11a50a28889dbd7ca22ffa730ef443e39f3cb5b
diff --git a/test/965-default-verify/build b/test/965-default-verify/build
new file mode 100755
index 0000000..3727f5e
--- /dev/null
+++ b/test/965-default-verify/build
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# make us exit on a failure
+set -e
+
+if [[ $@ == *"--jvm"* ]]; then
+  # Build the Java files if we are running a --jvm test
+  mkdir -p src classes
+  ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
+  ${JAVAC} -implicit:none -d classes build-src/Statics.java src/Main.java src/Iface.java
+  rm -f classes/Statics.class
+  ${JAVAC} -implicit:none -d classes src/Statics.java
+else
+  # TODO Support building with jack.
+  ./default-build "$@" --experimental default-methods
+fi
diff --git a/test/965-default-verify/build-src/Statics.java b/test/965-default-verify/build-src/Statics.java
new file mode 100644
index 0000000..300aeec
--- /dev/null
+++ b/test/965-default-verify/build-src/Statics.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Statics {
+  public static void nonexistantFunction() {
+      System.out.println("I don't exist");
+  }
+}
+
diff --git a/test/965-default-verify/expected.txt b/test/965-default-verify/expected.txt
new file mode 100644
index 0000000..b31314f
--- /dev/null
+++ b/test/965-default-verify/expected.txt
@@ -0,0 +1,15 @@
+Create Main instance
+Calling functions on concrete Main
+Calling verifiable function on Main
+Hello
+Calling unverifiable function on Main
+Expected NSME Thrown on Main
+Calling verifiable function on Main
+Hello
+Calling functions on interface Iface
+Calling verifiable function on Iface
+Hello
+Calling unverifiable function on Iface
+Expected NSME Thrown on Iface
+Calling verifiable function on Iface
+Hello
diff --git a/test/965-default-verify/info.txt b/test/965-default-verify/info.txt
new file mode 100644
index 0000000..2ccabf5
--- /dev/null
+++ b/test/965-default-verify/info.txt
@@ -0,0 +1,8 @@
+Smali-based tests for verification interaction with experimental interface
+default methods.
+
+build-src contains java files that are needed if you are to compile with javac
+since it is much more proactive about finding likely runtime errors then smali.
+
+To run with --jvm you must export JAVA_HOME to a Java 8 Language installation
+and pass the --use-java-home to run-test
diff --git a/test/965-default-verify/run b/test/965-default-verify/run
new file mode 100755
index 0000000..8944ea9
--- /dev/null
+++ b/test/965-default-verify/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+${RUN} "$@" --experimental default-methods
diff --git a/test/965-default-verify/smali/Iface.smali b/test/965-default-verify/smali/Iface.smali
new file mode 100644
index 0000000..74799a6
--- /dev/null
+++ b/test/965-default-verify/smali/Iface.smali
@@ -0,0 +1,40 @@
+# /*
+#  * Copyright (C) 2015 The Android Open Source Project
+#  *
+#  * Licensed under the Apache License, Version 2.0 (the "License");
+#  * you may not use this file except in compliance with the License.
+#  * You may obtain a copy of the License at
+#  *
+#  *      http://www.apache.org/licenses/LICENSE-2.0
+#  *
+#  * Unless required by applicable law or agreed to in writing, software
+#  * distributed under the License is distributed on an "AS IS" BASIS,
+#  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  * See the License for the specific language governing permissions and
+#  * limitations under the License.
+#  */
+#
+# public interface Iface {
+#   public default String sayHi() {
+#       return "Hello";
+#   }
+#
+#   public default void verificationSoftFail() {
+#       Statics.nonexistantFunction();
+#   }
+# }
+
+.class public abstract interface LIface;
+.super Ljava/lang/Object;
+
+.method public sayHi()Ljava/lang/String;
+    .locals 1
+    const-string v0, "Hello"
+    return-object v0
+.end method
+
+.method public verificationSoftFail()V
+    .locals 1
+    invoke-static {}, LStatics;->nonexistantFunction()V
+    return-void
+.end method
diff --git a/test/965-default-verify/smali/Main.smali b/test/965-default-verify/smali/Main.smali
new file mode 100644
index 0000000..8e90706
--- /dev/null
+++ b/test/965-default-verify/smali/Main.smali
@@ -0,0 +1,179 @@
+# /*
+#  * Copyright (C) 2015 The Android Open Source Project
+#  *
+#  * Licensed under the Apache License, Version 2.0 (the "License");
+#  * you may not use this file except in compliance with the License.
+#  * You may obtain a copy of the License at
+#  *
+#  *      http://www.apache.org/licenses/LICENSE-2.0
+#  *
+#  * Unless required by applicable law or agreed to in writing, software
+#  * distributed under the License is distributed on an "AS IS" BASIS,
+#  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  * See the License for the specific language governing permissions and
+#  * limitations under the License.
+#  */
+#
+# class Main implements Iface {
+#   public static void main(String[] args) {
+#       System.out.println("Create Main instance");
+#       Main m = new Main();
+#       System.out.println("Calling functions on concrete Main");
+#       callMain(m);
+#       System.out.println("Calling functions on interface Iface");
+#       callIface(m);
+#   }
+#
+#   public static void callMain(Main m) {
+#       System.out.println("Calling verifiable function on Main");
+#       System.out.println(m.sayHi());
+#       System.out.println("Calling unverifiable function on Main");
+#       try {
+#           m.verificationSoftFail();
+#           System.out.println("Unexpected no error Thrown on Main");
+#       } catch (NoSuchMethodError e) {
+#           System.out.println("Expected NSME Thrown on Main");
+#       } catch (Throwable e) {
+#           System.out.println("Unexpected Error Thrown on Main");
+#           e.printStackTrace(System.out);
+#       }
+#       System.out.println("Calling verifiable function on Main");
+#       System.out.println(m.sayHi());
+#       return;
+#   }
+#
+#   public static void callIface(Iface m) {
+#       System.out.println("Calling verifiable function on Iface");
+#       System.out.println(m.sayHi());
+#       System.out.println("Calling unverifiable function on Iface");
+#       try {
+#           m.verificationSoftFail();
+#           System.out.println("Unexpected no error Thrown on Iface");
+#       } catch (NoSuchMethodError e) {
+#           System.out.println("Expected NSME Thrown on Iface");
+#       } catch (Throwable e) {
+#           System.out.println("Unexpected Error Thrown on Iface");
+#           e.printStackTrace(System.out);
+#       }
+#       System.out.println("Calling verifiable function on Iface");
+#       System.out.println(m.sayHi());
+#       return;
+#   }
+# }
+
+.class public LMain;
+.super Ljava/lang/Object;
+.implements LIface;
+
+.method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
+.method public static main([Ljava/lang/String;)V
+    .locals 3
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    const-string v0, "Create Main instance"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    new-instance v2, LMain;
+    invoke-direct {v2}, LMain;-><init>()V
+
+    const-string v0, "Calling functions on concrete Main"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+    invoke-static {v2}, LMain;->callMain(LMain;)V
+
+    const-string v0, "Calling functions on interface Iface"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+    invoke-static {v2}, LMain;->callIface(LIface;)V
+
+    return-void
+.end method
+
+.method public static callIface(LIface;)V
+    .locals 3
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+    const-string v0, "Calling verifiable function on Iface"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    invoke-interface {p0}, LIface;->sayHi()Ljava/lang/String;
+    move-result-object v0
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    const-string v0, "Calling unverifiable function on Iface"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+    :try_start
+        invoke-interface {p0}, LIface;->verificationSoftFail()V
+
+        const-string v0, "Unexpected no error Thrown on Iface"
+        invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+        goto :error_end
+    :try_end
+    .catch Ljava/lang/NoSuchMethodError; {:try_start .. :try_end} :NSME_error_start
+    .catch Ljava/lang/Throwable; {:try_start .. :try_end} :other_error_start
+    :NSME_error_start
+        const-string v0, "Expected NSME Thrown on Iface"
+        invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+        goto :error_end
+    :other_error_start
+        move-exception v2
+        const-string v0, "Unexpected Error Thrown on Iface"
+        invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+        invoke-virtual {v2,v1}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V
+        goto :error_end
+    :error_end
+    const-string v0, "Calling verifiable function on Iface"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    invoke-interface {p0}, LIface;->sayHi()Ljava/lang/String;
+    move-result-object v0
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    return-void
+.end method
+
+.method public static callMain(LMain;)V
+    .locals 3
+    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+    const-string v0, "Calling verifiable function on Main"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    invoke-virtual {p0}, LMain;->sayHi()Ljava/lang/String;
+    move-result-object v0
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    const-string v0, "Calling unverifiable function on Main"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+    :try_start
+        invoke-virtual {p0}, LMain;->verificationSoftFail()V
+
+        const-string v0, "Unexpected no error Thrown on Main"
+        invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+        goto :error_end
+    :try_end
+    .catch Ljava/lang/NoSuchMethodError; {:try_start .. :try_end} :NSME_error_start
+    .catch Ljava/lang/Throwable; {:try_start .. :try_end} :other_error_start
+    :NSME_error_start
+        const-string v0, "Expected NSME Thrown on Main"
+        invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+        goto :error_end
+    :other_error_start
+        move-exception v2
+        const-string v0, "Unexpected Error Thrown on Main"
+        invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+        invoke-virtual {v2,v1}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V
+        goto :error_end
+    :error_end
+    const-string v0, "Calling verifiable function on Main"
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    invoke-virtual {p0}, LMain;->sayHi()Ljava/lang/String;
+    move-result-object v0
+    invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+    return-void
+.end method
diff --git a/test/965-default-verify/smali/Statics.smali b/test/965-default-verify/smali/Statics.smali
new file mode 100644
index 0000000..1e8cac0
--- /dev/null
+++ b/test/965-default-verify/smali/Statics.smali
@@ -0,0 +1,30 @@
+# /*
+#  * Copyright (C) 2015 The Android Open Source Project
+#  *
+#  * Licensed under the Apache License, Version 2.0 (the "License");
+#  * you may not use this file except in compliance with the License.
+#  * You may obtain a copy of the License at
+#  *
+#  *      http://www.apache.org/licenses/LICENSE-2.0
+#  *
+#  * Unless required by applicable law or agreed to in writing, software
+#  * distributed under the License is distributed on an "AS IS" BASIS,
+#  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  * See the License for the specific language governing permissions and
+#  * limitations under the License.
+#  */
+#
+# class Statics {
+#   // public static void nonexistantFunction() {
+#   //     System.out.println("I don't exist");
+#   // }
+# }
+#
+.class public LStatics;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method