From 9a6c6a465045e13e5cd74d5e709b5cdab0685f83 Mon Sep 17 00:00:00 2001 From: Deepu Ganapathiyadan Date: Wed, 26 Jun 2019 14:06:49 -0700 Subject: [PATCH] Fix a null pointer while converting bundle array to list object. Add more tests. --- .../bridge/util/ArgumentsExTests.java | 133 ++++++++++++++++++ .../bridge/util/BridgeArgumentsTest.java | 27 +++- .../bridge/helpers/ArgumentsEx.java | 34 ++--- .../bridge/util/BridgeArguments.java | 8 +- 4 files changed, 183 insertions(+), 19 deletions(-) create mode 100644 android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/ArgumentsExTests.java diff --git a/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/ArgumentsExTests.java b/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/ArgumentsExTests.java new file mode 100644 index 00000000..16b9a1f9 --- /dev/null +++ b/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/ArgumentsExTests.java @@ -0,0 +1,133 @@ +package com.walmartlabs.electrode.reactnative.bridge.util; + +import android.os.Bundle; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.walmartlabs.electrode.reactnative.bridge.BaseBridgeTestCase; +import com.walmartlabs.electrode.reactnative.bridge.helpers.ArgumentsEx; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class ArgumentsExTests extends BaseBridgeTestCase { + + @Test + public void toBundleNull() { + assertEquals(0, ArgumentsEx.toBundle(null).size()); + } + + @Test + public void toBundleEmpty() { + WritableMap readableMap = Arguments.createMap(); + assertEquals(0, ArgumentsEx.toBundle(readableMap).size()); + } + + @Test + public void toBundleEmptyArray() { + WritableMap readableMap = Arguments.createMap(); + readableMap.putArray("test", Arguments.createArray()); + assertEquals(0, ArgumentsEx.toBundle(readableMap).size()); + } + + @Test + public void toBundleNullKeyValue() { + WritableMap readableMap = Arguments.createMap(); + readableMap.putArray("test", null); + Bundle outBundle = ArgumentsEx.toBundle(readableMap); + assertEquals(1, outBundle.size()); + } + + @Test + public void toBundleStringArray() { + final String STRING_ARRAY = "stringArray"; + WritableMap readableMap = Arguments.createMap(); + WritableArray stringArray = Arguments.createArray(); + stringArray.pushString("1"); + stringArray.pushString("2"); + stringArray.pushString("3"); + stringArray.pushString("4"); + + readableMap.putArray(STRING_ARRAY, stringArray); + Bundle outBundle = ArgumentsEx.toBundle(readableMap); + assertEquals(1, outBundle.size()); + assertNotNull(outBundle.getStringArray(STRING_ARRAY)); + String[] outArray = outBundle.getStringArray(STRING_ARRAY); + assertEquals(readableMap.getArray(STRING_ARRAY).size(), outArray.length); + } + + @Test + public void toBundleBooleanArray() { + final String BOOLEAN_ARRAY = "booleanArray"; + WritableMap readableMap = Arguments.createMap(); + WritableArray booleanArray = Arguments.createArray(); + booleanArray.pushBoolean(true); + booleanArray.pushBoolean(true); + booleanArray.pushBoolean(true); + booleanArray.pushBoolean(true); + + readableMap.putArray(BOOLEAN_ARRAY, booleanArray); + Bundle outBundle = ArgumentsEx.toBundle(readableMap); + assertEquals(1, outBundle.size()); + assertNotNull(outBundle.getBooleanArray(BOOLEAN_ARRAY)); + boolean[] outArray = outBundle.getBooleanArray(BOOLEAN_ARRAY); + ReadableArray expectedArray = readableMap.getArray(BOOLEAN_ARRAY); + assertEquals(expectedArray.size(), outArray.length); + + for (int i = 0; i < expectedArray.size(); i++) { + boolean expected = expectedArray.getBoolean(i); + assertEquals(expected, outArray[i]); + } + } + + @Test + public void toBundleNumberArray() { + final String NUMBER_ARRAY = "numberArray"; + WritableMap readableMap = Arguments.createMap(); + WritableArray numberArray = Arguments.createArray(); + numberArray.pushInt(1); + numberArray.pushInt(2); + numberArray.pushInt(3); + numberArray.pushInt(4); + + readableMap.putArray(NUMBER_ARRAY, numberArray); + Bundle outBundle = ArgumentsEx.toBundle(readableMap); + assertEquals(1, outBundle.size()); + double[] outArray = outBundle.getDoubleArray(NUMBER_ARRAY); + assertNotNull(outArray); + ReadableArray expectedArray = readableMap.getArray(NUMBER_ARRAY); + assertEquals(expectedArray.size(), outArray.length); + + for (int i = 0; i < expectedArray.size(); i++) { + int expected = expectedArray.getInt(i); + assertEquals(expected, outArray[i], 0); + } + } + + @Test + public void toBundleMap() { + final String MAP = "map"; + WritableMap readableMap = Arguments.createMap(); + WritableMap readableMapData = Arguments.createMap(); + readableMapData.putArray("nullKey", null); + readableMapData.putString("string", "some string"); + readableMapData.putInt("int", 1); + readableMapData.putBoolean("bool", true); + readableMap.putMap(MAP, readableMapData); + Bundle outBundle = ArgumentsEx.toBundle(readableMap); + assertEquals(1, outBundle.size()); + + Bundle innerBundle = outBundle.getBundle(MAP); + assertNotNull(innerBundle); + assertNull(innerBundle.get("nullKey")); + assertEquals("some string", innerBundle.getString("string")); + assertEquals(1, innerBundle.getDouble("int"), 0); + assertTrue(innerBundle.getBoolean("bool")); + } +} diff --git a/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArgumentsTest.java b/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArgumentsTest.java index b2f29c73..52b19e3b 100644 --- a/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArgumentsTest.java +++ b/android/electrode-reactnative-bridge/src/androidTest/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArgumentsTest.java @@ -327,7 +327,7 @@ public void testModelParcelable() { add(40); }}; final Person inputPerson = new Person.Builder("testName", 10).addresses(addressList).siblingsNames(namesList).siblingsAges(agesList).build(); - Parcel personParcel = Parcel.obtain(); + Parcel personParcel = Parcel.obtain(); inputPerson.writeToParcel(personParcel, inputPerson.describeContents()); personParcel.setDataPosition(0); @@ -339,4 +339,29 @@ public void testModelParcelable() { assertEquals(inputPerson.getName(), outPerson.getName()); } + + public void testNullList() { + final Person inputPerson = new Person.Builder("testName", 10).addresses(null).siblingsNames(null).siblingsAges(null).build(); + Parcel personParcel = Parcel.obtain(); + inputPerson.writeToParcel(personParcel, inputPerson.describeContents()); + personParcel.setDataPosition(0); + + Person outPerson = Person.CREATOR.createFromParcel(personParcel); + assertNotNull(outPerson); + assertEquals(0, outPerson.getAddressList().size()); + assertEquals(0, outPerson.getSiblingsAges().size()); + assertEquals(0, outPerson.getSiblingsNames().size()); + assertEquals(inputPerson.getName(), outPerson.getName()); + } + + public void testNullListItem() { + Bundle bundle = new Bundle(); + bundle.putString("name", "John"); + bundle.putInt("month", 1); + bundle.putString("addressList", null); + + Person person = new Person(bundle); + assertNotNull(person); + } + } \ No newline at end of file diff --git a/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/helpers/ArgumentsEx.java b/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/helpers/ArgumentsEx.java index f6622294..5865083a 100644 --- a/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/helpers/ArgumentsEx.java +++ b/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/helpers/ArgumentsEx.java @@ -137,22 +137,24 @@ public static Bundle toBundle(@Nullable ReadableMap readableMap) { break; case Array: { ReadableArray readableArray = readableMap.getArray(key); - switch (readableArray.getType(0)) { - case String: - bundle.putStringArray(key, ArgumentsEx.toStringArray(readableArray)); - break; - case Boolean: - bundle.putBooleanArray(key, ArgumentsEx.toBooleanArray(readableArray)); - break; - case Number: - // Can be int or double but we just assume double for now - bundle.putDoubleArray(key, ArgumentsEx.toDoubleArray(readableArray)); - break; - case Map: - bundle.putParcelableArray(key, ArgumentsEx.toBundleArray(readableArray)); - break; - case Array: - throw new UnsupportedOperationException("Arrays of arrays is not supported"); + if(readableArray.size() > 0) { + switch (readableArray.getType(0)) { + case String: + bundle.putStringArray(key, ArgumentsEx.toStringArray(readableArray)); + break; + case Boolean: + bundle.putBooleanArray(key, ArgumentsEx.toBooleanArray(readableArray)); + break; + case Number: + // Can be int or double but we just assume double for now + bundle.putDoubleArray(key, ArgumentsEx.toDoubleArray(readableArray)); + break; + case Map: + bundle.putParcelableArray(key, ArgumentsEx.toBundleArray(readableArray)); + break; + case Array: + throw new UnsupportedOperationException("Arrays of arrays is not supported"); + } } } break; diff --git a/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArguments.java b/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArguments.java index e98b2fab..0c422324 100644 --- a/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArguments.java +++ b/android/electrode-reactnative-bridge/src/main/java/com/walmartlabs/electrode/reactnative/bridge/util/BridgeArguments.java @@ -211,10 +211,14 @@ private static boolean isArray(@NonNull Object obj) { /** * @param obj input array - * @param listItemClass Defines the conent type of the list + * @param listItemClass Defines the content type of the list * @return List */ - public static List getList(Object obj, @NonNull Class listItemClass) { + public static List getList(@Nullable Object obj, @NonNull Class listItemClass) { + if (obj == null) { + return new ArrayList<>(); + } + if (!isArray(obj)) { throw new IllegalArgumentException("Should never reach here, expected an array, received: " + obj); }