test.nim
1 # To run these tests, simply execute `nimble test`. 2 3 import unittest 4 import edn, options, tables, strutils 5 6 # need to re-structure this at some point 7 test "everything": 8 var node: EdnNode 9 10 node = read(" nil") 11 check node.kind == EdnNil 12 13 node = read("10") 14 check node.kind == EdnInt 15 check node.num == 10 16 17 node = read("10e10") 18 check node.kind == EdnFloat 19 check node.fnum == 10e10 20 21 node = read("+5.0E5") 22 check node.kind == EdnFloat 23 check node.fnum == +5.0E5 24 25 node = read("true") 26 check node.kind == EdnBool 27 check node.boolVal == true 28 29 node = read("1 2 3") 30 check node.kind == EdnInt 31 check node.num == 1 32 33 node = read("(1 2 3)") 34 check node.kind == EdnList 35 check node.list.len == 3 36 37 node = read("""( 38 ;; comment in a list 39 )""") 40 check node.kind == EdnList 41 check node.comments.len == 0 42 43 block: 44 # comment related tests 45 46 var opts: ParseOptions 47 opts.eof_is_error = true 48 opts.suppress_read = false 49 opts.conditional_exprs = asError 50 opts.comments_handling = keepComments 51 node = read(""";; this is a coment 52 () 53 """, opts) 54 check node.kind == EdnCommentLine 55 check node.comments.len == 0 56 57 node = read("""( 58 ;; this is a coment 59 ()) 60 """, opts) 61 check node.kind == EdnList 62 check node.list[0].comments.len > 0 63 64 node = read(""";; this is a comment 65 (1 2 66 ;; last elem 67 3)""", opts) 68 check node.kind == EdnCommentLine 69 70 # the comment should be returned on subsequent read(). 71 # not very clean, but does not require a look-ahead read() 72 node = read("""() 73 ;; comment after a list""", opts) 74 check node.kind == EdnList 75 check node.comments.len == 0 76 77 node = read("""( 78 ;; comment in a list 79 )""", opts) 80 check node.kind == EdnList 81 check node.comments.len == 1 82 check node.comments[0].placement == Inside 83 84 node = read(""";; this is a comment 85 (1 2 86 ;; last elem 87 3)""", opts) 88 check node.kind == EdnCommentLine 89 check node.comments.len == 0 90 91 node = read("""{:x 1 92 ;;comment 93 :y 2} """, opts) 94 check node.kind == EdnMap 95 96 node = read("""{:view s/Keyword 97 ;;comment 98 (s/optional-key :label) s/Str 99 (foo 1) 2} """, opts) 100 check node.kind == EdnMap 101 102 103 node = read("""{:view s/Keyword 104 ;;comment 105 (s/optional-key :label) s/Str 106 (foo 1) 2} """) 107 check node.kind == EdnMap 108 109 node = read(""";; this is a comment 110 (1 2 111 ;; last elem 112 3)""") 113 check node.kind == EdnList 114 check node.comments.len == 0 115 check node.list[2].comments.len == 0 116 117 node = read("1") 118 check node.kind == EdnInt 119 check node.num == 1 120 121 node = read("-1") 122 check node.kind == EdnInt 123 check node.num == -1 124 125 node = read("1M") 126 check node.kind == EdnInt #TODO: for now... 127 128 node = read("()") 129 check node.kind == EdnList 130 check node.list.len == 0 131 132 node = read("(())") 133 check node.kind == EdnList 134 check node.list.len == 1 135 check node.list[0].kind == EdnList 136 check node.list[0].list.len == 0 137 138 node = read("nil") 139 check node.kind == EdnNil 140 141 node = read("symbol-👋") #emoji 142 check node.kind == EdnSymbol 143 check node.symbol.name == "symbol-👋" 144 145 node = read(":foo") 146 check node.kind == EdnKeyword 147 check node.keyword.name == "foo" 148 check node.namespacing == NoNamespace 149 check $node == ":foo" 150 151 node = read("::foobar") 152 check node.kind == EdnKeyword 153 check node.keyword.name == "foobar" 154 check node.keyword.ns == "" 155 check node.namespacing == LocalNamespace 156 check $node == "::foobar" 157 158 node = read("+foo+") 159 check node.kind == EdnSymbol 160 check node.symbol.name == "+foo+" 161 162 node = read("moo/bar") 163 check node.kind == EdnSymbol 164 check node.symbol == ("moo", "bar") 165 166 node = read("'foo") # -> (quote foo) 167 check node.kind == EdnList 168 check node.list[0] == new_edn_symbol("", "quote") 169 170 node = read("{}") 171 check node.kind == EdnMap 172 check node.map.len == 0 173 174 node = read("{:A 1 :B 2}") 175 check node.kind == EdnMap 176 check node.map.len == 2 177 178 node = read("{:A 1, :B 2}") 179 check node.kind == EdnMap 180 check node.map.len == 2 181 182 node = read("{:x 1M :y 2}") 183 check node.kind == EdnMap 184 check node.map.len == 2 185 186 node = read("{:order_date #clj-time/date-time \"2019-12-01T00:00:00.000Z\", :quantity 125.3M, 1 1}") 187 check node.kind == EdnMap 188 check node.map.len == 3 189 190 try: 191 node = read("moo/bar/baz") 192 raise new_exception(Exception, "FAILURE") 193 except ParseError: 194 discard 195 196 node = read("[1 2 , 3,4]") 197 check node.kind == EdnVector 198 check node.vec.len == 4 199 200 node = read("^{:k 1} {}") 201 check node.kind == EdnMap 202 check node.map.count == 0 203 # TODO: define 'len' for HMap 204 check node.map_meta.count == 1 205 check node.map_meta[new_edn_keyword("", "k")].get() == new_edn_int(1) 206 207 let hh = new_hmap() 208 hh[new_edn_keyword("", "foo")] = edn_true 209 check hh[new_edn_keyword("", "foo")].get() == new_edn_bool(true) 210 211 node = read("^ :foo []") 212 check node.kind == EdnVector 213 check node.vec.len == 0 214 check node.vec_meta.count == 1 215 check node.vec_meta[new_edn_keyword("", "foo")].get() == new_edn_bool(true) 216 217 node = read("^foo (1 2 3)") 218 check node.kind == EdnList 219 check node.list.len == 3 220 check node.list_meta.count == 1 221 check node.list_meta[KeyTag].get() == new_edn_symbol("", "foo") 222 223 node = read("^{:x 1} #{1}") 224 check node.kind == EdnSet 225 check node.set_meta.count == 1 226 227 node = read("^\"foo\" Symbol") 228 check node.kind == EdnSymbol 229 check node.symbol == new_edn_symbol("", "Symbol").symbol 230 check node.symbol_meta[KeyTag].get().kind == EdnString 231 check node.symbol_meta[KeyTag].get().str == "foo" 232 233 node = read("\"foo\"") 234 check node.kind == EdnString 235 check node.str == "foo" 236 check node.str.len == 3 237 238 node = read("#_ [foo bar]") 239 check node == nil 240 241 node = read("#{foo whateve 1}") 242 check node.kind == EdnSet 243 check node.set_elems.count == 3 244 245 node = read("#{}") 246 check node.kind == EdnSet 247 check node.set_elems.count == 0 248 249 node = read("#:foo {:x 1}") 250 check node.kind == EdnMap 251 check node.map.count == 1 252 check node.map[new_edn_keyword("foo", "x")].get == new_edn_int(1) 253 254 node = read("1/2") 255 check node.kind == EdnRatio 256 check node.rnum == (BiggestInt(1), BiggestInt(2)) 257 258 node = read("{:ratio -1/2}") 259 check node.kind == EdnMap 260 check node.map[new_edn_keyword("", "ratio")].get == new_edn_ratio(-1, 2) 261 262 node = read("#foo.bar -1") 263 check node.kind == EdnTaggedValue 264 check node.value.kind == EdnInt 265 check node.value == new_edn_int(-1) 266 267 node = read("#foo.bar [1 2 \"balls\"]") 268 check node.kind == EdnTaggedValue 269 check node.value.kind == EdnVector 270 271 node = read("#(or % disabled)") 272 check node.kind == EdnList 273 274 # let's set up conditional forms reading 275 var opts: ParseOptions 276 opts.conditional_exprs = asTagged 277 init_edn_readers(opts) 278 279 # conditional compilation exprs 280 node = read("#+clj #{foo}") 281 check node.tag == ("", "+clj") 282 check node.kind == EdnTaggedValue 283 check node.value.kind == EdnSet 284 285 opts.conditional_exprs = cljSource 286 init_edn_readers(opts) 287 node = read("#+clj #{foo}") 288 check node.kind == EdnSet 289 node = read("#+cljs {}") 290 check node == nil 291 292 node = read("[1 2 #+cljs 3 4]") 293 check node.kind == EdnVector 294 check node.vec.len == 3 295 296 var opts1: ParseOptions 297 opts1.eof_is_error = true 298 opts1.suppress_read = false 299 opts1.conditional_exprs = cljSource 300 301 node = read("#?(:clj :x)", opts1) 302 check node.kind == EdnKeyword 303 304 node = read("#?(:cljs :x)", opts1) 305 check node == nil 306 307 try: 308 node = read("#?(:cljs :x :clj)", opts1) 309 check false 310 except ParseError: 311 discard 312 313 node = read("[1 2 #?(:clj 3)]", opts1) 314 check node.kind == EdnVector 315 check node.vec.len == 3 316 317 opts1.conditional_exprs = cljsSource 318 node = read("[1 2 #?(:clj 3)]", opts1) 319 check node.kind == EdnVector 320 check node.vec.len == 2 321 322 opts1.conditional_exprs = ignoreConditionals 323 node = read("#?@(:clj [:generator-fn tlsubs/subscriber-timeline-record-generator])", opts1) 324 check node == nil 325 326 opts1.conditional_exprs = cljSource 327 # this should splice the tuple into key & value of the map, 328 #so result should be a map with one entry in it. 329 node = read("{#?@(:clj [:generator-fn tlsubs/subscriber-timeline-record-generator])}", opts1) 330 check node.kind == EdnMap 331 check node.map[new_edn_keyword("", "generator-fn")].get().kind == EdnSymbol 332 333 try: 334 node = read("{:ratio 1/-2}") 335 check node.kind == EdnMap 336 except ParseError: 337 discard 338 339 try: 340 node = read(";; foo bar") 341 check false 342 except ParseError: 343 discard 344 345 node = read("\"\uffff\"") 346 check node.kind == EdnString 347 348 node = read("\\uffff") 349 check node.kind == EdnCharacter 350 351 node = read("()") # for the following to work 352 var n1: EdnNode = EdnNode(kind: EdnNil) 353 var n2: EdnNode = EdnNode(kind: EdnNil) 354 var n3: EdnNode = EdnNode(kind: EdnBool, boolVal: false) 355 var n4: EdnNode = EdnNode(kind: EdnBool, boolVal: false) 356 #echo "===? ", n1 == n2 357 var t = new_table[EdnNode,int]() 358 t[n3] = 3 359 #echo "COUNT OF ELEMS ", t.len, " ", n1.hash, " ", n2.hash, " ", n3.hash 360 t[n4] = 4 361 #echo "COUNT OF ELEMS ", t.len, " ", n1.hash, " ", n2.hash, " ", n3.hash 362 t[n4] = 5 363 #echo "COUNT OF ELEMS ", t.len, " ", n1.hash, " ", n2.hash, " ", n3.hash 364 365 var mm1 = new_hmap() 366 mm1[n2] = n2 367 mm1[node] = node 368 369 mm1 = new_hmap(0) 370 mm1[node] = node 371 check mm1.count == 1 372 mm1[n1] = n1 373 check mm1.count == 2 374 mm1[n1] = n2 375 check mm1.count == 2 376 for i in 1..10: 377 mm1[new_edn_int(i.int_to_str())] = new_edn_int(i.int_to_str()) 378 check mm1.count == 12 379 check mm1[n1].get() == n2 380 381 node = read("#\".*\"") 382 check node.kind == EdnRegex 383 384 node = read("#'some-ns/symbol") 385 check node.kind == EdnVarQuote 386 387