Add JNI tests for lambdas

Bug: 27259142

Change-Id: I2a1b31db85dc487c1e6a62609d4497c3a4d4d3a6
diff --git a/test/004-JniTest/build b/test/004-JniTest/build
new file mode 100755
index 0000000..e8e9f31
--- /dev/null
+++ b/test/004-JniTest/build
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Copyright 2016 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
+
+# Hard-wired use of experimental jack.
+# TODO: fix this temporary work-around for lambdas, see b/19467889
+export USE_JACK=true
+# export JACK_SERVER=false
+# export JACK_REPOSITORY="${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/jacks"
+
+# e.g. /foo/bar/jack-3.10.ALPHA.jar -> 3.10.ALPHA
+# export JACK_VERSION="$(find "$JACK_REPOSITORY" -name '*ALPHA*' | sed 's/.*jack-//g' | sed 's/[.]jar//g')"
+./default-build "$@" --experimental lambdas
diff --git a/test/004-JniTest/expected.txt b/test/004-JniTest/expected.txt
index 155c6ae..f7e404d 100644
--- a/test/004-JniTest/expected.txt
+++ b/test/004-JniTest/expected.txt
@@ -55,3 +55,6 @@
 DefaultInterface.JniCallSoftConflictMethod
 Calling method ConflictInterface->JniCallConflictDefaultMethod on object of type ConcreteClass
 EXCEPTION OCCURED: java.lang.IncompatibleClassChangeError: Conflicting default method implementations void ConflictInterface.JniCallConflictDefaultMethod()
+hi-lambda: λ
+hi-default δλ
+hi-default δλ
diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc
index f632331..2bdf8d1 100644
--- a/test/004-JniTest/jni_test.cc
+++ b/test/004-JniTest/jni_test.cc
@@ -721,3 +721,22 @@
 extern "C" JNIEXPORT void JNICALL Java_Main_testCallDefaultMethods(JNIEnv* env) {
   JniCallDefaultMethodsTest(env).Test();
 }
+
+static void InvokeSpecificMethod(JNIEnv* env, jobject obj, const char* method) {
+  jclass lambda_class = env->FindClass("LambdaInterface");
+  assert(!env->ExceptionCheck());
+  assert(lambda_class != nullptr);
+  jmethodID method_id = env->GetMethodID(lambda_class, method, "()V");
+  assert(!env->ExceptionCheck());
+  env->CallVoidMethod(obj, method_id);
+  assert(!env->ExceptionCheck());
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaDefaultMethod(
+    JNIEnv* e, jclass, jobject l) {
+  InvokeSpecificMethod(e, l, "sayHiTwice");
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaMethod(JNIEnv* e, jclass, jobject l) {
+  InvokeSpecificMethod(e, l, "sayHi");
+}
diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java
index 9f4a852..e0530d8 100644
--- a/test/004-JniTest/src/Main.java
+++ b/test/004-JniTest/src/Main.java
@@ -40,6 +40,10 @@
         testProxyGetMethodID();
         testJniCriticalSectionAndGc();
         testCallDefaultMethods();
+        String lambda = "λ";
+        testInvokeLambdaMethod(() -> { System.out.println("hi-lambda: " + lambda); });
+        String def = "δ";
+        testInvokeLambdaDefaultMethod(() -> { System.out.println("hi-default " + def + lambda); });
     }
 
     private static native void testCallDefaultMethods();
@@ -255,6 +259,19 @@
     }
 
     private static native void enterJniCriticalSection(int arraySize, byte[] array0, byte[] array);
+
+    private static native void testInvokeLambdaMethod(LambdaInterface iface);
+
+    private static native void testInvokeLambdaDefaultMethod(LambdaInterface iface);
+}
+
+@FunctionalInterface
+interface LambdaInterface {
+  public void sayHi();
+  public default void sayHiTwice() {
+    sayHi();
+    sayHi();
+  }
 }
 
 class JniCallNonvirtualTest {