/
CycleDetectionTest.kt
124 lines (121 loc) · 5.15 KB
/
CycleDetectionTest.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package com.tylerthrailkill.helpers.prettyprint
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
object CycleDetectionTest : Spek({
setup()
describe("pretty printing") {
context("plain objects with cycles") {
it("should detect a cycle with plain Unit") {
val unit = Unit
val identity = System.identityHashCode(unit)
prettyPrint(unit) mapsTo """
Unit(
INSTANCE = cyclic reference detected for $identity
)[${'$'}id=$identity]
"""
}
it("should detect a cycle with two small objects") {
val sco1 = SmallCyclicalObject1()
val sco2 = SmallCyclicalObject2(sco1)
sco1.c = sco2
val identity = System.identityHashCode(sco1)
prettyPrint(sco1) mapsTo """
SmallCyclicalObject1(
c = SmallCyclicalObject2(
c = cyclic reference detected for $identity
)
)[${'$'}id=$identity]
"""
}
it("should detect no cycle when an element is repeated several times in the same objects fields") {
val smallObject = SmallObject("a string in small object", 777)
val nestedLargeObjectNull = NestedLargeObject(
NestedSmallObject(smallObject),
smallObject,
"test string, please don't break",
null
)
prettyPrint(nestedLargeObjectNull) mapsTo """
NestedLargeObject(
nestedSmallObject = NestedSmallObject(
smallObject = SmallObject(
field1 = a string in small object
field2 = 777
)
)
smallObject = SmallObject(
field1 = a string in small object
field2 = 777
)
testString = test string, please don't break
bigObject = null
)
"""
}
}
context("maps with cycles") {
it("should detect a cycle between an object with a map with an object with a cycle") {
val objectWithMap = ObjectWithMap(
mutableMapOf(1 to null)
)
val objectContainingObjectWithMap = ObjectContainingObjectWithMap()
objectContainingObjectWithMap.objectWithMap = objectWithMap
objectWithMap.map[1] = objectContainingObjectWithMap
val identity = System.identityHashCode(objectWithMap)
prettyPrint(objectWithMap) mapsTo """
ObjectWithMap(
map = {
1 -> ObjectContainingObjectWithMap(
objectWithMap = cyclic reference detected for $identity
)
}
)[${'$'}id=$identity]
""".trimIndent()
}
it("should detect a cycle of a map containing itself") {
val outerMap: MutableMap<Int, Any?> = mutableMapOf(1 to null)
val innerMap = mutableMapOf(1 to outerMap)
outerMap[1] = innerMap
val identity = System.identityHashCode(outerMap)
prettyPrint(outerMap) mapsTo """
{
1 -> {
1 -> cyclic reference detected for $identity
}
}[${'$'}id=$identity]
""".trimIndent()
}
}
context("lists with cycles") {
it("should detect a cycle between an object with a list with an object with a cycle") {
val objectWithList = ObjectWithList(mutableListOf())
val objectContainingObjectWithList = ObjectContainingObjectWithList()
objectContainingObjectWithList.objectWithList = objectWithList
objectWithList.list.add(objectContainingObjectWithList)
val identity = System.identityHashCode(objectWithList)
prettyPrint(objectWithList) mapsTo """
ObjectWithList(
list = [
ObjectContainingObjectWithList(
objectWithList = cyclic reference detected for $identity
)
]
)[${'$'}id=$identity]
""".trimIndent()
}
it("should detect a cycle of a list containing itself") {
val outerList: MutableList<Any?> = mutableListOf()
val innerList = mutableListOf(outerList)
outerList.add(innerList)
val identity = System.identityHashCode(outerList)
prettyPrint(outerList) mapsTo """
[
[
cyclic reference detected for $identity
]
][${'$'}id=$identity]
""".trimIndent()
}
}
}
})