From 101c2ff8f2524f9b8124e580ead001f7e3556d85 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 1 Aug 2017 07:28:17 -0700 Subject: [PATCH] fix problems with params[] serialization Was passing through DlgState params a number of classes that weren't serializable or that didn't have equals() methods required for DEBUG assertions to pass. Added versions of equals() that just call super in non-DEBUG case since it's a lot of code and isn't required except for testing. (Serialization of course is.) --- .../org/eehouse/android/xw4/DlgState.java | 36 +++++----- .../android/xw4/GamesListDelegate.java | 19 +++--- .../eehouse/android/xw4/NetLaunchInfo.java | 65 ++++++++++++++++--- .../java/org/eehouse/android/xw4/Utils.java | 10 +++ .../eehouse/android/xw4/jni/CurGameInfo.java | 54 +++++++++++++-- .../eehouse/android/xw4/jni/GameSummary.java | 54 ++++++++++++++- .../eehouse/android/xw4/jni/LocalPlayer.java | 32 +++++++++ 7 files changed, 228 insertions(+), 42 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java index 165e78760..1cc94f926 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java @@ -73,21 +73,27 @@ public class DlgState implements Parcelable { public DlgState setTitle( int id ) { m_titleId = id; return this; } - // @Override - // public String toString() - // { - // String params = ""; - // if ( null != m_params ) { - // List strs = new ArrayList<>(); - // for (Object obj : m_params) { - // strs.add(String.format("%s", obj)); - // } - // params = TextUtils.join( ",", strs ); - // } - // return String.format("[msg: %s; key: %s; action: %s; pair %s: na: %s; pos: %d; neg: %d; title: %d; params: %s]", - // m_msg, m_prefsKey, m_action, m_pair, m_onNAChecked, - // m_posButton, m_negButton, m_titleId, params ); - // } + @Override + public String toString() + { + if ( BuildConfig.DEBUG) { + String params = ""; + if ( null != m_params ) { + List strs = new ArrayList<>(); + for (Object obj : m_params) { + strs.add(String.format("%s", obj)); + } + params = TextUtils.join( ",", strs ); + } + return String.format("[id: %s; msg: %s; key: %s; action: %s; pair %s; " + + "na: %s; pos: %d; neg: %d; title: %d; " + + "params: %s]", + m_id, m_msg, m_prefsKey, m_action, m_pair, m_onNAChecked, + m_posButton, m_negButton, m_titleId, params ); + } else { + return super.toString(); + } + } // I only need this if BuildConfig.DEBUG is true... @Override diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java index 80edd91cd..a31368173 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java @@ -862,7 +862,8 @@ public class GamesListDelegate extends ListDelegateBase lstnr = new OnClickListener() { public void onClick( DialogInterface dlg, int item ) { - curThis().makeThenLaunchOrConfigure( edit, true, false ); + String name = edit.getText().toString(); + curThis().makeThenLaunchOrConfigure( name, true, false ); } }; @@ -874,7 +875,8 @@ public class GamesListDelegate extends ListDelegateBase if ( canDoDefaults ) { lstnr2 = new OnClickListener() { public void onClick( DialogInterface dlg, int item ) { - curThis().makeThenLaunchOrConfigure( edit, false, false ); + String name = edit.getText().toString(); + curThis().makeThenLaunchOrConfigure( name, false, false ); } }; ab.setNegativeButton( R.string.use_defaults, lstnr2 ); @@ -2543,7 +2545,7 @@ public class GamesListDelegate extends ListDelegateBase // Returns true if user has what looks like a default name and has not // said he wants us to stop bugging him about it. - private boolean askingChangeName( EditText edit, boolean doConfigure ) + private boolean askingChangeName( String name, boolean doConfigure ) { boolean asking = false; boolean skipAsk = XWPrefs @@ -2563,7 +2565,7 @@ public class GamesListDelegate extends ListDelegateBase makeConfirmThenBuilder( msg, Action.NEW_GAME_DFLT_NAME ) .setOnNA( Action.SET_NA_DEFAULTNAME ) .setNegButton( R.string.button_later ) - .setParams( edit, doConfigure ) + .setParams( name, doConfigure ) .show(); } } @@ -2574,19 +2576,18 @@ public class GamesListDelegate extends ListDelegateBase { boolean handled = null != m_newGameParams; if ( handled ) { - EditText edit = (EditText)m_newGameParams[0]; + String name = (String)m_newGameParams[0]; boolean doConfigure = (Boolean)m_newGameParams[1]; m_newGameParams = null; - makeThenLaunchOrConfigure( edit, doConfigure, true ); + makeThenLaunchOrConfigure( name, doConfigure, true ); } return handled; } - private void makeThenLaunchOrConfigure( EditText edit, boolean doConfigure, + private void makeThenLaunchOrConfigure( String name, boolean doConfigure, boolean skipAsk ) { - if ( skipAsk || !askingChangeName( edit, doConfigure ) ) { - String name = edit.getText().toString(); + if ( skipAsk || !askingChangeName( name, doConfigure ) ) { long rowID; long groupID = 1 == m_mySIS.selGroupIDs.size() ? m_mySIS.selGroupIDs.iterator().next() : DBUtils.GROUPID_UNSPEC; diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java index ee2b29e41..7fffef51c 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java @@ -26,21 +26,23 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import junit.framework.Assert; +import java.io.InputStream; +import java.io.Serializable; +import java.util.Iterator; -import org.eehouse.android.xw4.jni.CommsAddrRec; -import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; -import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet; -import org.eehouse.android.xw4.jni.CurGameInfo; -import org.eehouse.android.xw4.jni.GameSummary; -import org.eehouse.android.xw4.loc.LocUtils; import org.json.JSONException; import org.json.JSONObject; -import java.io.InputStream; -import java.util.Iterator; +import junit.framework.Assert; -public class NetLaunchInfo { +import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; +import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet; +import org.eehouse.android.xw4.jni.CommsAddrRec; +import org.eehouse.android.xw4.jni.CurGameInfo; +import org.eehouse.android.xw4.jni.GameSummary; +import org.eehouse.android.xw4.loc.LocUtils; + +public class NetLaunchInfo implements Serializable { private static final String TAG = NetLaunchInfo.class.getSimpleName(); private static final String ADDRS_KEY = "ad"; private static final String PHONE_KEY = "phn"; @@ -108,6 +110,8 @@ public class NetLaunchInfo { p2pMacAddress = bundle.getString( MultiService.P2P_MAC_ADDRESS ); m_addrs = new CommsConnTypeSet( bundle.getInt( ADDRS_KEY ) ); + + Utils.testSerialization( this ); } public static NetLaunchInfo makeFrom( Bundle bundle ) @@ -317,6 +321,45 @@ public class NetLaunchInfo { bundle.putInt( ADDRS_KEY, flags ); } + @Override + public boolean equals( Object obj ) + { + NetLaunchInfo other = null; + boolean result = null != obj && obj instanceof NetLaunchInfo; + if ( result ) { + other = (NetLaunchInfo)obj; + result = ((null == gameName) ? (null == other.gameName) + : gameName.equals(other.gameName)) + && ((null == dict) ? (null == other.dict) + : dict.equals(other.dict)) + && lang == other.lang + && forceChannel == other.forceChannel + && nPlayersT == other.nPlayersT + && nPlayersH == other.nPlayersH + && ((null == room) ? (null == other.room) + : room.equals(other.room)) + && ((null == btName) ? (null == other.btName) + : btName.equals(other.btName)) + && ((null == btAddress) ? (null == other.btAddress) + : btAddress.equals(other.btAddress)) + && ((null == p2pMacAddress) ? (null == other.p2pMacAddress) + : p2pMacAddress.equals(other.p2pMacAddress)) + && ((null == phone) ? (null == other.phone) + : phone.equals(other.phone)) + && isGSM == other. isGSM + && osVers == other.osVers + && _conTypes == other._conTypes + && gameID == other.gameID + && ((null == m_addrs ? (null == other.m_addrs) + : m_addrs.equals(other.m_addrs))) + && m_valid == other.m_valid + && ((null == inviteID ? (null == other.inviteID) + : inviteID.equals(other.inviteID))) + ; + } + return result; + } + public String makeLaunchJSON() { String result = null; @@ -608,5 +651,7 @@ public class NetLaunchInfo { } } m_valid = valid; + + Utils.testSerialization( this ); } } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java index 943d294a3..b4d98e644 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/Utils.java @@ -533,6 +533,16 @@ public class Utils { return result; } + public static void testSerialization( Serializable obj ) + { + if ( BuildConfig.DEBUG ) { + String as64 = serializableToString64( obj ); + Object other = string64ToSerializable( as64 ); + Assert.assertTrue( other.equals( obj ) ); + Log.d( TAG, "testSerialization(%s) worked!!!", obj ); + } + } + private static void setFirstBootStatics( Context context ) { if ( null == s_isFirstBootThisVersion ) { diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CurGameInfo.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CurGameInfo.java index f4e91902b..2ca019ad4 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CurGameInfo.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CurGameInfo.java @@ -22,20 +22,21 @@ package org.eehouse.android.xw4.jni; import android.content.Context; +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; +import org.json.JSONObject; + import junit.framework.Assert; +import org.eehouse.android.xw4.BuildConfig; import org.eehouse.android.xw4.DictLangCache; import org.eehouse.android.xw4.DictUtils; import org.eehouse.android.xw4.Log; import org.eehouse.android.xw4.R; +import org.eehouse.android.xw4.Utils; import org.eehouse.android.xw4.loc.LocUtils; -import org.json.JSONObject; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Random; - -import java.io.Serializable; public class CurGameInfo implements Serializable { private static final String TAG = CurGameInfo.class.getSimpleName(); @@ -149,6 +150,8 @@ public class CurGameInfo implements Serializable { for ( ii = 0; ii < MAX_NUM_PLAYERS; ++ii ) { players[ii] = new LocalPlayer( src.players[ii] ); } + + Utils.testSerialization( this ); } public String getJSONData() @@ -270,6 +273,43 @@ public class CurGameInfo implements Serializable { return matter; } + @Override + public boolean equals( Object obj ) + { + boolean result; + if ( BuildConfig.DEBUG ) { + CurGameInfo other = null; + result = null != obj && obj instanceof CurGameInfo; + if ( result ) { + other = (CurGameInfo)obj; + result = dictLang == other.dictLang + && gameID == other.gameID + && gameSeconds == other.gameSeconds + && nPlayers == other.nPlayers + && boardSize == other.boardSize + && forceChannel == other.forceChannel + && hintsNotAllowed == other.hintsNotAllowed + && timerEnabled == other.timerEnabled + && allowPickTiles == other.allowPickTiles + && allowHintRect == other.allowHintRect + && m_smartness == other.m_smartness + && Arrays.deepEquals( players, other.players ) + && ((null == dictName) ? (null == other.dictName) + : dictName.equals(other.dictName)) + && ((null == serverRole) ? (null == other.serverRole) + : serverRole.equals(other.serverRole)) + && ((null == phoniesAction) ? (null == other.phoniesAction) + : phoniesAction.equals(other.phoniesAction)) + && ((null == m_name) ? (null == other.m_name) + : m_name.equals(other.m_name)) + ; + } + } else { + result = super.equals( obj ); + } + return result; + } + public int remoteCount() { int count = 0; diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java index ec4f2a243..38ac36b75 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java @@ -24,9 +24,13 @@ import android.content.Context; import android.text.TextUtils; import java.io.Serializable; +import java.util.Arrays; + +import org.json.JSONObject; import junit.framework.Assert; +import org.eehouse.android.xw4.BuildConfig; import org.eehouse.android.xw4.DBUtils; import org.eehouse.android.xw4.Log; import org.eehouse.android.xw4.R; @@ -36,7 +40,6 @@ import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet; import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole; import org.eehouse.android.xw4.loc.LocUtils; -import org.json.JSONObject; /** Info we want to access when the game's closed that's not available * in CurGameInfo @@ -98,6 +101,55 @@ public class GameSummary implements Serializable { return null != relayID; } + @Override + public boolean equals( Object obj ) + { + boolean result; + if ( BuildConfig.DEBUG ) { + result = null != obj && obj instanceof GameSummary; + if ( result ) { + GameSummary other = (GameSummary)obj; + result = lastMoveTime == other.lastMoveTime + && nMoves == other.nMoves + && turn == other.turn + && turnIsLocal == other.turnIsLocal + && nPlayers == other.nPlayers + && missingPlayers == other.missingPlayers + && gameOver == other.gameOver + && seed == other.seed + && modtime == other.modtime + && gameID == other.gameID + && dictLang == other.dictLang + && nPacketsPending == other.nPacketsPending + && ((null == scores) ? (null == other.scores) + : scores.equals(other.scores)) + && Arrays.deepEquals( m_players, other.m_players ) + && ((null == conTypes) ? (null == other.conTypes) + : conTypes.equals(other.conTypes)) + && ((null == roomName) ? (null == other.roomName) + : roomName.equals(other.roomName)) + && ((null == relayID) ? (null == other.relayID) + : relayID.equals(other.relayID)) + && Arrays.deepEquals( remoteDevs, other.remoteDevs ) + && ((null == serverRole) ? (null == other.serverRole) + : serverRole.equals(other.serverRole)) + && ((null == m_giFlags) ? (null == other.m_giFlags) + : m_giFlags.equals(other.m_giFlags)) + && ((null == m_playersSummary) ? (null == other.m_playersSummary) + : m_playersSummary.equals(other.m_playersSummary)) + && ((null == m_gi) ? (null == other.m_gi) + : m_gi.equals(other.m_gi)) + && Arrays.deepEquals( m_remotePhones, other.m_remotePhones ) + && ((null == m_extras) ? (null == other.m_extras) + : m_extras.equals(other.m_extras)) + ; + } + } else { + result = super.equals( obj ); + } + return result; + } + public String summarizePlayers() { String result; diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/LocalPlayer.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/LocalPlayer.java index 36188c753..e6d356148 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/LocalPlayer.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/LocalPlayer.java @@ -26,7 +26,9 @@ import java.io.Serializable; import junit.framework.Assert; +import org.eehouse.android.xw4.BuildConfig; import org.eehouse.android.xw4.R; +import org.eehouse.android.xw4.Utils; public class LocalPlayer implements Serializable { public String name; @@ -43,6 +45,8 @@ public class LocalPlayer implements Serializable { String fmt = context.getString( R.string.player_fmt); name = String.format( fmt, num + 1 ); password = ""; + + // Utils.testSerialization( this ); } public LocalPlayer( final LocalPlayer src ) @@ -53,6 +57,34 @@ public class LocalPlayer implements Serializable { password = src.password; dictName = src.dictName; secondsUsed = src.secondsUsed; + + // Utils.testSerialization( this ); + } + + @Override + public boolean equals( Object obj ) + { + boolean result; + if ( BuildConfig.DEBUG ) { + LocalPlayer other = null; + result = null != obj && obj instanceof LocalPlayer; + if ( result ) { + other = (LocalPlayer)obj; + result = secondsUsed == other.secondsUsed + && robotIQ == other.robotIQ + && isLocal == other.isLocal + && ((null == name) ? (null == other.name) + : name.equals(other.name)) + && ((null == password) ? (null == other.password) + : password.equals(other.password)) + && ((null == dictName) ? (null == other.dictName) + : dictName.equals(other.dictName)) + ; + } + } else { + result = super.equals( obj ); + } + return result; } public boolean isRobot()