Skip to content

Commit 5487588

Browse files
committed
Test parcel while saving, tests for ParseRelation
1 parent 257840f commit 5487588

File tree

4 files changed

+100
-6
lines changed

4 files changed

+100
-6
lines changed

Parse/src/main/java/com/parse/ParseObjectParcelDecoder.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
* {@code ParseObject}s have been decoded. When a pointer is found and we have already decoded
1313
* an instance for the same object id, we use the decoded instance.
1414
*
15-
* This is very similar to what {@link KnownParseObjectDecoder} does for JSON, and is meant to be
16-
* used with {@link ParseObjectParcelEncoder}.
15+
* This is very similar to what {@link KnownParseObjectDecoder} does for JSON.
1716
*/
1817
/* package */ class ParseObjectParcelDecoder extends ParseParcelDecoder {
1918

@@ -32,11 +31,13 @@ protected ParseObject decodePointer(Parcel source) {
3231
if (objects.containsKey(objectId)) {
3332
return objects.get(objectId);
3433
}
35-
// Should not happen if using in conjunction with ParseObjectParcelEncoder .
36-
return ParseObject.createWithoutData(className, objectId);
34+
// Should not happen if encoding was done through ParseObjectParcelEncoder.
35+
ParseObject object = ParseObject.createWithoutData(className, objectId);
36+
objects.put(objectId, object);
37+
return object;
3738
}
3839

39-
/* package for tests */ String getObjectOrLocalId(ParseObject object) {
40+
private String getObjectOrLocalId(ParseObject object) {
4041
return object.getObjectId() != null ? object.getObjectId() : object.getOrCreateLocalId();
4142
}
4243
}

Parse/src/main/java/com/parse/ParseParcelEncoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public void encode(Object object, Parcel dest) {
133133
+ object.getClass().toString());
134134
}
135135

136-
} catch (Exception e) {
136+
} catch (IllegalArgumentException e) {
137137
throw new IllegalArgumentException("Could not encode this object into Parcel. "
138138
+ object.getClass().toString());
139139
}

Parse/src/test/java/com/parse/ParseObjectTest.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import static org.mockito.Matchers.any;
4242
import static org.mockito.Matchers.anyString;
4343
import static org.mockito.Mockito.mock;
44+
import static org.mockito.Mockito.verify;
4445
import static org.mockito.Mockito.when;
4546

4647
@RunWith(RobolectricTestRunner.class)
@@ -582,6 +583,61 @@ public void testRecursiveParcel() throws Exception {
582583
assertEquals(newObject.getParseObject("self").getParseObject("self").getObjectId(), "id");
583584
}
584585

586+
@Test
587+
public void testParcelWhileSaving() throws Exception {
588+
ParseFieldOperations.registerDefaultDecoders();
589+
ParseObject object, other;
590+
List<Task<Void>> tasks = new ArrayList<>();
591+
592+
// Mocked to let save work
593+
ParseCurrentUserController userController = mock(ParseCurrentUserController.class);
594+
when(userController.getAsync()).thenReturn(Task.<ParseUser>forResult(null));
595+
ParseCorePlugins.getInstance().registerCurrentUserController(userController);
596+
597+
// Mocked to simulate in-flight save
598+
TaskCompletionSource<ParseObject.State> tcs = new TaskCompletionSource<>();
599+
ParseObjectController objectController = mock(ParseObjectController.class);
600+
when(objectController.saveAsync(
601+
any(ParseObject.State.class),
602+
any(ParseOperationSet.class),
603+
anyString(),
604+
any(ParseDecoder.class)))
605+
.thenReturn(tcs.getTask());
606+
ParseCorePlugins.getInstance().registerObjectController(objectController);
607+
608+
// Create multiple ParseOperationSets
609+
object = new ParseObject("TestObject");
610+
object.setObjectId("id");
611+
object.put("key", "value");
612+
object.put("number", 5);
613+
tasks.add(object.saveInBackground());
614+
615+
object.put("key", "newValue");
616+
object.increment("number", 6);
617+
tasks.add(object.saveInBackground());
618+
619+
object.increment("number", -1);
620+
tasks.add(object.saveInBackground());
621+
622+
// Ensure Log.w is called...
623+
assertTrue(object.hasOutstandingOperations());
624+
Parcel parcel = Parcel.obtain();
625+
object.writeToParcel(parcel, 0);
626+
parcel.setDataPosition(0);
627+
other = ParseObject.CREATOR.createFromParcel(parcel);
628+
assertTrue(other.isDirty("key"));
629+
assertTrue(other.isDirty("number"));
630+
assertEquals(other.getString("key"), "newValue");
631+
assertEquals(other.getNumber("number"), 10);
632+
// By design, we assume that old operations failed even if
633+
// they are still running on the old instance.
634+
assertFalse(other.hasOutstandingOperations());
635+
636+
// Force finish save operations on the old instance.
637+
tcs.setResult(null);
638+
ParseTaskUtils.wait(Task.whenAll(tasks));
639+
}
640+
585641
// TODO test ParseGeoPoint and ParseFile after merge
586642

587643
//endregion

Parse/src/test/java/com/parse/ParseRelationTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
*/
99
package com.parse;
1010

11+
import android.os.Parcel;
12+
1113
import org.json.JSONArray;
1214
import org.json.JSONObject;
1315
import org.junit.Rule;
1416
import org.junit.Test;
1517
import org.junit.rules.ExpectedException;
18+
import org.junit.runner.RunWith;
19+
import org.robolectric.RobolectricTestRunner;
20+
import org.robolectric.annotation.Config;
1621
import org.skyscreamer.jsonassert.JSONCompareMode;
1722

1823
import static org.junit.Assert.assertEquals;
@@ -24,6 +29,8 @@
2429
import static org.mockito.Mockito.when;
2530
import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
2631

32+
@RunWith(RobolectricTestRunner.class)
33+
@Config(constants = BuildConfig.class, sdk = 23)
2734
public class ParseRelationTest {
2835

2936
@Rule
@@ -77,6 +84,36 @@ public void testConstructorWithJSONAndDecoder() throws Exception {
7784

7885
//endregion
7986

87+
//region testParcelable
88+
89+
@Test
90+
public void testParcelable() throws Exception {
91+
ParseFieldOperations.registerDefaultDecoders();
92+
ParseRelation<ParseObject> relation = new ParseRelation<>("Test");
93+
ParseObject parent = new ParseObject("Parent");
94+
parent.setObjectId("parentId");
95+
relation.ensureParentAndKey(parent, "key");
96+
ParseObject inner = new ParseObject("Test");
97+
inner.setObjectId("innerId");
98+
relation.add(inner);
99+
100+
Parcel parcel = Parcel.obtain();
101+
relation.writeToParcel(parcel, 0);
102+
parcel.setDataPosition(0);
103+
//noinspection unchecked
104+
ParseRelation<ParseObject> newRelation = ParseRelation.CREATOR.createFromParcel(parcel);
105+
assertEquals(newRelation.getTargetClass(), "Test");
106+
assertEquals(newRelation.getKey(), "key");
107+
assertEquals(newRelation.getParent().getClassName(), "Parent");
108+
assertEquals(newRelation.getParent().getObjectId(), "parentId");
109+
assertEquals(newRelation.getKnownObjects().size(), 1);
110+
111+
// This would fail assertTrue(newRelation.hasKnownObject(inner)).
112+
// That is because ParseRelation uses == to check for known objects.
113+
}
114+
115+
//endregion
116+
80117
//region testEnsureParentAndKey
81118

82119
@Test

0 commit comments

Comments
 (0)