Skip to content

Commit

Permalink
Add ts to enqueue (#3984)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/488551667048375/1206114567373973/f

### Description
Ensure VPN enqueues contain ET ts.

### Steps to test this PR
QA optional
  • Loading branch information
aitorvs authored Dec 8, 2023
1 parent 8a937ae commit ce3309b
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import com.duckduckgo.networkprotection.impl.pixels.NetworkProtectionPixelNames.
import com.squareup.anvil.annotations.ContributesBinding
import dagger.SingleInstanceIn
import javax.inject.Inject
import javax.inject.Qualifier
import org.threeten.bp.Instant
import org.threeten.bp.ZoneId
import org.threeten.bp.ZoneOffset
import org.threeten.bp.format.DateTimeFormatter

Expand Down Expand Up @@ -318,6 +320,7 @@ class RealNetworkProtectionPixel @Inject constructor(
private val pixel: Pixel,
private val vpnSharedPreferencesProvider: VpnSharedPreferencesProvider,
private val cohortStore: NetpCohortStore,
private val etTimestamp: ETTimestamp,
) : NetworkProtectionPixels {

private val preferences: SharedPreferences by lazy {
Expand Down Expand Up @@ -559,7 +562,7 @@ class RealNetworkProtectionPixel @Inject constructor(
enqueue: Boolean = false,
) {
if (enqueue) {
pixel.enqueueFire(pixelName, payload)
pixel.enqueueFire(pixelName, payload.addTimestampAtZoneET())
} else {
pixel.fire(pixelName, payload)
}
Expand All @@ -583,7 +586,7 @@ class RealNetworkProtectionPixel @Inject constructor(
// check if pixel was already sent in the current day
if (timestamp == null || now > timestamp) {
if (enqueue) {
this.pixel.enqueueFire(pixelName, payload)
this.pixel.enqueueFire(pixelName, payload.addTimestampAtZoneET())
.also { preferences.edit { putString(pixelName.appendTimestampSuffix(), now) } }
} else {
this.pixel.fire(pixelName, payload)
Expand All @@ -602,7 +605,7 @@ class RealNetworkProtectionPixel @Inject constructor(
if (didExecuteAlready) return

if (pixel.enqueue) {
this.pixel.enqueueFire(pixel, payload).also { preferences.edit { putBoolean(tag ?: pixel.pixelName, true) } }
this.pixel.enqueueFire(pixel, payload.addTimestampAtZoneET()).also { preferences.edit { putBoolean(tag ?: pixel.pixelName, true) } }
} else {
this.pixel.fire(pixel, payload).also { preferences.edit { putBoolean(tag ?: pixel.pixelName, true) } }
}
Expand All @@ -612,12 +615,32 @@ class RealNetworkProtectionPixel @Inject constructor(
return "${this}_timestamp"
}

private fun Map<String, String>.addTimestampAtZoneET(): Map<String, String> {
return this.toMutableMap().apply {
put(TIMESTAMP_ET_PARAM, etTimestamp.formattedTimestamp())
}
}

private fun getUtcIsoLocalDate(): String {
// returns YYYY-MM-dd
return Instant.now().atOffset(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE)
}

companion object {
private const val NETP_PIXELS_PREF_FILE = "com.duckduckgo.networkprotection.pixels.v1"
private const val TIMESTAMP_ET_PARAM = "ts"
}
}

@Retention(AnnotationRetention.BINARY)
@Qualifier
private annotation class InternalApi

// This class is here for testing purposes
@InternalApi
open class ETTimestamp @Inject constructor() {
open fun formattedTimestamp(): String {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
return Instant.now().atZone(ZoneId.of("America/New_York")).format(formatter)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class RealNetworkProtectionPixelTest {

@Mock
private lateinit var vpnSharedPreferencesProvider: VpnSharedPreferencesProvider

private lateinit var fakeNetpCohortStore: FakeNetpCohortStore

private lateinit var testee: RealNetworkProtectionPixel
Expand All @@ -51,43 +52,58 @@ class RealNetworkProtectionPixelTest {
whenever(
vpnSharedPreferencesProvider.getSharedPreferences(eq("com.duckduckgo.networkprotection.pixels.v1"), eq(true), eq(false)),
).thenReturn(prefs)
testee = RealNetworkProtectionPixel(pixel, vpnSharedPreferencesProvider, fakeNetpCohortStore)
testee = RealNetworkProtectionPixel(
pixel,
vpnSharedPreferencesProvider,
fakeNetpCohortStore,
object : ETTimestamp() {
override fun formattedTimestamp(): String {
return "2000-01-01"
}
},
)
}

@Test
fun whenReportErrorInRegistrationIsCalledTwiceThenFireCountPixelTwiceAndDailyPixelOnce() {
testee.reportErrorInRegistration()
testee.reportErrorInRegistration()

verify(pixel).enqueueFire("m_netp_ev_backend_api_error_device_registration_failed_d")
verify(pixel, times(2)).enqueueFire("m_netp_ev_backend_api_error_device_registration_failed_c")
verify(pixel).enqueueFire("m_netp_ev_backend_api_error_device_registration_failed_d", mapOf("ts" to "2000-01-01"))
verify(pixel, times(2)).enqueueFire("m_netp_ev_backend_api_error_device_registration_failed_c", mapOf("ts" to "2000-01-01"))
}

@Test
fun whenReportErrorWgInvalidStateIsCalledTwiceThenFireCountPixelTwiceAndDailyPixelOnce() {
testee.reportErrorWgInvalidState()
testee.reportErrorWgInvalidState()

verify(pixel).enqueueFire("m_netp_ev_wireguard_error_invalid_state_d")
verify(pixel, times(2)).enqueueFire("m_netp_ev_wireguard_error_invalid_state_c")
verify(pixel).enqueueFire("m_netp_ev_wireguard_error_invalid_state_d", mapOf("ts" to "2000-01-01"))
verify(pixel, times(2)).enqueueFire("m_netp_ev_wireguard_error_invalid_state_c", mapOf("ts" to "2000-01-01"))
}

@Test
fun whenReportErrorWgBackendCantStartIsCalledTwiceThenFireCountPixelTwiceAndDailyPixelOnce() {
testee.reportErrorWgBackendCantStart()
testee.reportErrorWgBackendCantStart()

verify(pixel).enqueueFire("m_netp_ev_wireguard_error_cannot_start_wireguard_backend_d")
verify(pixel, times(2)).enqueueFire("m_netp_ev_wireguard_error_cannot_start_wireguard_backend_c")
verify(pixel).enqueueFire("m_netp_ev_wireguard_error_cannot_start_wireguard_backend_d", mapOf("ts" to "2000-01-01"))
verify(pixel, times(2)).enqueueFire("m_netp_ev_wireguard_error_cannot_start_wireguard_backend_c", mapOf("ts" to "2000-01-01"))
}

@Test
fun whenReportEnabledCalledTwiceThenFireDailyPixelOnce() {
testee.reportEnabled()
testee.reportEnabled()

verify(pixel).enqueueFire("m_netp_ev_enabled_d", mapOf("cohort" to fakeNetpCohortStore.cohortLocalDate?.toString().orEmpty()))
verify(pixel).enqueueFire(NETP_ENABLE_UNIQUE, mapOf("cohort" to fakeNetpCohortStore.cohortLocalDate?.toString().orEmpty()))
verify(pixel).enqueueFire(
"m_netp_ev_enabled_d",
mapOf("cohort" to fakeNetpCohortStore.cohortLocalDate?.toString().orEmpty(), "ts" to "2000-01-01"),
)
verify(pixel).enqueueFire(
NETP_ENABLE_UNIQUE,
mapOf("cohort" to fakeNetpCohortStore.cohortLocalDate?.toString().orEmpty(), "ts" to "2000-01-01"),
)
}

@Test
Expand All @@ -103,35 +119,35 @@ class RealNetworkProtectionPixelTest {
testee.reportVpnConnectivityLoss()
testee.reportVpnConnectivityLoss()

verify(pixel).enqueueFire("m_netp_ev_vpn_connectivity_lost_d")
verify(pixel, times(2)).enqueueFire("m_netp_ev_vpn_connectivity_lost_c")
verify(pixel).enqueueFire("m_netp_ev_vpn_connectivity_lost_d", mapOf("ts" to "2000-01-01"))
verify(pixel, times(2)).enqueueFire("m_netp_ev_vpn_connectivity_lost_c", mapOf("ts" to "2000-01-01"))
}

@Test
fun whenReportVpnReconnectFailedCalledTwiceThenFireCountPixelTwiceAndDailyPixelOnce() {
testee.reportVpnReconnectFailed()
testee.reportVpnReconnectFailed()

verify(pixel).enqueueFire("m_netp_ev_vpn_reconnect_failed_d")
verify(pixel, times(2)).enqueueFire("m_netp_ev_vpn_reconnect_failed_c")
verify(pixel).enqueueFire("m_netp_ev_vpn_reconnect_failed_d", mapOf("ts" to "2000-01-01"))
verify(pixel, times(2)).enqueueFire("m_netp_ev_vpn_reconnect_failed_c", mapOf("ts" to "2000-01-01"))
}

@Test
fun whenReportWireguardLibraryLoadFailedCalledTwiceThenFireCountPixelTwiceAndDailyPixelOnce() {
testee.reportWireguardLibraryLoadFailed()
testee.reportWireguardLibraryLoadFailed()

verify(pixel).enqueueFire("m_netp_ev_wireguard_error_unable_to_load_wireguard_library_d")
verify(pixel, times(2)).enqueueFire("m_netp_ev_wireguard_error_unable_to_load_wireguard_library_c")
verify(pixel).enqueueFire("m_netp_ev_wireguard_error_unable_to_load_wireguard_library_d", mapOf("ts" to "2000-01-01"))
verify(pixel, times(2)).enqueueFire("m_netp_ev_wireguard_error_unable_to_load_wireguard_library_c", mapOf("ts" to "2000-01-01"))
}

@Test
fun whenReportRekeyCompletedCalledTwiceThenFireDailyPixelOnce() {
testee.reportRekeyCompleted()
testee.reportRekeyCompleted()

verify(pixel).enqueueFire("m_netp_ev_rekey_completed_d")
verify(pixel, times(2)).enqueueFire("m_netp_ev_rekey_completed_c")
verify(pixel).enqueueFire("m_netp_ev_rekey_completed_d", mapOf("ts" to "2000-01-01"))
verify(pixel, times(2)).enqueueFire("m_netp_ev_rekey_completed_c", mapOf("ts" to "2000-01-01"))
}

@Test
Expand Down

0 comments on commit ce3309b

Please sign in to comment.