summary refs log tree commit diff stats
path: root/tests/stdlib/tlists.nim
blob: 5993278c79e2cc6b3821004f3cd1aea9755a463c (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
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD
discard """
  matrix: "--mm:refc; --mm:orc"
  targets: "c js"
"""

import std/[lists, sequtils]
import std/assertions

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 == []
  
  block issue19297: # add (appends a shallow copy)
    var a: SinglyLinkedList[int]
    var b: SinglyLinkedList[int]

    doAssert a.toSeq == @[]
    a.add(1)
    doAssert a.toSeq == @[1]
    a.add(b)
    doAssert a.toSeq == @[1]
    a.add(2)
    doAssert a.toSeq == @[1, 2]
  
  block issue19314: # add (appends a shallow copy)
    var a: DoublyLinkedList[int]
    var b: DoublyLinkedList[int]

    doAssert a.toSeq == @[]
    a.add(1)
    doAssert a.toSeq == @[1]
    a.add(b)
    doAssert a.toSeq == @[1]
    a.add(2)
    doAssert a.toSeq == @[1, 2]

  block RemoveLastNodeFromSinglyLinkedList:
    var list = initSinglyLinkedList[string]()
    let n1 = newSinglyLinkedNode("sonic")
    let n2 = newSinglyLinkedNode("the")
    let n3 = newSinglyLinkedNode("tiger")
    let n4 = newSinglyLinkedNode("hedgehog")
    list.add(n1)
    list.add(n2)
    list.add(n3)
    list.remove(n3)
    list.add(n4)
    doAssert list.toSeq == @["sonic", "the", "hedgehog"]

static: main()
main()