@@ -297,6 +297,63 @@ internal class CompositionTest<Type, Field> {
297297 assert (sndComposedExpression == = answer)
298298 }
299299
300+ @Test
301+ fun testComposeSeveralTimes () = with (ctx) {
302+ val fstAddress = mockk<USymbolicHeapRef >()
303+ val fstIndex = mockk<USizeExpr >()
304+
305+ val sndAddress = mockk<USymbolicHeapRef >()
306+ val sndIndex = mockk<USizeExpr >()
307+
308+ val arrayType: KClass <Array <* >> = Array ::class
309+ // Create an empty region
310+ val region = emptyInputArrayRegion(arrayType, mkBv32Sort()) { key, memoryRegion ->
311+ mkInputArrayReading(memoryRegion, key.first, key.second)
312+ }
313+
314+ // TODO replace with jacoDB type
315+ // create a reading from the region
316+ val fstArrayIndexReading = mkInputArrayReading(region, fstAddress, fstIndex)
317+
318+ val typeEvaluator = mockk<UTypeEvaluator <KClass <* >>>() // TODO replace with jacoDB type
319+ val sndHeapEvaluator = URegionHeap <Field , KClass <* >>(ctx) // TODO replace with jacoDB type
320+ // create a heap with a record: (sndAddress, sndIndex) = 2
321+ sndHeapEvaluator.writeArrayIndex(sndAddress, sndIndex, arrayType, mkBv32Sort(), 2 .toBv(), mkTrue())
322+
323+ val sndComposer = UComposer (
324+ ctx, stackEvaluator, sndHeapEvaluator, typeEvaluator, mockEvaluator
325+ ) // TODO replace with jacoDB type
326+
327+ val fstEvaluator = URegionHeap <Field , KClass <* >>(ctx) // TODO replace with jacoDB type
328+ // create a heap with a record: (fstAddress, fstIndex) = 1
329+ fstEvaluator.writeArrayIndex(fstAddress, fstIndex, arrayType, mkBv32Sort(), 1 .toBv(), mkTrue())
330+
331+ val fstComposer = UComposer (
332+ ctx, stackEvaluator, fstEvaluator, typeEvaluator, mockEvaluator
333+ ) // TODO replace with jacoDB type
334+
335+ // Both heaps leave everything untouched
336+ every { sndAddress.accept(sndComposer) } returns sndAddress
337+ every { sndAddress.accept(fstComposer) } returns sndAddress
338+ every { fstAddress.accept(sndComposer) } returns fstAddress
339+ every { fstAddress.accept(fstComposer) } returns fstAddress
340+
341+ every { fstIndex.accept(fstComposer) } returns fstIndex
342+ every { fstIndex.accept(sndComposer) } returns fstIndex
343+ every { sndIndex.accept(fstComposer) } returns sndIndex
344+ every { sndIndex.accept(sndComposer) } returns sndIndex
345+
346+ val sndComposedExpr = sndComposer.compose(fstArrayIndexReading)
347+ val fstComposedExpr = fstComposer.compose(sndComposedExpr)
348+
349+ val expectedRegion = region
350+ .write(USymbolicArrayIndex (fstAddress, fstIndex), 1 .toBv(), guard = mkTrue())
351+ .write(USymbolicArrayIndex (sndAddress, sndIndex), 2 .toBv(), guard = mkTrue())
352+
353+ require(fstComposedExpr is UInputArrayReading <* , * >)
354+ assert (fstComposedExpr.region.updates.toList() == expectedRegion.updates.toList())
355+ }
356+
300357 @Test
301358 fun testUAllocatedArrayIndexReading () = with (ctx) {
302359 val arrayType: KClass <Array <* >> = Array ::class
0 commit comments