summary refs log tree commit diff stats
path: root/tests/stdlib/tlists.nim
blob: 54fa8b24fd17869780e8871f7d407ff3b822d5e8 (plain) (blame)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
discard """
  targets: "c js"
"""

import std/[lists, sequtils]

const
  data = [1, 2, 3, 4, 5, 6]


template main =
  block SinglyLinkedListTest1:
    var L: SinglyLinkedList[int]
    for d in items(data): L.prepend(d)
    for d in items(data): L.add(d)
    doAssert($L == "[6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6]")

    doAssert(4 in L)

  block SinglyLinkedListTest2:
    var L: SinglyLinkedList[string]
    for d in items(data): L.prepend($d)
    doAssert($L == """["6", "5", "4", "3", "2", "1"]""")

    doAssert("4" in L)


  block DoublyLinkedListTest1:
    var L: DoublyLinkedList[int]
    for d in items(data): L.prepend(d)
    for d in items(data): L.add(d)
    L.remove(L.find(1))
    doAssert($L == "[6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6]")

    doAssert(4 in L)

  block SinglyLinkedRingTest1:
    var L: SinglyLinkedRing[int]
    L.prepend(4)
    doAssert($L == "[4]")
    L.prepend(4)

    doAssert($L == "[4, 4]")
    doAssert(4 in L)


  block DoublyLinkedRingTest1:
    var L: DoublyLinkedRing[int]
    L.prepend(4)
    doAssert($L == "[4]")
    L.prepend(4)

    doAssert($L == "[4, 4]")
    doAssert(4 in L)

    L.add(3)
    L.add(5)
    doAssert($L == "[4, 4, 3, 5]")

    L.remove(L.find(3))
    L.remove(L.find(5))
    L.remove(L.find(4))
    L.remove(L.find(4))
    doAssert($L == "[]")
    doAssert(4 notin L)

  block tlistsToString:
    block:
      var l = initDoublyLinkedList[int]()
      l.add(1)
      l.add(2)
      l.add(3)
      doAssert $l == "[1, 2, 3]"
    block:
      var l = initDoublyLinkedList[string]()
      l.add("1")
      l.add("2")
      l.add("3")
      doAssert $l == """["1", "2", "3"]"""
    block:
      var l = initDoublyLinkedList[char]()
      l.add('1')
      l.add('2')
      l.add('3')
      doAssert $l == """['1', '2', '3']"""

  # Copied here until it is merged into sequtils
  template take(a: untyped, max: int): untyped =
    type T = typeof(block: (for ai in a: ai))
    var ret: seq[T]
    var i = 0
    if max > 0:
      for ai in a:
        ret.add ai
        i.inc
        if i >= max: break
    ret

  template testCommon(initList, toList) =

    block: # toSinglyLinkedList, toDoublyLinkedList
      let l = seq[int].default
      doAssert l.toList.toSeq == []
      doAssert [1].toList.toSeq == [1]
      doAssert [1, 2, 3].toList.toSeq == [1, 2, 3]

    block copy:
      doAssert array[0, int].default.toList.copy.toSeq == []
      doAssert [1].toList.copy.toSeq == [1]
      doAssert [1, 2].toList.copy.toSeq == [1, 2]
      doAssert [1, 2, 3].toList.copy.toSeq == [1, 2, 3]
      type Foo = ref object
        x: int
      var f0 = Foo(x: 0)
      let f1 = Foo(x: 1)
      var a = [f0].toList
      var b = a.copy
      b.add f1
      doAssert a.toSeq == [f0]
      doAssert b.toSeq == [f0, f1]
      f0.x = 42
      doAssert a.head.value.x == 42
      doAssert b.head.value.x == 42

    block: # add, addMoved
      block:
        var
          l0 = initList[int]()
          l1 = [1].toList
          l2 = [2, 3].toList
          l3 = [4, 5, 6].toList
        l0.add l3
        l1.add l3
        l2.addMoved l3
        doAssert l0.toSeq == [4, 5, 6]
        doAssert l1.toSeq == [1, 4, 5, 6]
        doAssert l2.toSeq == [2, 3, 4, 5, 6]
        doAssert l3.toSeq == []
        l2.add l3 # re-adding l3 that was destroyed is now a no-op
        doAssert l2.toSeq == [2, 3, 4, 5, 6]
        doAssert l3.toSeq == []
      block:
        var
          l0 = initList[int]()
          l1 = [1].toList
          l2 = [2, 3].toList
          l3 = [4, 5, 6].toList
        l3.addMoved l0
        l2.addMoved l1
        doAssert l3.toSeq == [4, 5, 6]
        doAssert l2.toSeq == [2, 3, 1]
        l3.add l0
        doAssert l3.toSeq == [4, 5, 6]
      block:
        var c = [0, 1].toList
        c.addMoved c
        doAssert c.take(6) == [0, 1, 0, 1, 0, 1]

    block: # prepend, prependMoved
      block:
        var
          l0 = initList[int]()
          l1 = [1].toList
          l2 = [2, 3].toList
          l3 = [4, 5, 6].toList
        l0.prepend l3
        l1.prepend l3
        doAssert l3.toSeq == [4, 5, 6]
        l2.prependMoved l3
        doAssert l0.toSeq == [4, 5, 6]
        doAssert l1.toSeq == [4, 5, 6, 1]
        doAssert l2.toSeq == [4, 5, 6, 2, 3]
        doAssert l3.toSeq == []
        l2.prepend l3 # re-prepending l3 that was destroyed is now a no-op
        doAssert l2.toSeq == [4, 5, 6, 2, 3]
        doAssert l3.toSeq == []
      block:
        var
          l0 = initList[int]()
          l1 = [1].toList
          l2 = [2, 3].toList
          l3 = [4, 5, 6].toList
        l3.prependMoved l0
        l2.prependMoved l1
        doAssert l3.toSeq == [4, 5, 6]
        doAssert l2.toSeq == [1, 2, 3]
        l3.prepend l0
        doAssert l3.toSeq == [4, 5, 6]
      block:
        var c = [0, 1].toList
        c.prependMoved c
        doAssert c.take(6) == [0, 1, 0, 1, 0, 1]

    block remove:
      var l = [0, 1, 2, 3].toList
      let
        l0 = l.head
        l1 = l0.next
        l2 = l1.next
        l3 = l2.next
      l.remove l0
      doAssert l.toSeq == [1, 2, 3]
      l.remove l2
      doAssert l.toSeq == [1, 3]
      l.remove l2
      doAssert l.toSeq == [1, 3]
      l.remove l3
      doAssert l.toSeq == [1]
      l.remove l1
      doAssert l.toSeq == []
      # Cycle preservation
      var a = [10, 11, 12].toList
      a.addMoved a
      doAssert a.take(6) == @[10, 11, 12, 10, 11, 12]
      a.remove a.head.next
      doAssert a.take(6) == @[10, 12, 10, 12, 10, 12]
      a.remove a.head
      doAssert a.take(6) == @[12, 12, 12, 12, 12, 12]

  testCommon initSinglyLinkedList, toSinglyLinkedList
  testCommon initDoublyLinkedList, toDoublyLinkedList

  block remove: # return value check
    var l = [0, 1, 2, 3].toSinglyLinkedList
    let n = l.head.next.next
    doAssert l.remove(n) == true
    doAssert l.toSeq == [0, 1, 3]
    doAssert l.remove(n) == false
    doAssert l.toSeq == [0, 1, 3]
    doAssert l.remove(l.head) == true
    doAssert l.toSeq == [1, 3]
    doAssert l.remove(l.head.next) == true
    doAssert l.toSeq == [1]
    doAssert l.remove(l.head) == true
    doAssert l.toSeq == []

static: main()
main()