@@ -20,9 +20,11 @@ package com.google.firebase.dataconnect.core
20
20
21
21
import com.google.firebase.dataconnect.testutil.property.arbitrary.DataConnectArb
22
22
import com.google.firebase.dataconnect.testutil.property.arbitrary.dataConnect
23
+ import com.google.firebase.dataconnect.testutil.property.arbitrary.distinctPair
23
24
import com.google.firebase.dataconnect.testutil.property.arbitrary.queryRefImpl
24
25
import com.google.firebase.dataconnect.testutil.shouldContainWithNonAbuttingText
25
26
import io.kotest.assertions.assertSoftly
27
+ import io.kotest.assertions.withClue
26
28
import io.kotest.common.ExperimentalKotest
27
29
import io.kotest.matchers.shouldBe
28
30
import io.kotest.matchers.shouldNotBe
@@ -31,9 +33,10 @@ import io.kotest.matchers.string.shouldStartWith
31
33
import io.kotest.matchers.types.shouldBeSameInstanceAs
32
34
import io.kotest.property.Arb
33
35
import io.kotest.property.PropTestConfig
34
- import io.kotest.property.arbitrary.arbitrary
36
+ import io.kotest.property.arbitrary.bind
35
37
import io.kotest.property.arbitrary.choice
36
38
import io.kotest.property.arbitrary.int
39
+ import io.kotest.property.arbitrary.map
37
40
import io.kotest.property.assume
38
41
import io.kotest.property.checkAll
39
42
import kotlinx.coroutines.test.runTest
@@ -43,22 +46,17 @@ import org.junit.Test
43
46
class QueryResultImplUnitTest {
44
47
45
48
@Test
46
- fun `'data' should be the same object given to the constructor` () = runTest {
47
- checkAll(propTestConfig, Arb .dataConnect.queryRefImpl(), Arb .dataConnect.testData()) {
48
- query,
49
- data ->
50
- val queryResult = query.QueryResultImpl (data)
51
- queryResult.data shouldBeSameInstanceAs data
52
- }
53
- }
54
-
55
- @Test
56
- fun `'ref' should be the QueryRefImpl object that was used to create it` () = runTest {
57
- checkAll(propTestConfig, Arb .dataConnect.queryRefImpl(), Arb .dataConnect.testData()) {
58
- query,
59
- data ->
60
- val queryResult = query.QueryResultImpl (data)
61
- queryResult.ref shouldBeSameInstanceAs query
49
+ fun `properties should be the same objects given to or inferred by the constructor` () = runTest {
50
+ checkAll(
51
+ propTestConfig,
52
+ Arb .dataConnect.queryRefImpl(),
53
+ Arb .dataConnect.testData(),
54
+ ) { ref, data ->
55
+ val queryResult = ref.QueryResultImpl (data)
56
+ assertSoftly {
57
+ withClue(" ref" ) { queryResult.ref shouldBeSameInstanceAs ref }
58
+ withClue(" data" ) { queryResult.data shouldBeSameInstanceAs data }
59
+ }
62
60
}
63
61
}
64
62
@@ -125,10 +123,8 @@ class QueryResultImplUnitTest {
125
123
checkAll(
126
124
propTestConfig,
127
125
Arb .dataConnect.queryRefImpl(),
128
- Arb .dataConnect.testData(),
129
- Arb .dataConnect.testData()
130
- ) { query, data1, data2 ->
131
- assume(data1 != data2)
126
+ Arb .dataConnect.testData().distinctPair()
127
+ ) { query, (data1, data2) ->
132
128
val queryResult1 = query.QueryResultImpl (data1)
133
129
val queryResult2 = query.QueryResultImpl (data2)
134
130
queryResult1.equals(queryResult2) shouldBe false
@@ -139,11 +135,9 @@ class QueryResultImplUnitTest {
139
135
fun `equals() should return false when only 'ref' differs` () = runTest {
140
136
checkAll(
141
137
propTestConfig,
142
- Arb .dataConnect.queryRefImpl(),
143
- Arb .dataConnect.queryRefImpl(),
138
+ Arb .dataConnect.queryRefImpl().distinctPair(),
144
139
Arb .dataConnect.testData()
145
- ) { query1, query2, data,
146
- ->
140
+ ) { (query1, query2), data ->
147
141
assume(query1 != query2)
148
142
val queryResult1 = query1.QueryResultImpl (data)
149
143
val queryResult2 = query2.QueryResultImpl (data)
@@ -152,12 +146,11 @@ class QueryResultImplUnitTest {
152
146
}
153
147
154
148
@Test
155
- fun `equals() should return false when data of first object is null and second is non-null` () =
149
+ fun `equals() should return false when data of first data is null and second is non-null` () =
156
150
runTest {
157
151
checkAll(propTestConfig, Arb .dataConnect.queryRefImpl(), Arb .dataConnect.testData()) {
158
152
query,
159
- data,
160
- ->
153
+ data ->
161
154
val queryResult1 = query.QueryResultImpl (null )
162
155
val queryResult2 = query.QueryResultImpl (data)
163
156
queryResult1.equals(queryResult2) shouldBe false
@@ -169,8 +162,7 @@ class QueryResultImplUnitTest {
169
162
runTest {
170
163
checkAll(propTestConfig, Arb .dataConnect.queryRefImpl(), Arb .dataConnect.testData()) {
171
164
query,
172
- data,
173
- ->
165
+ data ->
174
166
val queryResult1 = query.QueryResultImpl (data)
175
167
val queryResult2 = query.QueryResultImpl (null )
176
168
queryResult1.equals(queryResult2) shouldBe false
@@ -192,8 +184,7 @@ class QueryResultImplUnitTest {
192
184
fun `hashCode() should return the same value on equal objects` () = runTest {
193
185
checkAll(propTestConfig, Arb .dataConnect.queryRefImpl(), Arb .dataConnect.testData()) {
194
186
query,
195
- data,
196
- ->
187
+ data ->
197
188
val queryResult1 = query.QueryResultImpl (data)
198
189
val queryResult2 = query.QueryResultImpl (data)
199
190
queryResult1.hashCode() shouldBe queryResult2.hashCode()
@@ -203,12 +194,10 @@ class QueryResultImplUnitTest {
203
194
@Test
204
195
fun `hashCode() should return a different value if 'data' is different` () = runTest {
205
196
checkAll(
206
- propTestConfig ,
197
+ hashEqualityPropTestConfig ,
207
198
Arb .dataConnect.queryRefImpl(),
208
- Arb .dataConnect.testData(),
209
- Arb .dataConnect.testData()
210
- ) { query, data1, data2,
211
- ->
199
+ Arb .dataConnect.testData().distinctPair(),
200
+ ) { query, (data1, data2) ->
212
201
assume(data1.hashCode() != data2.hashCode())
213
202
val queryResult1 = query.QueryResultImpl (data1)
214
203
val queryResult2 = query.QueryResultImpl (data2)
@@ -219,12 +208,10 @@ class QueryResultImplUnitTest {
219
208
@Test
220
209
fun `hashCode() should return a different value if 'ref' is different` () = runTest {
221
210
checkAll(
222
- propTestConfig,
223
- Arb .dataConnect.queryRefImpl(),
224
- Arb .dataConnect.queryRefImpl(),
211
+ hashEqualityPropTestConfig,
212
+ Arb .dataConnect.queryRefImpl().distinctPair(),
225
213
Arb .dataConnect.testData()
226
- ) { query1, query2, data,
227
- ->
214
+ ) { (query1, query2), data ->
228
215
assume(query1.hashCode() != query2.hashCode())
229
216
val queryResult1 = query1.QueryResultImpl (data)
230
217
val queryResult2 = query2.QueryResultImpl (data)
@@ -239,21 +226,25 @@ class QueryResultImplUnitTest {
239
226
private companion object {
240
227
val propTestConfig = PropTestConfig (iterations = 20 )
241
228
229
+ // Allow a small number of failures to account for the rare, but possible situation where two
230
+ // distinct instances produce the same hash code.
231
+ val hashEqualityPropTestConfig =
232
+ propTestConfig.copy(
233
+ minSuccess = propTestConfig.iterations!! - 2 ,
234
+ maxFailure = 2 ,
235
+ )
236
+
242
237
fun DataConnectArb.testVariables (string : Arb <String > = string()): Arb <TestVariables > =
243
- arbitrary {
244
- TestVariables (string.bind())
245
- }
238
+ string.map { TestVariables (it) }
246
239
247
- fun DataConnectArb.testData (string : Arb <String > = string()): Arb <TestData > = arbitrary {
248
- TestData (string.bind())
249
- }
240
+ fun DataConnectArb.testData (string : Arb <String > = string()): Arb <TestData > =
241
+ string.map { TestData (it) }
250
242
251
243
fun DataConnectArb.queryResultImpl (
252
244
query : Arb <QueryRefImpl <TestData ?, TestVariables >> = queryRefImpl(),
253
- data : Arb <TestData > = testData()
254
- ): Arb <QueryRefImpl <TestData ?, TestVariables >.QueryResultImpl > = arbitrary {
255
- query.bind().QueryResultImpl (data.bind())
256
- }
245
+ data : Arb <TestData > = testData(),
246
+ ): Arb <QueryRefImpl <TestData ?, TestVariables >.QueryResultImpl > =
247
+ Arb .bind(query, data) { query, data -> query.QueryResultImpl (data) }
257
248
258
249
fun DataConnectArb.queryRefImpl (): Arb <QueryRefImpl <TestData ?, TestVariables >> =
259
250
queryRefImpl(Arb .dataConnect.testVariables())
0 commit comments