Skip to content

Fix ParseUserCurrentCoder bug #724

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions Parse/src/main/java/com/parse/ParseUserCurrentCoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import static com.parse.ParseUser.State;
Expand Down Expand Up @@ -54,7 +55,11 @@ public static ParseUserCurrentCoder get() {
@Override
public <T extends ParseObject.State> JSONObject encode(
T state, ParseOperationSet operations, ParseEncoder encoder) {

// FYI we'll be double writing sessionToken and authData for now...
// This is important. super.encode() has no notion of sessionToken and authData, so it treats them
// like objects (simply passed to the encoder). This means that a null sessionToken will become
// JSONObject.NULL. This must be accounted in #decode().
JSONObject objectJSON = super.encode(state, operations, encoder);

String sessionToken = ((State) state).sessionToken();
Expand Down Expand Up @@ -90,17 +95,20 @@ public <T extends ParseObject.State> JSONObject encode(
@Override
public <T extends ParseObject.State.Init<?>> T decode(
T builder, JSONObject json, ParseDecoder decoder) {
ParseUser.State.Builder userBuilder = (State.Builder) builder;
ParseUser.State.Builder userBuilder = (State.Builder) super.decode(builder, json, decoder);

// super.decode will read its own values and add them to the builder using put().
// This means the state for session token and auth data might be illegal, returning
// unexpected types. For instance if sessionToken was null, now it's JSONObject.NULL.
// We must overwrite these possibly wrong values.
String newSessionToken = json.optString(KEY_SESSION_TOKEN, null);
if (newSessionToken != null) {
userBuilder.sessionToken(newSessionToken);
json.remove(KEY_SESSION_TOKEN);
}
userBuilder.sessionToken(newSessionToken);

JSONObject newAuthData = json.optJSONObject(KEY_AUTH_DATA);
if (newAuthData != null) {
if (newAuthData == null) {
userBuilder.authData(null);
} else {
try {
// Merge in auth data.
@SuppressWarnings("rawtypes")
Iterator i = newAuthData.keys();
while (i.hasNext()) {
Expand All @@ -113,10 +121,8 @@ public <T extends ParseObject.State.Init<?>> T decode(
} catch (JSONException e) {
throw new RuntimeException(e);
}
json.remove(KEY_AUTH_DATA);
}

// FYI we'll be double writing sessionToken and authData for now...
return super.decode(builder, json, decoder);
return (T) userBuilder;
}
}
10 changes: 3 additions & 7 deletions Parse/src/test/java/com/parse/ParseConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,14 @@
// For android.os.Looper
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = TestHelper.ROBOLECTRIC_SDK_VERSION)
public class ParseConfigTest {
public class ParseConfigTest extends ResetPluginsParseTest {

@Before
public void setUp() {
public void setUp() throws Exception {
super.setUp();
ParseTestUtils.setTestParseUser();
}

@After
public void tearDown() {
ParseCorePlugins.getInstance().reset();
}

//region testConstructor

@Test
Expand Down
15 changes: 13 additions & 2 deletions Parse/src/test/java/com/parse/ParseInstallationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import bolts.Task;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -253,8 +254,16 @@ public void testUpdateBeforeSave() throws Exception {
installation.updateBeforeSave();

// Make sure we update timezone
String zone = TimeZone.getDefault().getID();
assertEquals(zone, installation.getString(KEY_TIME_ZONE));
String zone = installation.getString(KEY_TIME_ZONE);
String deviceZone = TimeZone.getDefault().getID();
if (zone != null) {
assertEquals(zone, deviceZone);
} else {
// If it's not updated it's because it was not acceptable.
assertFalse(deviceZone.equals("GMT"));
assertFalse(deviceZone.indexOf("/") > 0);
}

// Make sure we update version info
Context context = Parse.getApplicationContext();
String packageName = context.getPackageName();
Expand All @@ -265,9 +274,11 @@ public void testUpdateBeforeSave() throws Exception {
assertEquals(packageName, installation.getString(KEY_APP_IDENTIFIER));
assertEquals(appName, installation.getString(KEY_APP_NAME));
assertEquals(appVersion, installation.getString(KEY_APP_VERSION));

// Make sure we update device info
assertEquals("android", installation.getString(KEY_DEVICE_TYPE));
assertEquals("installationId", installation.getString(KEY_INSTALLATION_ID));

// Make sure we update the locale identifier
assertEquals("en-US", installation.getString(KEY_LOCALE_IDENTIFIER));
}
Expand Down
18 changes: 15 additions & 3 deletions Parse/src/test/java/com/parse/ParseUserCurrentCoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,6 @@ public void testDecodeSuccessWithSessionTokenAndAuthData() throws Exception {
Map<String, String> twitterAuthData = authData.get("twitter");
assertEquals("twitterId", twitterAuthData.get("id"));
assertEquals("twitterAccessToken", twitterAuthData.get("access_token"));
// Make sure objectJson does not have sessionToken and authData anymore
assertFalse(objectJson.has(KEY_SESSION_TOKEN));
assertFalse(objectJson.has(KEY_AUTH_DATA));
}

@Test
Expand All @@ -111,4 +108,19 @@ public void testDecodeSuccessWithoutSessionTokenAndAuthData() throws Exception {
// We always return non-null for authData()
assertEquals(0, state.authData().size());
}

@Test
public void testEncodeDecodeWithNullValues() throws Exception {
ParseUser.State state = new ParseUser.State.Builder()
.sessionToken(null)
.authData(null)
.build();
ParseUserCurrentCoder coder = ParseUserCurrentCoder.get();
JSONObject object = coder.encode(state, null, PointerEncoder.get());
ParseUser.State.Builder builder =
coder.decode(new ParseUser.State.Builder(), object, ParseDecoder.get());
state = builder.build();
assertNull(state.sessionToken());
assertEquals(0, state.authData().size());
}
}