Merge "Enable passing of publishedData to scripts." into sc-v2-dev
diff --git a/packages/ScriptExecutor/src/BundleWrapper.cpp b/packages/ScriptExecutor/src/BundleWrapper.cpp
index 938854f..8957833 100644
--- a/packages/ScriptExecutor/src/BundleWrapper.cpp
+++ b/packages/ScriptExecutor/src/BundleWrapper.cpp
@@ -49,10 +49,11 @@
static_cast<jboolean>(value));
}
-void BundleWrapper::putInteger(const char* key, int value) {
- jmethodID putIntMethod = mJNIEnv->GetMethodID(mBundleClass, "putInt", "(Ljava/lang/String;I)V");
- mJNIEnv->CallVoidMethod(mBundle, putIntMethod, mJNIEnv->NewStringUTF(key),
- static_cast<jint>(value));
+void BundleWrapper::putLong(const char* key, int64_t value) {
+ jmethodID putLongMethod =
+ mJNIEnv->GetMethodID(mBundleClass, "putLong", "(Ljava/lang/String;J)V");
+ mJNIEnv->CallVoidMethod(mBundle, putLongMethod, mJNIEnv->NewStringUTF(key),
+ static_cast<jlong>(value));
}
void BundleWrapper::putDouble(const char* key, double value) {
diff --git a/packages/ScriptExecutor/src/BundleWrapper.h b/packages/ScriptExecutor/src/BundleWrapper.h
index e15c56a..7303bd0 100644
--- a/packages/ScriptExecutor/src/BundleWrapper.h
+++ b/packages/ScriptExecutor/src/BundleWrapper.h
@@ -40,7 +40,7 @@
// Family of methods that puts the provided 'value' into the PersistableBundle
// under provided 'key'.
void putBoolean(const char* key, bool value);
- void putInteger(const char* key, int value);
+ void putLong(const char* key, int64_t value);
void putDouble(const char* key, double value);
void putString(const char* key, const char* value);
void putLongArray(const char* key, const std::vector<int64_t>& value);
diff --git a/packages/ScriptExecutor/src/JniUtils.cpp b/packages/ScriptExecutor/src/JniUtils.cpp
index 90683ce..3152722 100644
--- a/packages/ScriptExecutor/src/JniUtils.cpp
+++ b/packages/ScriptExecutor/src/JniUtils.cpp
@@ -44,6 +44,7 @@
jclass booleanClass = env->FindClass("java/lang/Boolean");
jclass integerClass = env->FindClass("java/lang/Integer");
+ jclass longClass = env->FindClass("java/lang/Long");
jclass numberClass = env->FindClass("java/lang/Number");
jclass stringClass = env->FindClass("java/lang/String");
jclass intArrayClass = env->FindClass("[I");
@@ -70,6 +71,10 @@
} else if (env->IsInstanceOf(value, integerClass)) {
jmethodID intMethod = env->GetMethodID(integerClass, "intValue", "()I");
lua_pushinteger(luaEngine->getLuaState(), env->CallIntMethod(value, intMethod));
+ } else if (env->IsInstanceOf(value, longClass)) {
+ jmethodID longMethod = env->GetMethodID(longClass, "longValue", "()J");
+ lua_pushinteger(luaEngine->getLuaState(), env->CallLongMethod(value, longMethod));
+
} else if (env->IsInstanceOf(value, numberClass)) {
// Condense other numeric types using one class. Because lua supports only
// integer or double, and we handled integer in previous if clause.
diff --git a/packages/ScriptExecutor/src/LuaEngine.cpp b/packages/ScriptExecutor/src/LuaEngine.cpp
index 55bb977..023333d 100644
--- a/packages/ScriptExecutor/src/LuaEngine.cpp
+++ b/packages/ScriptExecutor/src/LuaEngine.cpp
@@ -72,7 +72,7 @@
if (lua_isboolean(lua, /* index = */ -1)) {
bundleWrapper->putBoolean(key, static_cast<bool>(lua_toboolean(lua, /* index = */ -1)));
} else if (lua_isinteger(lua, /* index = */ -1)) {
- bundleWrapper->putInteger(key, static_cast<int>(lua_tointeger(lua, /* index = */ -1)));
+ bundleWrapper->putLong(key, static_cast<int64_t>(lua_tointeger(lua, /* index = */ -1)));
} else if (lua_isnumber(lua, /* index = */ -1)) {
bundleWrapper->putDouble(key, static_cast<double>(lua_tonumber(lua, /* index = */ -1)));
} else if (lua_isstring(lua, /* index = */ -1)) {
@@ -248,10 +248,8 @@
// input arguments are in the Lua stack as well in proper order.
// On how to call Lua functions: https://www.lua.org/pil/25.2.html
// Doc on lua_pcall: https://www.lua.org/manual/5.3/manual.html#lua_pcall
- // TODO(b/189241508): Once we implement publishedData parsing, nargs should
- // change from 1 to 2.
// TODO(b/192284612): add test case for failed call.
- return lua_pcall(mLuaState, /* nargs= */ 1, /* nresults= */ 0, /*errfunc= */ 0);
+ return lua_pcall(mLuaState, /* nargs= */ 2, /* nresults= */ 0, /*errfunc= */ 0);
}
int LuaEngine::onSuccess(lua_State* lua) {
diff --git a/packages/ScriptExecutor/src/ScriptExecutorJni.cpp b/packages/ScriptExecutor/src/ScriptExecutorJni.cpp
index c11a30b..a5add58 100644
--- a/packages/ScriptExecutor/src/ScriptExecutorJni.cpp
+++ b/packages/ScriptExecutor/src/ScriptExecutorJni.cpp
@@ -108,11 +108,8 @@
return;
}
- // TODO(b/189241508): Provide implementation to parse publishedData input,
- // convert it into Lua table and push into Lua stack.
- if (publishedData) {
- LOG(WARNING) << "Parsing of publishedData is not implemented yet.";
- }
+ // Unpack bundle in publishedData, convert to Lua table and push it to Lua stack.
+ pushBundleToLuaTable(env, engine, publishedData);
// Unpack bundle in savedState, convert to Lua table and push it to Lua
// stack.
diff --git a/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java b/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
index d2cb1c8..06e318b 100644
--- a/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
+++ b/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
@@ -84,9 +84,7 @@
return;
}
- // TODO(b/189241508): Start passing publishedData instead of null
- // once publishedData parser is implemented.
- nativeInvokeScript(mLuaEnginePtr, scriptBody, functionName, null,
+ nativeInvokeScript(mLuaEnginePtr, scriptBody, functionName, publishedData,
savedState, listener);
});
}
diff --git a/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java b/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
index cb76a75..52b5cc7 100644
--- a/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
+++ b/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
@@ -86,18 +86,9 @@
private final ScriptExecutorListener mFakeScriptExecutorListener =
new ScriptExecutorListener();
- // TODO(b/189241508). Parsing of publishedData is not implemented yet.
- // Null is the only accepted input.
- private final PersistableBundle mPublishedData = null;
+ private final PersistableBundle mPublishedData = new PersistableBundle();
private final PersistableBundle mSavedState = new PersistableBundle();
- private static final String LUA_SCRIPT =
- "function hello(state)\n"
- + " print(\"Hello World\")\n"
- + "end\n";
-
- private static final String LUA_METHOD = "hello";
-
private final CountDownLatch mBindLatch = new CountDownLatch(1);
private static final int BIND_SERVICE_TIMEOUT_SEC = 5;
@@ -120,9 +111,9 @@
// Helper method to invoke the script and wait for it to complete and return a response.
private void runScriptAndWaitForResponse(String script, String function,
- PersistableBundle previousState)
+ PersistableBundle publishedData, PersistableBundle previousState)
throws RemoteException {
- mScriptExecutor.invokeScript(script, function, mPublishedData, previousState,
+ mScriptExecutor.invokeScript(script, function, publishedData, previousState,
mFakeScriptExecutorListener);
try {
if (!mFakeScriptExecutorListener.mResponseLatch.await(SCRIPT_PROCESSING_TIMEOUT_SEC,
@@ -136,7 +127,8 @@
}
private void runScriptAndWaitForError(String script, String function) throws RemoteException {
- runScriptAndWaitForResponse(script, function, new PersistableBundle());
+ runScriptAndWaitForResponse(script, function, new PersistableBundle(),
+ new PersistableBundle());
}
@Before
@@ -152,32 +144,15 @@
}
@Test
- public void invokeScript_helloWorld() throws RemoteException {
- // Expect to load "hello world" script successfully and push the function.
- mScriptExecutor.invokeScript(LUA_SCRIPT, LUA_METHOD, mPublishedData, mSavedState,
- mFakeScriptExecutorListener);
- // Sleep, otherwise the test case will complete before the script loads
- // because invokeScript is non-blocking.
- try {
- // TODO(b/192285332): Replace sleep logic with waiting for specific callbacks
- // to be called once they are implemented. Otherwise, this could be a flaky test.
- TimeUnit.SECONDS.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- fail(e.getMessage());
- }
- }
-
- @Test
public void invokeScript_returnsResult() throws RemoteException {
String returnResultScript =
- "function hello(state)\n"
+ "function hello(data, state)\n"
+ " result = {hello=\"world\"}\n"
+ " on_success(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(returnResultScript, "hello", mSavedState);
+ runScriptAndWaitForResponse(returnResultScript, "hello", mPublishedData, mSavedState);
// Expect to get back a bundle with a single string key: string value pair:
// {"hello": "world"}
@@ -189,34 +164,34 @@
@Test
public void invokeScript_allSupportedPrimitiveTypes() throws RemoteException {
String script =
- "function knows(state)\n"
+ "function knows(data, state)\n"
+ " result = {string=\"hello\", boolean=true, integer=1, number=1.1}\n"
+ " on_success(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "knows", mSavedState);
+ runScriptAndWaitForResponse(script, "knows", mPublishedData, mSavedState);
// Expect to get back a bundle with 4 keys, each corresponding to a distinct supported type.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(4);
assertThat(mFakeScriptExecutorListener.mSavedBundle.getString("string")).isEqualTo(
"hello");
assertThat(mFakeScriptExecutorListener.mSavedBundle.getBoolean("boolean")).isEqualTo(true);
- assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("integer")).isEqualTo(1);
+ assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("integer")).isEqualTo(1);
assertThat(mFakeScriptExecutorListener.mSavedBundle.getDouble("number")).isEqualTo(1.1);
}
@Test
public void invokeScript_skipsUnsupportedTypes() throws RemoteException {
String script =
- "function nested(state)\n"
+ "function nested(data, state)\n"
+ " result = {string=\"hello\", boolean=true, integer=1, number=1.1}\n"
+ " result.nested_table = {x=0, y=0}\n"
+ " on_success(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "nested", mSavedState);
+ runScriptAndWaitForResponse(script, "nested", mPublishedData, mSavedState);
// Verify that expected error is received.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -228,13 +203,13 @@
@Test
public void invokeScript_emptyBundle() throws RemoteException {
String script =
- "function empty(state)\n"
+ "function empty(data, state)\n"
+ " result = {}\n"
+ " on_success(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "empty", mSavedState);
+ runScriptAndWaitForResponse(script, "empty", mPublishedData, mSavedState);
// If a script returns empty table as the result, we get an empty bundle.
assertThat(mFakeScriptExecutorListener.mSavedBundle).isNotNull();
@@ -245,9 +220,8 @@
public void invokeScript_processPreviousStateAndReturnResult() throws RemoteException {
// Here we verify that the script actually processes provided state from a previous run
// and makes calculation based on that and returns the result.
- // TODO(b/189241508): update function signatures.
String script =
- "function update(state)\n"
+ "function update(data, state)\n"
+ " result = {y = state.x+1}\n"
+ " on_success(result)\n"
+ "end\n";
@@ -255,11 +229,11 @@
previousState.putInt("x", 1);
- runScriptAndWaitForResponse(script, "update", previousState);
+ runScriptAndWaitForResponse(script, "update", mPublishedData, previousState);
// Verify that y = 2, because y = x + 1 and x = 1.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
- assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("y")).isEqualTo(2);
+ assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("y")).isEqualTo(2);
}
@Test
@@ -267,9 +241,8 @@
throws RemoteException {
// Here we verify that all supported primitive types in supplied previous state Bundle
// are interpreted by the script as expected.
- // TODO(b/189241508): update function signatures.
String script =
- "function update_all(state)\n"
+ "function update_all(data, state)\n"
+ " result = {}\n"
+ " result.integer = state.integer + 1\n"
+ " result.number = state.number + 0.1\n"
@@ -284,11 +257,11 @@
previousState.putString("string", "ABRA");
- runScriptAndWaitForResponse(script, "update_all", previousState);
+ runScriptAndWaitForResponse(script, "update_all", mPublishedData, previousState);
// Verify that keys are preserved but the values are modified as expected.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(4);
- assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("integer")).isEqualTo(2);
+ assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("integer")).isEqualTo(2);
assertThat(mFakeScriptExecutorListener.mSavedBundle.getDouble("number")).isEqualTo(0.2);
assertThat(mFakeScriptExecutorListener.mSavedBundle.getBoolean("boolean")).isEqualTo(true);
assertThat(mFakeScriptExecutorListener.mSavedBundle.getString("string")).isEqualTo(
@@ -300,9 +273,8 @@
throws RemoteException {
// Here we verify that all supported array types in supplied previous state Bundle are
// interpreted by the script as expected.
- // TODO(b/189241508): update function signatures.
String script =
- "function arrays(state)\n"
+ "function arrays(data, state)\n"
+ " result = {}\n"
+ " result.int_array = state.int_array\n"
+ " result.long_array = state.long_array\n"
@@ -319,7 +291,7 @@
previousState.putStringArray("string_array", string_array);
- runScriptAndWaitForResponse(script, "arrays", previousState);
+ runScriptAndWaitForResponse(script, "arrays", mPublishedData, previousState);
// Verify that keys are preserved but the values are modified as expected.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(3);
@@ -338,9 +310,8 @@
public void invokeScript_modifiesArray()
throws RemoteException {
// Verify that an array modified by a script is properly sent back by the callback.
- // TODO(b/189241508): update function signatures.
String script =
- "function modify_array(state)\n"
+ "function modify_array(data, state)\n"
+ " result = {}\n"
+ " result.long_array = state.long_array\n"
+ " result.long_array[2] = 100\n"
@@ -352,7 +323,7 @@
long[] expected_array = new long[]{1, 100, 3};
- runScriptAndWaitForResponse(script, "modify_array", previousState);
+ runScriptAndWaitForResponse(script, "modify_array", mPublishedData, previousState);
// Verify that keys are preserved but the values are modified as expected.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
@@ -364,9 +335,8 @@
public void invokeScript_processesStringArray()
throws RemoteException {
// Verify that an array modified by a script is properly sent back by the callback.
- // TODO(b/189241508): update function signatures.
String script =
- "function process_string_array(state)\n"
+ "function process_string_array(data, state)\n"
+ " result = {}\n"
+ " result.answer = state.string_array[1] .. state.string_array[2]\n"
+ " on_success(result)\n"
@@ -375,7 +345,7 @@
String[] string_array = new String[]{"Hello ", "world!"};
previousState.putStringArray("string_array", string_array);
- runScriptAndWaitForResponse(script, "process_string_array", previousState);
+ runScriptAndWaitForResponse(script, "process_string_array", mPublishedData, previousState);
// Verify that keys are preserved but the values are modified as expected.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
@@ -387,9 +357,8 @@
public void invokeScript_arraysWithLengthAboveLimitCauseError()
throws RemoteException {
// Verifies that arrays pushed by Lua that have their size over the limit cause error.
- // TODO(b/189241508): update function signatures.
String script =
- "function size_limit(state)\n"
+ "function size_limit(data, state)\n"
+ " result = {}\n"
+ " result.huge_array = {}\n"
+ " for i=1, 10000 do\n"
@@ -398,7 +367,7 @@
+ " on_success(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "size_limit", mSavedState);
+ runScriptAndWaitForResponse(script, "size_limit", mPublishedData, mSavedState);
// Verify that expected error is received.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -414,9 +383,8 @@
throws RemoteException {
// Verifies that values in returned array must be the same integer type.
// For example string values in a Lua array are not allowed.
- // TODO(b/189241508): update function signatures.
String script =
- "function table_with_numbers_and_strings(state)\n"
+ "function table_with_numbers_and_strings(data, state)\n"
+ " result = {}\n"
+ " result.mixed_array = state.long_array\n"
+ " result.mixed_array[2] = 'a'\n"
@@ -426,7 +394,8 @@
long[] long_array = new long[]{1, 2, 3};
previousState.putLongArray("long_array", long_array);
- runScriptAndWaitForResponse(script, "table_with_numbers_and_strings", previousState);
+ runScriptAndWaitForResponse(script, "table_with_numbers_and_strings", mPublishedData,
+ previousState);
// Verify that expected error is received.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -440,9 +409,8 @@
throws RemoteException {
// Documents the current behavior that copies only indexed values in a Lua table that
// contains both keyed and indexed data.
- // TODO(b/189241508): update function signatures.
String script =
- "function keys_and_indices(state)\n"
+ "function keys_and_indices(data, state)\n"
+ " result = {}\n"
+ " result.mixed_array = state.long_array\n"
+ " result.mixed_array['a'] = 130\n"
@@ -452,7 +420,7 @@
long[] long_array = new long[]{1, 2, 3};
previousState.putLongArray("long_array", long_array);
- runScriptAndWaitForResponse(script, "keys_and_indices", previousState);
+ runScriptAndWaitForResponse(script, "keys_and_indices", mPublishedData, previousState);
// Verify that keys are preserved but the values are modified as expected.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
@@ -464,9 +432,8 @@
public void invokeScript_noLuaBufferOverflowForLargeInputArrays() throws RemoteException {
// Tests that arrays with length that exceed internal Lua buffer size of 20 elements
// do not cause buffer overflow and are handled properly.
- // TODO(b/189241508): update function signatures.
String script =
- "function large_input_array(state)\n"
+ "function large_input_array(data, state)\n"
+ " sum = 0\n"
+ " for _, val in ipairs(state.long_array) do\n"
+ " sum = sum + val\n"
@@ -485,11 +452,11 @@
long expected_sum =
(longArray[0] + longArray[n - 1]) * n / 2; // sum of an arithmetic sequence.
- runScriptAndWaitForResponse(script, "large_input_array", previousState);
+ runScriptAndWaitForResponse(script, "large_input_array", mPublishedData, previousState);
// Verify that keys are preserved but the values are modified as expected.
assertThat(mFakeScriptExecutorListener.mSavedBundle.size()).isEqualTo(1);
- assertThat(mFakeScriptExecutorListener.mSavedBundle.getInt("total")).isEqualTo(
+ assertThat(mFakeScriptExecutorListener.mSavedBundle.getLong("total")).isEqualTo(
expected_sum);
}
@@ -549,19 +516,20 @@
@Test
public void invokeScript_returnsFinalResult() throws RemoteException {
String returnFinalResultScript =
- "function script_finishes(state)\n"
+ "function script_finishes(data, state)\n"
+ " result = {data = state.input + 1}\n"
+ " on_script_finished(result)\n"
+ "end\n";
PersistableBundle previousState = new PersistableBundle();
previousState.putInt("input", 1);
- runScriptAndWaitForResponse(returnFinalResultScript, "script_finishes", previousState);
+ runScriptAndWaitForResponse(returnFinalResultScript, "script_finishes", mPublishedData,
+ previousState);
// Expect to get back a bundle with a single key-value pair {"data": 2}
// because data = state.input + 1 as in the script body above.
assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(1);
- assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("data")).isEqualTo(2);
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("data")).isEqualTo(2);
}
@Test
@@ -569,9 +537,8 @@
throws RemoteException {
// Here we verify that all supported primitive types are present in the returned final
// result bundle are present.
- // TODO(b/189241508): update function signatures.
String script =
- "function finalize_all(state)\n"
+ "function finalize_all(data, state)\n"
+ " result = {}\n"
+ " result.integer = state.integer + 1\n"
+ " result.number = state.number + 0.1\n"
@@ -586,11 +553,11 @@
previousState.putString("string", "ABRA");
- runScriptAndWaitForResponse(script, "finalize_all", previousState);
+ runScriptAndWaitForResponse(script, "finalize_all", mPublishedData, previousState);
// Verify that keys are preserved but the values are modified as expected.
assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(4);
- assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("integer")).isEqualTo(2);
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("integer")).isEqualTo(2);
assertThat(mFakeScriptExecutorListener.mFinalResult.getDouble("number")).isEqualTo(0.2);
assertThat(mFakeScriptExecutorListener.mFinalResult.getBoolean("boolean")).isEqualTo(true);
assertThat(mFakeScriptExecutorListener.mFinalResult.getString("string")).isEqualTo(
@@ -600,13 +567,13 @@
@Test
public void invokeScript_emptyFinalResultBundle() throws RemoteException {
String script =
- "function empty_final_result(state)\n"
+ "function empty_final_result(data, state)\n"
+ " result = {}\n"
+ " on_script_finished(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "empty_final_result", mSavedState);
+ runScriptAndWaitForResponse(script, "empty_final_result", mPublishedData, mSavedState);
// If a script returns empty table as the final result, we get an empty bundle.
assertThat(mFakeScriptExecutorListener.mFinalResult).isNotNull();
@@ -617,7 +584,7 @@
public void invokeScript_wrongNumberOfCallbackInputsInOnScriptFinished()
throws RemoteException {
String script =
- "function wrong_number_of_outputs_in_on_script_finished(state)\n"
+ "function wrong_number_of_outputs_in_on_script_finished(data, state)\n"
+ " result = {}\n"
+ " extra = 1\n"
+ " on_script_finished(result, extra)\n"
@@ -625,7 +592,7 @@
runScriptAndWaitForResponse(script, "wrong_number_of_outputs_in_on_script_finished",
- mSavedState);
+ mPublishedData, mSavedState);
// We expect to get an error here because we expect only 1 input parameter in
// on_script_finished.
@@ -638,14 +605,15 @@
@Test
public void invokeScript_wrongNumberOfCallbackInputsInOnSuccess() throws RemoteException {
String script =
- "function wrong_number_of_outputs_in_on_success(state)\n"
+ "function wrong_number_of_outputs_in_on_success(data, state)\n"
+ " result = {}\n"
+ " extra = 1\n"
+ " on_success(result, extra)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "wrong_number_of_outputs_in_on_success", mSavedState);
+ runScriptAndWaitForResponse(script, "wrong_number_of_outputs_in_on_success",
+ mPublishedData, mSavedState);
// We expect to get an error here because we expect only 1 input parameter in on_success.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
@@ -657,13 +625,14 @@
@Test
public void invokeScript_wrongTypeInOnSuccess() throws RemoteException {
String script =
- "function wrong_type_in_on_success(state)\n"
+ "function wrong_type_in_on_success(data, state)\n"
+ " result = 1\n"
+ " on_success(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "wrong_type_in_on_success", mSavedState);
+ runScriptAndWaitForResponse(script, "wrong_type_in_on_success",
+ mPublishedData, mSavedState);
// We expect to get an error here because the type of the input parameter for on_success
// must be a Lua table.
@@ -676,13 +645,14 @@
@Test
public void invokeScript_wrongTypeInOnScriptFinished() throws RemoteException {
String script =
- "function wrong_type_in_on_script_finished(state)\n"
+ "function wrong_type_in_on_script_finished(data, state)\n"
+ " result = 1\n"
+ " on_success(result)\n"
+ "end\n";
- runScriptAndWaitForResponse(script, "wrong_type_in_on_script_finished", mSavedState);
+ runScriptAndWaitForResponse(script, "wrong_type_in_on_script_finished",
+ mPublishedData, mSavedState);
// We expect to get an error here because the type of the input parameter for
// on_script_finished must be a Lua table.
@@ -696,11 +666,13 @@
public void invokeScriptLargeInput_largePublishedData() throws Exception {
// Verifies that large input does not overwhelm Binder's buffer because pipes are used
// instead.
- // TODO(b/189241508): Once publishedData parsing is implemented, change the script and
- // the test to process the published data input and return something meaningful.
String script =
- "function large_published_data(state)\n"
- + " result = {success = true}\n"
+ "function large_published_data(data, state)\n"
+ + " sum = 0\n"
+ + " for _, val in ipairs(data.array) do\n"
+ + " sum = sum + val\n"
+ + " end\n"
+ + " result = {total = sum}\n"
+ " on_script_finished(result)\n"
+ "end\n";
@@ -715,6 +687,8 @@
array8Mb[i] = i;
}
bundle.putLongArray("array", array8Mb);
+ long expectedSum =
+ (array8Mb[0] + array8Mb[n - 1]) * n / 2; // sum of an arithmetic sequence.
mScriptExecutor.invokeScriptForLargeInput(script, "large_published_data", readFd,
mSavedState,
@@ -729,10 +703,70 @@
SCRIPT_PROCESSING_TIMEOUT_SEC,
TimeUnit.SECONDS);
- assertWithMessage("Failed to get the callback method called by the script on time").that(
- gotResponse).isTrue();
+ assertWithMessage("Failed to get the callback method called by the script on time")
+ .that(gotResponse).isTrue();
assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(1);
- assertThat(mFakeScriptExecutorListener.mFinalResult.getBoolean("success")).isTrue();
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("total"))
+ .isEqualTo(expectedSum);
+ }
+
+ @Test
+ public void invokeScript_bothPublishedDataAndPreviousStateAreProvided() throws RemoteException {
+ // Verifies that both published data and previous state PersistableBundles
+ // are piped into script.
+ String script =
+ "function data_and_state(data, state)\n"
+ + " result = {answer = data.a .. data.b .. state.c .. state.d}\n"
+ + " on_script_finished(result)\n"
+ + "end\n";
+
+ PersistableBundle publishedData = new PersistableBundle();
+ publishedData.putString("a", "A");
+ publishedData.putString("b", "B");
+
+ PersistableBundle previousState = new PersistableBundle();
+ previousState.putString("c", "C");
+ previousState.putString("d", "D");
+
+ runScriptAndWaitForResponse(script, "data_and_state", publishedData, previousState);
+
+ // If a script returns empty table as the final result, we get an empty bundle.
+ assertThat(mFakeScriptExecutorListener.mFinalResult).isNotNull();
+ assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(1);
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getString("answer")).isEqualTo(
+ "ABCD");
+ }
+
+ @Test
+ public void invokeScript_outputIntAndLongAreTreatedAsLong() throws RemoteException {
+ // Verifies that we treat output both integer and long as long integer type although we
+ // distinguish between int and long in the script input.
+ String script =
+ "function int_and_long_are_output_long(data, state)\n"
+ + " result = {int = data.int, long = state.long}\n"
+ + " on_script_finished(result)\n"
+ + "end\n";
+
+ PersistableBundle publishedData = new PersistableBundle();
+ publishedData.putInt("int", 100);
+
+ PersistableBundle previousState = new PersistableBundle();
+ previousState.putLong("long", 200);
+
+ runScriptAndWaitForResponse(script, "int_and_long_are_output_long",
+ publishedData, previousState);
+
+ // If a script returns empty table as the final result, we get an empty bundle.
+ assertThat(mFakeScriptExecutorListener.mFinalResult).isNotNull();
+ assertThat(mFakeScriptExecutorListener.mFinalResult.size()).isEqualTo(2);
+ // getInt should always return "empty" value (zero) because all integer types are treated
+ // as Java long.
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("int")).isEqualTo(0);
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getInt("long")).isEqualTo(0);
+ // Instead all expected integer values are successfully retrieved using getLong method
+ // from the output bundle.
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("int")).isEqualTo(100);
+ assertThat(mFakeScriptExecutorListener.mFinalResult.getLong("long")).isEqualTo(200);
}
}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
index 7c4a4b1..d2f011f 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
@@ -43,7 +43,7 @@
public class CarTelemetryTestFragment extends Fragment {
private static final String LUA_SCRIPT_ON_GEAR_CHANGE =
- "function onGearChange(state)\n"
+ "function onGearChange(published_data, state)\n"
+ " result = {data = \"Hello World!\"}\n"
+ " on_script_finished(result)\n"
+ "end\n";