Skip to content

Commit

Permalink
Remove unused code and fix format
Browse files Browse the repository at this point in the history
  • Loading branch information
jinliu9508 committed Feb 6, 2024
1 parent fbe9f74 commit 3d34cf0
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 214 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import android.widget.TextView;
import com.onesignal.Continue;
import com.onesignal.OneSignal;
import com.onesignal.core.internal.config.ConfigModelStore;
import com.onesignal.sdktest.adapter.SubscriptionRecyclerViewAdapter;
import com.onesignal.user.subscriptions.IPushSubscription;
import com.onesignal.sdktest.R;
Expand Down Expand Up @@ -274,11 +273,6 @@ public ActivityViewModel onActivityCreated(Context context) {
getActivity().startActivity(new Intent(getActivity(), SecondaryActivity.class));
});

Button createDeadlock = getActivity().findViewById(R.id.main_activity_deadlock_button);
createDeadlock.setOnClickListener(v -> {
createDeadlock();
});

aliasSet = new HashMap<>();
aliasArrayList = new ArrayList<>();

Expand Down Expand Up @@ -937,44 +931,4 @@ private void refreshState() {
// triggers are not persisted, they are always "starting from scratch"
refreshTriggerRecyclerView();
}

private void createDeadlock() {

// register test observers
IPushSubscriptionObserver observer = state -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
OneSignal.getUser().getPushSubscription().optIn();
System.out.println("JinTest optedout");
};
OneSignal.getUser().getPushSubscription().addObserver(observer);

// calling login will call setOptAnyProperty, which locks model.data
// then, any observer added will be fired, which will lock subscribers
Thread t1 = new Thread() {
@Override
public void run() {
OneSignal.getUser().getPushSubscription().optOut();
OneSignal.getUser().getPushSubscription().optIn();
System.out.println("JinTest optedin");
}
};

Thread t2 = new Thread() {
@Override
public void run() {
OneSignal.logout();
OneSignal.login("testJin");
System.out.println("JinTest login");
}
};

t1.start();
t2.start();


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@
android:orientation="vertical">

<!-- Application -->

<LinearLayout
android:id="@+id/main_activity_account_linear_layout"
android:layout_width="match_parent"
Expand Down Expand Up @@ -1269,30 +1268,6 @@
android:visibility="visible"/>

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginStart="12dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:orientation="vertical">

<Button
android:id="@+id/main_activity_deadlock_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ripple_selector_white_red"
android:text="@string/create_deadlock"
android:textColor="@android:color/white"
android:textSize="19sp"
android:visibility="visible" />

</LinearLayout>
</LinearLayout>

</androidx.core.widget.NestedScrollView>
Expand Down
1 change: 0 additions & 1 deletion Examples/OneSignalDemo/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
<string name="revoke_consent">Revoke Consent</string>

<string name="navigate_next_activity">Next activity</string>
<string name="create_deadlock">Create deadlock</string>

