Skip to content

Commit 78d8b77

Browse files
Defines a brute force isEqualTo API for PersistableBundle. PersistableBundle has historically been very painful to test since they are lazy containers and do not implement equals. While the existing per value subjects are useful, they do not allow for generic comparison in parametrized tests which limits flexibility and results in more boilerplate in unit tests.
PiperOrigin-RevId: 812881330
1 parent 43475af commit 78d8b77

File tree

5 files changed

+352
-31
lines changed

5 files changed

+352
-31
lines changed

ext/truth/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
* `BundleSubject` and `PersistableBundleSubject` now share `BaseBundle` support,
1212
including additional array type assertions
13+
* `PersistableBundleSubject` now supports `isEqualTo` and `isNotEqualTo` for
14+
direct comparison between two `PersistableBundle`'s.
1315
* Added `integerArrayList` method to `BundleSubject`.
1416

1517
**Breaking Changes**

ext/truth/java/androidx/test/ext/truth/api/current_public.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,9 @@ package androidx.test.ext.truth.os {
149149
method public final com.google.common.truth.PrimitiveIntArraySubject! intArray(String!);
150150
method public final com.google.common.truth.IntegerSubject! integer(String!);
151151
method public final void isEmpty();
152+
method public void isEqualTo(android.os.PersistableBundle!);
152153
method public final void isNotEmpty();
154+
method public void isNotEqualTo(android.os.PersistableBundle!);
153155
method public final com.google.common.truth.PrimitiveLongArraySubject! longArray(String!);
154156
method public final com.google.common.truth.LongSubject! longInt(String!);
155157
method public androidx.test.ext.truth.os.PersistableBundleSubject! persistableBundle(String!);

ext/truth/java/androidx/test/ext/truth/os/BaseBundleSubject.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.common.truth.PrimitiveLongArraySubject;
3333
import com.google.common.truth.StringSubject;
3434
import com.google.common.truth.Subject;
35+
import java.util.Arrays;
3536

3637
/**
3738
* Subject for making assertions about {@link BaseBundle}s.
@@ -118,4 +119,32 @@ public final PrimitiveDoubleArraySubject doubleArray(String key) {
118119
public final ObjectArraySubject<String> stringArray(String key) {
119120
return check("getStringArray(%s)", key).that(actual.getStringArray(key));
120121
}
122+
123+
/** Checks if two bundle values are equal. */
124+
protected final boolean isBaseBundleValueEqual(Object actual, Object expected) {
125+
if ((actual == null) != (expected == null)) {
126+
return false;
127+
} else if (actual == null) {
128+
return true;
129+
}
130+
131+
// We need to iterate through each possible array type, since .equals() would just be
132+
// referential equality.
133+
if (actual instanceof boolean[] actualArray && expected instanceof boolean[] expectedArray) {
134+
return Arrays.equals(actualArray, expectedArray);
135+
} else if (actual instanceof double[] actualArray
136+
&& expected instanceof double[] expectedArray) {
137+
return Arrays.equals(actualArray, expectedArray);
138+
} else if (actual instanceof int[] actualArray && expected instanceof int[] expectedArray) {
139+
return Arrays.equals(actualArray, expectedArray);
140+
} else if (actual instanceof long[] actualArray && expected instanceof long[] expectedArray) {
141+
return Arrays.equals(actualArray, expectedArray);
142+
} else if (actual instanceof String[] actualArray
143+
&& expected instanceof String[] expectedArray) {
144+
return Arrays.equals(actualArray, expectedArray);
145+
} else {
146+
// If types don't match above, or they're simply a non-array type, use normal equality.
147+
return actual.equals(expected);
148+
}
149+
}
121150
}

ext/truth/java/androidx/test/ext/truth/os/PersistableBundleSubject.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@
1515
*/
1616
package androidx.test.ext.truth.os;
1717

18+
import static com.google.common.truth.Fact.simpleFact;
19+
1820
import android.os.Build;
1921
import android.os.PersistableBundle;
2022
import androidx.annotation.RequiresApi;
2123
import com.google.common.truth.FailureMetadata;
2224
import com.google.common.truth.Subject;
2325
import com.google.common.truth.Truth;
26+
import java.util.Set;
2427

2528
/**
2629
* Subject for making assertions about {@link PersistableBundle}s.
@@ -34,6 +37,56 @@ public static PersistableBundleSubject assertThat(PersistableBundle persistableB
3437
return Truth.assertAbout(persistableBundles()).that(persistableBundle);
3538
}
3639

40+
public final void isEqualTo(PersistableBundle other) {
41+
if (!arePersistableBundlesEqual(actual, other)) {
42+
failWithActual(simpleFact("expected to be equal to " + other));
43+
}
44+
}
45+
46+
public final void isNotEqualTo(PersistableBundle other) {
47+
if (arePersistableBundlesEqual(actual, other)) {
48+
failWithActual(simpleFact("expected to not be equal to " + other));
49+
}
50+
}
51+
52+
private final boolean arePersistableBundlesEqual(
53+
PersistableBundle actual, PersistableBundle expected) {
54+
if ((actual == null) != (expected == null)) {
55+
return false;
56+
} else if (actual == null) {
57+
return true;
58+
}
59+
60+
if (actual.size() != expected.size()) {
61+
return false;
62+
}
63+
64+
Set<String> actualKeys = actual.keySet();
65+
Set<String> expectedKeys = expected.keySet();
66+
if (!actualKeys.equals(expectedKeys)) {
67+
return false;
68+
}
69+
70+
for (String key : actualKeys) {
71+
Object actualValue = actual.get(key);
72+
Object expectedValue = expected.get(key);
73+
boolean actualHasPersistableBundleValue = actualValue instanceof PersistableBundle;
74+
boolean expectedHasPersistableBundleValue = expectedValue instanceof PersistableBundle;
75+
76+
if (actualHasPersistableBundleValue != expectedHasPersistableBundleValue) {
77+
return false;
78+
} else if (actualHasPersistableBundleValue) {
79+
if (!arePersistableBundlesEqual(
80+
actual.getPersistableBundle(key), expected.getPersistableBundle(key))) {
81+
return false;
82+
}
83+
} else if (!isBaseBundleValueEqual(actualValue, expectedValue)) {
84+
return false;
85+
}
86+
}
87+
return true;
88+
}
89+
3790
public static Subject.Factory<PersistableBundleSubject, PersistableBundle> persistableBundles() {
3891
return PersistableBundleSubject::new;
3992
}

0 commit comments

Comments
 (0)