Conversation
a5339c4 to
899ef0f
Compare
totalRam, processorCount and isLowRamDevice to DeviceInfo
65945bf to
55a5484
Compare
This comment has been minimized.
This comment has been minimized.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #3024 +/- ##
===========================================
+ Coverage 71.20% 71.24% +0.04%
===========================================
Files 922 922
Lines 34099 34172 +73
Branches 5776 5776
===========================================
+ Hits 24277 24344 +67
- Misses 8190 8204 +14
+ Partials 1632 1624 -8
🚀 New features to boost your workflow:
|
55a5484 to
c356214
Compare
c356214 to
a4e01bd
Compare
totalRam, processorCount and isLowRamDevice to DeviceInfototalRam, processorCount and isLowRamDevice to DeviceInfo
a4e01bd to
5235618
Compare
totalRam, processorCount and isLowRamDevice to DeviceInfototalRam, logicalCpuCount and isLowRam to DeviceInfo
84cc489 to
0d87288
Compare
b08d16b to
1163614
Compare
1163614 to
a95c0f6
Compare
0xnm
left a comment
There was a problem hiding this comment.
LGTM, just some minor cleanup is needed.
| val totalRam: Int?, | ||
| val isLowRam: Boolean? |
There was a problem hiding this comment.
I believe these two are nullable because the API we use to get this info may not return the data?
UPD: I see, it is due to the exception handling.
| - "android.content.Context.getSharedPreferences(kotlin.String?, kotlin.Int)" | ||
| - "android.content.Context.getSystemService(kotlin.String)" | ||
| - "android.content.Context.getSharedPreferences(kotlin.String?, kotlin.Int)" | ||
| - "android.content.Context.getSystemService(java.lang.Class)" |
There was a problem hiding this comment.
neat! we indeed can use it now since min API is 23.
| assertThat(actual.device) | ||
| .usingRecursiveComparison() | ||
| .ignoringFields("batteryLevel", "brightnessLevel") | ||
| .ignoringFields("batteryLevel", "brightnessLevel", "totalRam", "logicalCpuCount") |
There was a problem hiding this comment.
Afaik this was to avoid losing precision in the floating point values between serialization/deserialization roundtrip, so it is not needed for the integer values. Same for other deserialized assertions below.
There was a problem hiding this comment.
Actually, I added this because the recursive comparison seems to break with integer values, but I am happy to revisit it. Maybe I'll clue you in with the error stacktrace, you might have some useful insight to share. I'll follow up soon.
There was a problem hiding this comment.
In RumEventDeserializerTest.kt using:
@ForgeConfiguration(value = Configurator::class, seed = 0xd1285cd0106L)
The forged event has:
logicalCpuCount = 1181136908
totalRam = -479744429
// Also, would it make sense to only forge positive values?
// I kept it like this to cover all possible values and make sure
// we never get runtime errors as long as these values are Integers
And I get this error:
Can't find any field or property with name 'value'.
Error when introspecting properties was :
- No getter for property 'value' in java.lang.Integer
Error when introspecting fields was :
- Unable to obtain the value of the field <'value'> from <-479744429>
org.assertj.core.util.introspection.IntrospectionError:
Can't find any field or property with name 'value'.
Error when introspecting properties was :
- No getter for property 'value' in java.lang.Integer
Error when introspecting fields was :
- Unable to obtain the value of the field <'value'> from <-479744429>
at app//org.assertj.core.util.introspection.PropertyOrFieldSupport.getSimpleValue(PropertyOrFieldSupport.java:88)
at app//org.assertj.core.api.recursive.comparison.RecursiveComparisonDifferenceCalculator.determineDifferences(RecursiveComparisonDifferenceCalculator.java:295)
at app//org.assertj.core.api.recursive.comparison.RecursiveComparisonDifferenceCalculator.determineDifferences(RecursiveComparisonDifferenceCalculator.java:186)
at app//org.assertj.core.api.RecursiveComparisonAssert.determineDifferencesWith(RecursiveComparisonAssert.java:1199)
at app//org.assertj.core.api.RecursiveComparisonAssert.isEqualTo(RecursiveComparisonAssert.java:160)
at app//com.datadog.android.rum.utils.assertj.DeserializedLongTaskEventAssert.isEqualTo(DeserializedLongTaskEventAssert.kt:28)
at app//com.datadog.android.rum.internal.domain.event.RumEventDeserializerTest.M deserialize a serialized RUM LongTaskEvent W deserialize()(RumEventDeserializerTest.kt:156)
at java.base@21.0.8/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
Caused by: org.assertj.core.util.introspection.IntrospectionError: Unable to obtain the value of the field <'value'> from <-479744429>
at app//org.assertj.core.util.introspection.FieldSupport.readSimpleField(FieldSupport.java:248)
at app//org.assertj.core.util.introspection.FieldSupport.fieldValue(FieldSupport.java:202)
at app//org.assertj.core.util.introspection.PropertyOrFieldSupport.getSimpleValue(PropertyOrFieldSupport.java:70)
... 87 more
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private final int java.lang.Integer.value accessible: module java.base does not "opens java.lang" to unnamed module @72a34537
at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(Unknown Source)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Unknown Source)
at java.base/java.lang.reflect.Field.setAccessible(Unknown Source)
at org.assertj.core.util.introspection.FieldUtils.getField(FieldUtils.java:67)
at org.assertj.core.util.introspection.FieldUtils.readField(FieldUtils.java:141)
at org.assertj.core.util.introspection.FieldSupport.readSimpleField(FieldSupport.java:208)
I'll debug this further and get back to you, but please let me know if this is a known issue or if you have any insight! :)
There was a problem hiding this comment.
I think I have found a fix!
When serializing and deserializing the forged event with JsonParser, the Integer values are converted to Number values, specifically to LazilyParsedNumber.
Internally, assertj encounters the attribute (e.g totalRam), and calls:
Set<String> actualFieldsNames = Objects.getFieldsNames(dualValue.actual.getClass());Which returns ["value"].
It then tries to access the value field on both the actual and expected event, causing the Runtime Error above, since Integer.value is private.
Here is the quick fix:
val lazilyParsedIntPredicate = BiPredicate { v1: LazilyParsedNumber, v2: Integer -> v1.toInt() == v2.toInt() }
assertThat(actual.device)
.usingRecursiveComparison()
.withEqualsForFields(lazilyParsedIntPredicate, "totalRam", "logicalCpuCount")
.ignoringFields("batteryLevel", "brightnessLevel")
.isEqualTo(expected.device)I'll refine this and update the PR :)
There was a problem hiding this comment.
I have pushed new changes, and added a common extension:
/**
* Custom predicate for comparing Gson's LazilyParsedNumber with Integer fields.
*
* See [withGsonIntEqualsForFields].
*/
private val lazilyParsedIntPredicate = BiPredicate { v1: LazilyParsedNumber, v2: Int -> v1.toInt() == v2 }
/**
* Adds support for comparing Gson's LazilyParsedNumber with Integer fields
* during AssertJ recursive comparison.
*
* Gson deserializes Integer values as LazilyParsedNumber. During recursive
* comparison, AssertJ may attempt reflective field comparison (e.g. Integer.value),
* which fails because the field is private. This forces value-based comparison instead.
*/
fun<T : RecursiveComparisonAssert<T>> RecursiveComparisonAssert<T>.withGsonIntEqualsForFields(
vararg fieldNames: String
): RecursiveComparisonAssert<T> {
return this.withEqualsForFields(lazilyParsedIntPredicate, *fieldNames)
}a95c0f6 to
cf9f086
Compare
0xnm
left a comment
There was a problem hiding this comment.
lgtm, there is just one line leftover from debugging
cf9f086 to
8eb4230
Compare
|
Thanks @0xnm! I have removed the left-over debugging line, and rebased the PR. Let's see if all checks pass, then one final approval and I believe we can merge this 🙏 |
|
@0xnm The checks are failing with: Seems like a schema issue, but shouldn't it be updated automatically? Update I have checked the pipeline configuration, and it seems like we rely on caching using Is it possible that the CI is still picking up the old schema, since the branch hasn't changed after I have updated Also, shouldn't we be using |
|
There is some strange caching issue.
This will point to the current commit, while we want to point to the last known branch HEAD. |
What does this PR do?
Adds new attributes to the Device Info:
ActivityManager.isLowRamDevice)Additional Notes
Review checklist (to be filled by reviewers)