<string name="onesignal_app_id">0ba9731b-33bd-43f4-8b59-61172e27447d</string>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ open class Model(
* specified, must also specify [_parentModel]
*/
private val _parentProperty: String? = null,
private val initializationLock: Any = Any(),
) : IEventNotifier<IModelChangedHandler> {
/**
* A unique identifier for this model.
Expand Down Expand Up @@ -95,35 +94,26 @@ open class Model(
data[property] = listOfItems
}
} else {
val method = this.javaClass.methods.firstOrNull {
it.returnType != Void::class.java && it.name.contains(
property,
true
)
}
val method =
this.javaClass.methods.firstOrNull {
it.returnType !=
Void::class.java &&
it.name.contains(
property,
true,
)
}

if (method == null) {
data[property] = jsonObject.get(property)
} else {
when (method.returnType) {
Double::class.java, java.lang.Double::class.java -> data[property] =
jsonObject.getDouble(property)

Long::class.java, java.lang.Long::class.java -> data[property] =
jsonObject.getLong(property)

Float::class.java, java.lang.Float::class.java -> data[property] =
jsonObject.getDouble(property).toFloat()

Int::class.java, java.lang.Integer::class.java -> data[property] =
jsonObject.getInt(property)

Boolean::class.java, java.lang.Boolean::class.java -> data[property] =
jsonObject.getBoolean(property)

String::class.java, java.lang.String::class.java -> data[property] =
jsonObject.getString(property)

Double::class.java, java.lang.Double::class.java -> data[property] = jsonObject.getDouble(property)
Long::class.java, java.lang.Long::class.java -> data[property] = jsonObject.getLong(property)
Float::class.java, java.lang.Float::class.java -> data[property] = jsonObject.getDouble(property).toFloat()
Int::class.java, java.lang.Integer::class.java -> data[property] = jsonObject.getInt(property)
Boolean::class.java, java.lang.Boolean::class.java -> data[property] = jsonObject.getBoolean(property)
String::class.java, java.lang.String::class.java -> data[property] = jsonObject.getString(property)
else -> data[property] = jsonObject.get(property)
}
}
Expand Down Expand Up @@ -159,11 +149,9 @@ open class Model(
newData[::id.name] = id
}

synchronized(initializationLock) {
synchronized(data) {
data.clear()
data.putAll(newData)
}
synchronized(data) {
data.clear()
data.putAll(newData)
}
}

Expand Down Expand Up @@ -690,42 +678,38 @@ open class Model(
* @return The resulting [JSONObject].
*/
fun toJSON(): JSONObject {
synchronized(initializationLock) {
val jsonObject = JSONObject()
synchronized(data) {
for (kvp in data) {
when (val value = kvp.value) {
is Model -> {
jsonObject.put(kvp.key, value.toJSON())
}
val jsonObject = JSONObject()
synchronized(data) {
for (kvp in data) {
when (val value = kvp.value) {
is Model -> {
jsonObject.put(kvp.key, value.toJSON())
}

is List<*> -> {
val jsonArray = JSONArray()
for (arrayItem in value) {
if (arrayItem is Model) {
jsonArray.put(arrayItem.toJSON())
} else {
jsonArray.put(arrayItem)
}
is List<*> -> {
val jsonArray = JSONArray()
for (arrayItem in value) {
if (arrayItem is Model) {
jsonArray.put(arrayItem.toJSON())
} else {
jsonArray.put(arrayItem)
}
jsonObject.put(kvp.key, jsonArray)
}
jsonObject.put(kvp.key, jsonArray)
}

else -> {
jsonObject.put(kvp.key, value)
}
else -> {
jsonObject.put(kvp.key, value)
}
}
}
return jsonObject
}
return jsonObject
}

override fun subscribe(handler: IModelChangedHandler) = changeNotifier.subscribe(handler)

override fun unsubscribe(handler: IModelChangedHandler) {
changeNotifier.unsubscribe(handler)
}
override fun unsubscribe(handler: IModelChangedHandler) = changeNotifier.unsubscribe(handler)

override val hasSubscribers: Boolean
get() = changeNotifier.hasSubscribers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ abstract class ModelStore<TModel>(
model.subscribe(this)

persist()

}
changeSubscription.fire { it.onModelAdded(model, tag) }
}

Expand All @@ -142,7 +142,7 @@ abstract class ModelStore<TModel>(
model.unsubscribe(this)

persist()

}
changeSubscription.fire { it.onModelRemoved(model, tag) }
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.onesignal.common

import com.onesignal.common.events.EventProducer
import com.onesignal.common.modeling.IModelChangedHandler
import com.onesignal.common.modeling.IModelStoreChangeHandler
import com.onesignal.common.modeling.ModelChangedArgs
import com.onesignal.mocks.MockHelper
import com.onesignal.mocks.MockPreferencesService
import com.onesignal.user.internal.subscriptions.SubscriptionModel
import com.onesignal.user.internal.subscriptions.SubscriptionModelStore
import io.kotest.core.spec.style.FunSpec
import io.kotest.runner.junit4.KotestTestRunner
import junit.framework.TestCase
import org.junit.runner.RunWith

@RunWith(KotestTestRunner::class)
class ModelingTests : FunSpec({

test("Deadlock related to Model.setOptAnyProperty") {
// Given
val modelStore = MockHelper.configModelStore()
val model = modelStore.model

val t1 =
Thread {
// acquire "model.data", then trigger the onChanged event
model.setOptAnyProperty("key1", "value1")
}

val t2 =
Thread {
// acquire "model.initializationLock", then wait for "model.data" to be released
model.initializeFromModel("", MockHelper.configModelStore().model)
}

model.subscribe(
object : IModelChangedHandler {
// will be executed in t1
override fun onChanged(
args: ModelChangedArgs,
tag: String,
) {
Thread.sleep(200)
// waiting for "model.initializationLock"
model.toJSON()
}
},
)

t1.start()
t2.start()

// Set 1s timeout for t2 to complete the task
t2.join(1000)

// verify if the thread has been successfully terminated
TestCase.assertEquals(Thread.State.TERMINATED, t2.state)
}

test("Deadlock related to ModelSstore add() or remove()") {
// Given
val modelStore = SubscriptionModelStore(MockPreferencesService())
val event = EventProducer<SubscriptionModel>()
val oldSubscriptionModel = SubscriptionModel()
val newSubscriptionModel = SubscriptionModel()
oldSubscriptionModel.id = "oldModel"
newSubscriptionModel.id = "newModel"
modelStore.add(oldSubscriptionModel)

val t1 =
Thread {
// acquire "ModelStore.models", then trigger the onChanged event
System.out.println("1")
modelStore.add(newSubscriptionModel)
}

val t2 =
Thread {
System.out.println("2")
// acquire "model.data", then wait for "ModelStore.models"
newSubscriptionModel.toJSON()
}

modelStore.subscribe(
object : IModelStoreChangeHandler<SubscriptionModel> {
override fun onModelAdded(
model: SubscriptionModel,
tag: String,
) {
// waiting for "model.data"
model.initializeFromModel("", MockHelper.configModelStore().model)
}

override fun onModelUpdated(
args: ModelChangedArgs,
tag: String,
) {
// left empty in purpose
}

override fun onModelRemoved(
model: SubscriptionModel,
tag: String,
) {
// left empty in purpose
}
},
)

t1.start()
t2.start()

// Set 1s timeout for t2 to complete the task
t2.join(1000)

// verify if the thread has been successfully terminated
TestCase.assertEquals(Thread.State.TERMINATED, t2.state)
}
})
Loading

0 comments on commit 3d34cf0

Please sign in to comment.