From d7a513ad86e2b2503b615d41ba886790f1399865 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Thu, 21 Mar 2024 12:03:23 +0300 Subject: [PATCH 1/8] feat: set id --- .../sdk/java/internal/ModuleDeviceIdCore.java | 32 +++ .../java/internal/ModuleDeviceIdTests.java | 193 +++++++++++++++--- 2 files changed, 201 insertions(+), 24 deletions(-) diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java index 7e39ecfe..37cdfb6c 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java @@ -195,6 +195,27 @@ protected Config.DID acquireId() { return did; } + private void setIDInternal(String newDeviceID) { + if (Utils.isEmptyOrNull(newDeviceID)) { + L.w("[ModuleDeviceIdCore] setID, Empty id passed to setID method"); + return; + } + + if (getIDInternal().equals(newDeviceID)) { + L.w("[ModuleDeviceIdCore] setID, Same id passed to setID method, ignoring"); + return; + } + + // if current type is DEVELOPER_SUPPLIED + // an ID was provided by the host app previously + // we can assume that a device ID change with merge was executed previously + // now we change it without merging + // else + // SDK generated ID + // we change device ID with merge so that data is combined + changeDeviceIdInternal(newDeviceID, DeviceIdType.DEVELOPER_SUPPLIED, !getTypeInternal().equals(DeviceIdType.DEVELOPER_SUPPLIED)); + } + @Override public void stop(InternalConfig config, boolean clear) { if (tasks != null) { @@ -225,6 +246,17 @@ public String getID() { } } + /** + * Sets current device id to the new one. + * + * @param newDeviceID device id to set + */ + public void setID(String newDeviceID) { + synchronized (Countly.instance()) { + setIDInternal(newDeviceID); + } + } + /** * Returns current device id type. * diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java index a0882287..33efe023 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java @@ -4,6 +4,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import ly.count.sdk.java.Config; import ly.count.sdk.java.Countly; @@ -59,7 +60,7 @@ public void customDeviceId() { @Test public void changeWithMerge() { TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.DEVICE_ID); - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, false, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, no(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id setupView_Event_Session(); Assert.assertEquals(1, TestUtils.getCurrentRQ().length); // began session request @@ -96,7 +97,7 @@ public void changeWithoutMerge() throws InterruptedException { //why atomic string? Because changing it should also trigger dummy module callback asserts. //so it should be modifiable from outside TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.keysValues[0]); - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, true, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, yes(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(TestUtils.DEVICE_ID)); //custom id given setupView_Event_Session(); // setup view, event and session to simulate a device id change validateBeganSessionRequest(); // also validates rq size is 1 @@ -129,7 +130,7 @@ public void changeWithoutMerge_sameDeviceId() { //why atomic string? Because changing it should also trigger dummy module callback asserts. //so it should be modifiable from outside TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.keysValues[0]); - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, true, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, yes(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); //let sdk generate setupView_Event_Session(); // setup view, event and session to simulate a device id change validateBeganSessionRequest(); // also validates rq size is 1 @@ -153,7 +154,7 @@ public void changeWithoutMerge_nullDeviceId() { //why atomic string? Because changing it should also trigger dummy module callback asserts. //so it should be modifiable from outside TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.keysValues[0]); - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, true, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, yes(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); //let sdk generate setupView_Event_Session(); // setup view, event and session to simulate a device id change validateBeganSessionRequest(); // also validates rq size is 1 @@ -177,7 +178,7 @@ public void changeWithoutMerge_emptyDeviceId() { //why atomic string? Because changing it should also trigger dummy module callback asserts. //so it should be modifiable from outside TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.keysValues[0]); - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, true, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, yes(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); //let sdk generate setupView_Event_Session(); // setup view, event and session to simulate a device id change validateBeganSessionRequest(); // also validates rq size is 1 @@ -198,7 +199,7 @@ public void changeWithoutMerge_emptyDeviceId() { */ @Test public void changeWithMerge_nullDeviceId() { - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(null, false, DeviceIdType.SDK_GENERATED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(null, no(), DeviceIdType.SDK_GENERATED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id setupView_Event_Session(); @@ -220,7 +221,7 @@ public void changeWithMerge_nullDeviceId() { */ @Test public void changeWithMerge_emptyDeviceId() { - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(""), false, DeviceIdType.SDK_GENERATED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(""), no(), DeviceIdType.SDK_GENERATED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id setupView_Event_Session(); @@ -243,7 +244,7 @@ public void changeWithMerge_emptyDeviceId() { */ @Test public void changeWithMerge_sameDeviceId() throws InterruptedException { - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), false, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), no(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id setupView_Event_Session(); Thread.sleep(200); // wait for session request to written to the disk @@ -273,7 +274,7 @@ public void changeWithMerge_sameDeviceId() throws InterruptedException { */ @Test public void changeWithMerge_sessionNotStarted() { - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), false, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), no(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id setupEvent(); @@ -296,7 +297,7 @@ public void changeWithMerge_sessionNotStarted() { */ @Test public void changeWithoutMerge_sessionNotStarted() { - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), true, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), yes(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id validateDeviceIdIsSdkGenerated(); @@ -314,7 +315,7 @@ public void changeWithoutMerge_sessionNotStarted() { */ @Test public void changeWithoutMerge_sessionNotStarted_withEvents() throws InterruptedException { - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), true, DeviceIdType.DEVELOPER_SUPPLIED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(new TestUtils.AtomicString(TestUtils.DEVICE_ID), yes(), DeviceIdType.DEVELOPER_SUPPLIED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id setupEvent(); // two events created one is timed event it is started, the other is casual event String oldDeviceId = Countly.instance().deviceId().getID(); @@ -360,7 +361,7 @@ public void getID_getType_customDeviceId() { */ @Test public void logout_sdkGenerated() throws InterruptedException { - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(null, true, DeviceIdType.SDK_GENERATED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(null, yes(), DeviceIdType.SDK_GENERATED); Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id setupView_Event_Session(); @@ -382,7 +383,7 @@ public void logout_sdkGenerated() throws InterruptedException { @Test public void logout_developerSupplied() { TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.DEVICE_ID); - AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, true, DeviceIdType.SDK_GENERATED); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, yes(), DeviceIdType.SDK_GENERATED); Countly.instance().init(TestUtils.getConfigDeviceId(TestUtils.DEVICE_ID)); // to create sdk generated device id setupView_Event_Session(); @@ -422,6 +423,136 @@ public void acquireId_customId() { Assert.assertEquals(TestUtils.DEVICE_ID, did.id); } + @Test + public void setID() { + Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided + validateDeviceIdIsSdkGenerated(); // validate id exist and sdk generated + + String newId = TestUtils.keysValues[0]; + Countly.instance().deviceId().setID(newId); + validateDeviceIdDeveloperSupplied(newId); + } + + @Test + public void setID_null() { + Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided + validateDeviceIdIsSdkGenerated(); // validate id exist and sdk generated + + Countly.instance().deviceId().setID(null); + validateDeviceIdIsSdkGenerated(); + } + + @Test + public void setID_empty() { + Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided + validateDeviceIdIsSdkGenerated(); // validate id exist and sdk generated + + Countly.instance().deviceId().setID(""); + validateDeviceIdIsSdkGenerated(); + } + + @Test + public void setID_same() { + Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided + validateDeviceIdIsSdkGenerated(); // validate id exist and sdk generated + + Countly.instance().deviceId().setID(Countly.instance().deviceId().getID()); + validateDeviceIdIsSdkGenerated(); + } + + @Test + public void setID_sameCustom() { + Countly.instance().init(TestUtils.getBaseConfig(TestUtils.DEVICE_ID)); // custom id provided + validateDeviceIdDeveloperSupplied(TestUtils.DEVICE_ID); // validate id exist and developer supplied + + Countly.instance().deviceId().setID(TestUtils.DEVICE_ID); + validateDeviceIdDeveloperSupplied(TestUtils.DEVICE_ID); + } + + @Test + public void setID_custom() { + Countly.instance().init(TestUtils.getBaseConfig(TestUtils.DEVICE_ID)); // custom id provided + validateDeviceIdDeveloperSupplied(TestUtils.DEVICE_ID); // validate id exist and developer supplied + + String newId = TestUtils.keysValues[0]; + Countly.instance().deviceId().setID(newId); + validateDeviceIdDeveloperSupplied(newId); + } + + /** + * "changeWithoutMerge" with custom device id + * Validating that new id set and callback is called, and existing events,timed events and session must end, new session must begin + * request order should be first began session, 1 events, 1 end session, second began session, second end session, third began session + */ + @Test + public void setID_changeWithoutMerge() throws InterruptedException { + //why atomic string? Because changing it should also trigger dummy module callback asserts. + //so it should be modifiable from outside + TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.keysValues[0]); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, yes(), DeviceIdType.DEVELOPER_SUPPLIED); + Countly.instance().init(TestUtils.getConfigDeviceId(TestUtils.DEVICE_ID)); //custom id given + setupView_Event_Session(); // setup view, event and session to simulate a device id change + validateBeganSessionRequest(); // also validates rq size is 1 + + validateDeviceIdDeveloperSupplied(TestUtils.DEVICE_ID); + Assert.assertEquals(0, callCount.get()); + + Thread.sleep(1000); // waiting for timed event duration + Assert.assertEquals(2, TestUtils.getCurrentEQ().size()); // size should be 2 one view and a casual event + Countly.instance().deviceId().setID(deviceID.value); + Assert.assertEquals(0, TestUtils.getCurrentEQ().size()); // size should be zero because queue is flushed + Assert.assertEquals(1, callCount.get()); + validateDeviceIdWithoutMergeChange(4, TestUtils.DEVICE_ID); // there should be 2 began, 1 end, 1 events request + TestUtils.flushCurrentRQWithOldDeviceId(TestUtils.DEVICE_ID); // clean current rq with old device id requests + + deviceID.value += "1"; //change device id + Countly.instance().deviceId().setID(deviceID.value); + Assert.assertEquals(2, callCount.get()); + //if device id is not merged, then device id change request should not exist + validateDeviceIdWithoutMergeChange(3, TestUtils.keysValues[0]); // additional 1 session end 1 session begin, no events because no events exist + } + + /** + * "changeWithMerge" + * Validating that only one began session request is created and two device id change request for two + * "changeWithMerge" calls with different ids + * SDK must generate an id first, then should change with developer supplied two times + */ + @Test + public void setID_changeWithMerge_then_withoutMerge() throws InterruptedException { + TestUtils.AtomicString deviceID = new TestUtils.AtomicString(TestUtils.DEVICE_ID); + AtomicBoolean withMerge = new AtomicBoolean(false); + AtomicInteger callCount = initDummyModuleForDeviceIdChangedCallback(deviceID, withMerge, DeviceIdType.DEVELOPER_SUPPLIED); + Countly.instance().init(TestUtils.getConfigDeviceId(null)); // to create sdk generated device id + setupView_Event_Session(); + Assert.assertEquals(1, TestUtils.getCurrentRQ().length); // began session request + // validate began session request with generated id + validateBeganSessionRequest(); + validateDeviceIdIsSdkGenerated(); // validate device id generated by the sdk + + String oldDeviceId = Countly.instance().deviceId().getID(); + Assert.assertEquals(0, callCount.get()); // validate "deviceIdChanged" callback not called + + Assert.assertEquals(2, TestUtils.getCurrentEQ().size()); // size should not change because it is merge request + Countly.instance().deviceId().setID(deviceID.value); // TestUtils.DEVICE_ID + Assert.assertEquals(2, TestUtils.getCurrentEQ().size()); // size should not change because it is merge request + + Assert.assertEquals(1, callCount.get()); + validateDeviceIdWithMergeChange(oldDeviceId, 1, 2); + TestUtils.flushCurrentRQWithOldDeviceId(oldDeviceId); // clean current rq with old device id requests + + deviceID.value += "1"; + withMerge.set(true); // set atomic boolean to true to validate without merge + Thread.sleep(1000); // waiting for timed event duration + + Assert.assertEquals(2, TestUtils.getCurrentEQ().size()); // size should not change because it is merge request + Countly.instance().deviceId().setID(deviceID.value); // TestUtils.DEVICE_ID + "1" + Assert.assertEquals(0, TestUtils.getCurrentEQ().size()); // size should change because it is not a merge request + + Assert.assertEquals(2, callCount.get()); + validateDeviceIdWithoutMergeChange(3, TestUtils.DEVICE_ID, false); // there should be 1 began, 1 events request + } + /** * validates that requests in RQ are valid for without merge request * It validates the requests after a without merge device id change @@ -438,20 +569,22 @@ public void acquireId_customId() { * @param rqSize expected RQ size * @param oldDeviceId to validate device id in requests before device id change */ - private void validateDeviceIdWithoutMergeChange(final int rqSize, String oldDeviceId) { + private void validateDeviceIdWithoutMergeChange(final int rqSize, String oldDeviceId, boolean checkFirstReq) { Map[] requests = TestUtils.getCurrentRQ(); Assert.assertEquals(rqSize, TestUtils.getCurrentRQ().length); - - // validate first begin session request - TestUtils.validateRequiredParams(requests[0], oldDeviceId); // first request must be began session request - TestUtils.validateMetrics(requests[0].get("metrics")); // validate metrics exist in the first session request - Assert.assertEquals("1", requests[0].get("begin_session")); // validate begin session value is 1 - - int remainingRequestIndex = 1; // if there is no event request, then this will be 1 to continue checking + int remainingRequestIndex = 0; // if there is no begin session request, then this will be 0 to continue checking + + if (checkFirstReq) { + remainingRequestIndex = 1; // if no event request exists, then this will be 1 to continue checking + // validate first begin session request + TestUtils.validateRequiredParams(requests[0], oldDeviceId); // first request must be began session request + TestUtils.validateMetrics(requests[0].get("metrics")); // validate metrics exist in the first session request + Assert.assertEquals("1", requests[0].get("begin_session")); // validate begin session value is 1 + } // validate event request if exists try { - List existingEvents = validateEvents(1, oldDeviceId, 2); + List existingEvents = validateEvents(remainingRequestIndex, oldDeviceId, 2); if (!existingEvents.isEmpty()) { Map viewSegmentation = new ConcurrentHashMap<>(); viewSegmentation.put("segment", Device.dev.getOS()); @@ -478,6 +611,10 @@ private void validateDeviceIdWithoutMergeChange(final int rqSize, String oldDevi Assert.assertEquals("1", requests[remainingRequestIndex].get("begin_session")); // validate begin session value is 1 } + private void validateDeviceIdWithoutMergeChange(final int rqSize, String oldDeviceId) { + validateDeviceIdWithoutMergeChange(rqSize, oldDeviceId, true); + } + /** * Validates that the device id change request is valid * @@ -501,14 +638,14 @@ private void validateDeviceIdWithMergeChange(String oldDeviceId, final int rqIdx * @param type to validate by types * @return call count of the callback */ - private AtomicInteger initDummyModuleForDeviceIdChangedCallback(TestUtils.AtomicString deviceId, boolean withoutMerge, DeviceIdType type) { + private AtomicInteger initDummyModuleForDeviceIdChangedCallback(TestUtils.AtomicString deviceId, AtomicBoolean withoutMerge, DeviceIdType type) { AtomicInteger callCount = new AtomicInteger(0); SDKCore.testDummyModule = new ModuleBase() { @Override protected void deviceIdChanged(String oldDeviceId, boolean withMerge) { super.deviceIdChanged(oldDeviceId, withMerge); callCount.incrementAndGet(); - Assert.assertEquals(!withoutMerge, withMerge); + Assert.assertEquals(!withoutMerge.get(), withMerge); if (type == DeviceIdType.SDK_GENERATED) { validateDeviceIdIsSdkGenerated(); } else { @@ -601,4 +738,12 @@ private List validateEvents(int requestIndex, String deviceId, int ti return existingEvents; } + + private AtomicBoolean yes() { + return new AtomicBoolean(true); + } + + private AtomicBoolean no() { + return new AtomicBoolean(false); + } } From 85606553bb4f6a020c0202106369ba19ca640f05 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Thu, 21 Mar 2024 12:07:11 +0300 Subject: [PATCH 2/8] feat: changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bd4f5c3..d670e916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## XX.XX.XX +* Added a new function "setID(newDeviceId)" for managing device id changes. + ## 24.1.0 * !! Major breaking change !! The following method and its functionality is deprecated from the "UserEditor" interface and will not function anymore: From bdc468ea8a6be0d227d89fe25fe5859084678ab0 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Thu, 21 Mar 2024 14:03:57 +0300 Subject: [PATCH 3/8] doc: comments --- .../ly/count/sdk/java/internal/ModuleDeviceIdTests.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java index 33efe023..0f2eb769 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java @@ -480,7 +480,7 @@ public void setID_custom() { } /** - * "changeWithoutMerge" with custom device id + * "setID" with double without merge * Validating that new id set and callback is called, and existing events,timed events and session must end, new session must begin * request order should be first began session, 1 events, 1 end session, second began session, second end session, third began session */ @@ -513,9 +513,8 @@ public void setID_changeWithoutMerge() throws InterruptedException { } /** - * "changeWithMerge" - * Validating that only one began session request is created and two device id change request for two - * "changeWithMerge" calls with different ids + * "setID" first sdk generated then developer supplied + * Validating that first call acts like "changeWithMerge" and second call acts like "changeWithoutMerge" * SDK must generate an id first, then should change with developer supplied two times */ @Test From ab6235e5aa8635c23b0547321d075cd34f09e73d Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Fri, 22 Mar 2024 14:48:02 +0300 Subject: [PATCH 4/8] refactor: spread out --- .../sdk/java/internal/ModuleDeviceIdCore.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java index 37cdfb6c..2474f7c5 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java @@ -206,14 +206,16 @@ private void setIDInternal(String newDeviceID) { return; } - // if current type is DEVELOPER_SUPPLIED - // an ID was provided by the host app previously - // we can assume that a device ID change with merge was executed previously - // now we change it without merging - // else - // SDK generated ID - // we change device ID with merge so that data is combined - changeDeviceIdInternal(newDeviceID, DeviceIdType.DEVELOPER_SUPPLIED, !getTypeInternal().equals(DeviceIdType.DEVELOPER_SUPPLIED)); + if (getTypeInternal().equals(DeviceIdType.DEVELOPER_SUPPLIED)) { + // an ID was provided by the host app previously + // we can assume that a device ID change with merge was executed previously + // now we change it without merging + changeDeviceIdInternal(newDeviceID, DeviceIdType.DEVELOPER_SUPPLIED, false); + } else { + // SDK generated ID + // we change device ID with merge so that data is combined + changeDeviceIdInternal(newDeviceID, DeviceIdType.DEVELOPER_SUPPLIED, true); + } } @Override From e9904f499d6e12d9d5d4ced914ec6799b53b8ca3 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Mon, 25 Mar 2024 14:06:10 +0300 Subject: [PATCH 5/8] feat: pr changes --- CHANGELOG.md | 3 ++- .../java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d670e916..7a269cee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## XX.XX.XX -* Added a new function "setID(newDeviceId)" for managing device id changes. + +* Added a new function "setID(newDeviceId)" for managing device id changes according to the device ID Type. ## 24.1.0 diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java index 2474f7c5..e77f93c5 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleDeviceIdCore.java @@ -249,7 +249,8 @@ public String getID() { } /** - * Sets current device id to the new one. + * Sets device ID according to the device ID Type. + * If previous ID was Developer Supplied sets it without merge, otherwise with merge. * * @param newDeviceID device id to set */ From 41f19d281c58760bd2fdf92e840668f02be9bd04 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Mon, 25 Mar 2024 14:13:17 +0300 Subject: [PATCH 6/8] feat: combine tests --- .../java/internal/ModuleDeviceIdTests.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java index 0f2eb769..c8939d40 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java @@ -423,6 +423,14 @@ public void acquireId_customId() { Assert.assertEquals(TestUtils.DEVICE_ID, did.id); } + /** + * "setID" + * - Validate that device id is generated by the sdk + * - Set a new id and validate that it is set + * - Set null and validate that it is not changed + * - Set empty and validate that it is not changed + * - Set the same id and validate that it is not changed + */ @Test public void setID() { Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided @@ -431,35 +439,22 @@ public void setID() { String newId = TestUtils.keysValues[0]; Countly.instance().deviceId().setID(newId); validateDeviceIdDeveloperSupplied(newId); - } - - @Test - public void setID_null() { - Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided - validateDeviceIdIsSdkGenerated(); // validate id exist and sdk generated Countly.instance().deviceId().setID(null); - validateDeviceIdIsSdkGenerated(); - } - - @Test - public void setID_empty() { - Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided - validateDeviceIdIsSdkGenerated(); // validate id exist and sdk generated + validateDeviceIdDeveloperSupplied(newId); Countly.instance().deviceId().setID(""); - validateDeviceIdIsSdkGenerated(); - } - - @Test - public void setID_same() { - Countly.instance().init(TestUtils.getBaseConfig(null)); // no custom id provided - validateDeviceIdIsSdkGenerated(); // validate id exist and sdk generated + validateDeviceIdDeveloperSupplied(newId); Countly.instance().deviceId().setID(Countly.instance().deviceId().getID()); - validateDeviceIdIsSdkGenerated(); + validateDeviceIdDeveloperSupplied(newId); } + /** + * "setID" with custom device id + * - validate that device id is developer supplied + * - set same id and validate that it is not set + */ @Test public void setID_sameCustom() { Countly.instance().init(TestUtils.getBaseConfig(TestUtils.DEVICE_ID)); // custom id provided @@ -469,6 +464,11 @@ public void setID_sameCustom() { validateDeviceIdDeveloperSupplied(TestUtils.DEVICE_ID); } + /** + * "setID" with custom device id + * - validate that device id is developer supplied + * - set new id and validate that it is set + */ @Test public void setID_custom() { Countly.instance().init(TestUtils.getBaseConfig(TestUtils.DEVICE_ID)); // custom id provided @@ -533,7 +533,7 @@ public void setID_changeWithMerge_then_withoutMerge() throws InterruptedExceptio Assert.assertEquals(0, callCount.get()); // validate "deviceIdChanged" callback not called Assert.assertEquals(2, TestUtils.getCurrentEQ().size()); // size should not change because it is merge request - Countly.instance().deviceId().setID(deviceID.value); // TestUtils.DEVICE_ID + Countly.instance().deviceId().setID(TestUtils.DEVICE_ID); // TestUtils.DEVICE_ID Assert.assertEquals(2, TestUtils.getCurrentEQ().size()); // size should not change because it is merge request Assert.assertEquals(1, callCount.get()); @@ -545,7 +545,7 @@ public void setID_changeWithMerge_then_withoutMerge() throws InterruptedExceptio Thread.sleep(1000); // waiting for timed event duration Assert.assertEquals(2, TestUtils.getCurrentEQ().size()); // size should not change because it is merge request - Countly.instance().deviceId().setID(deviceID.value); // TestUtils.DEVICE_ID + "1" + Countly.instance().deviceId().setID(TestUtils.DEVICE_ID + "1"); // TestUtils.DEVICE_ID + "1" Assert.assertEquals(0, TestUtils.getCurrentEQ().size()); // size should change because it is not a merge request Assert.assertEquals(2, callCount.get()); From c7c04ba77aec5bd16cd1e1483a96ab17c0c55408 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Mon, 25 Mar 2024 14:24:14 +0300 Subject: [PATCH 7/8] feat: add comment to test setId --- .../java/internal/ModuleDeviceIdTests.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java index c8939d40..467b55b9 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java @@ -483,6 +483,21 @@ public void setID_custom() { * "setID" with double without merge * Validating that new id set and callback is called, and existing events,timed events and session must end, new session must begin * request order should be first began session, 1 events, 1 end session, second began session, second end session, third began session + *
+ * - Init the SDK with custom device id TestUtil.DEVICE_ID + * - Setup session, view and event + * - Validate that session is begun + * - Validate that device id is developer supplied, and it is TestUtil.DEVICE_ID + * - Wait for view duration to end + * - Validate that there are 2 events in the event queue (view start and casual event) + * - Set new device id TestUtil.keysValues[0] + * - Validate that there are no events in the event queue because it is flushed due to device id without merge change + * - Validate that callback is called once which is "deviceIdChanged" internal callback + * - Validate that there are 4 requests in the request queue, first began session, 1 events, 1 end session, second began session + * - Flush the request queue with old device id TestUtil.DEVICE_ID + * - Change device id to TestUtils.DEVICE_ID + "1" + * - Validate that there are 2 calls to the callback + * - Validate that there are 3 requests in the request queue, second began session, second end session, third began session */ @Test public void setID_changeWithoutMerge() throws InterruptedException { @@ -516,6 +531,20 @@ public void setID_changeWithoutMerge() throws InterruptedException { * "setID" first sdk generated then developer supplied * Validating that first call acts like "changeWithMerge" and second call acts like "changeWithoutMerge" * SDK must generate an id first, then should change with developer supplied two times + *
+ * - Init the SDK with no custom id + * - Setup session, view and event to simulate a device id change + * - Validate that session is begun + * - Validate that device id is sdk generated + * - Set new device id TestUtils.DEVICE_ID + * - Validate that EQ size is not changed because it is merge request + * - Validate that callback is called once which is "deviceIdChanged" internal callback + * - Validate that there are 2 requests in the event queue (first is begun session second one is device id change request) + * - Flush the request queue with old device id + * - Change device id to TestUtils.DEVICE_ID + "1" + * - Validate that EQ is flushed because it is not a merge request + * - Validate that callback is called twice + * - Validate that there are 3 requests in the request queue, first began session, 1 events, 1 end session */ @Test public void setID_changeWithMerge_then_withoutMerge() throws InterruptedException { From 4f878b1dca08dc956f8546c8f9c23e20307691cd Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray <57103426+arifBurakDemiray@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:35:56 +0300 Subject: [PATCH 8/8] Update ModuleDeviceIdTests.java --- .../java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java index 467b55b9..9dc24366 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/ModuleDeviceIdTests.java @@ -569,7 +569,7 @@ public void setID_changeWithMerge_then_withoutMerge() throws InterruptedExceptio validateDeviceIdWithMergeChange(oldDeviceId, 1, 2); TestUtils.flushCurrentRQWithOldDeviceId(oldDeviceId); // clean current rq with old device id requests - deviceID.value += "1"; + deviceID.value = TestUtils.DEVICE_ID + "1"; withMerge.set(true); // set atomic boolean to true to validate without merge Thread.sleep(1000); // waiting for timed event duration