summary refs log tree commit diff stats
path: root/tests/stdlib/tjsonmacro.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/stdlib/tjsonmacro.nim')
-rw-r--r--tests/stdlib/tjsonmacro.nim212
1 files changed, 152 insertions, 60 deletions
diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim
index 0521d558c..5a1b4b294 100644
--- a/tests/stdlib/tjsonmacro.nim
+++ b/tests/stdlib/tjsonmacro.nim
@@ -1,27 +1,45 @@
 discard """
   output: ""
+  matrix: "--mm:refc; --mm:orc"
+  targets: "c js"
 """
-import json, strutils, options, tables
 
-when true:
+import json, strutils, options, tables
+import std/assertions
+
+# The definition of the `%` proc needs to be here, since the `% c` calls below
+# can only find our custom `%` proc for `Pix` if defined in global scope.
+type
+  Pix = tuple[x, y: uint8, ch: uint16]
+proc `%`(p: Pix): JsonNode =
+  result = %* { "x" : % p.x,
+                "y" : % p.y,
+                "ch" : % p.ch }
+
+proc testJson() =
   # Tests inspired by own use case (with some additional tests).
   # This should succeed.
   type
     Point[T] = object
       x, y: T
 
-    ReplayEventKind* = enum
+    ReplayEventKind = enum
       FoodAppeared, FoodEaten, DirectionChanged
 
-    ReplayEvent* = object
+    ReplayEvent = object
       time*: float
       case kind*: ReplayEventKind
       of FoodAppeared, FoodEaten:
         foodPos*: Point[float]
+        case subKind*: bool
+        of true:
+          it: int
+        of false:
+          ot: float
       of DirectionChanged:
         playerPos*: float
 
-    Replay* = ref object
+    Replay = ref object
       events*: seq[ReplayEvent]
       test: int
       test2: string
@@ -33,7 +51,9 @@ when true:
       ReplayEvent(
         time: 1.2345,
         kind: FoodEaten,
-        foodPos: Point[float](x: 5.0, y: 1.0)
+        foodPos: Point[float](x: 5.0, y: 1.0),
+        subKind: true,
+        it: 7
       )
     ],
     test: 18827361,
@@ -90,7 +110,7 @@ when true:
     doAssert result.other == node["other"].getBiggestInt()
 
   # TODO: Test object variant with set in of branch.
-  # TODO: Should we support heterogenous arrays?
+  # TODO: Should we support heterogeneous arrays?
 
   # Tests that verify the error messages for invalid data.
   block:
@@ -241,7 +261,7 @@ when true:
         colors: array[2, BirdColor]
 
     var red = BirdColor(name: "red", rgb: [1.0, 0.0, 0.0])
-    var blue = Birdcolor(name: "blue", rgb: [0.0, 0.0, 1.0])
+    var blue = BirdColor(name: "blue", rgb: [0.0, 0.0, 1.0])
     var b = Bird(age: 3, height: 1.734, name: "bardo", colors: [red, blue])
     let jnode = %b
     let data = jnode.to(Bird)
@@ -277,24 +297,26 @@ when true:
     doAssert parsed.color == Red
 
   block:
-    type
-      Car = object
-        engine: tuple[name: string, capacity: float]
-        model: string
+    when not defined(js):
+      # disable on js because of #12492
+      type
+        Car = object
+          engine: tuple[name: string, capacity: float]
+          model: string
 
-    let j = """
-      {"engine": {"name": "V8", "capacity": 5.5}, "model": "Skyline"}
-    """
+      let j = """
+        {"engine": {"name": "V8", "capacity": 5.5}, "model": "Skyline"}
+      """
 
-    var i = 0
-    proc mulTest: JsonNode =
-      i.inc()
-      return parseJson(j)
+      var i = 0
+      proc mulTest(): JsonNode =
+        inc i
+        return parseJson(j)
 
-    let parsed = mulTest().to(Car)
-    doAssert parsed.engine.name == "V8"
+      let parsed = mulTest().to(Car)
+      doAssert parsed.engine.name == "V8"
 
-    doAssert i == 1
+      doAssert i == 1
 
   block:
     # Option[T] support!
@@ -471,8 +493,9 @@ when true:
     doAssert Table[string,int](t.dict)["a"] == 1
     doAssert Table[string,int](t.dict)["b"] == 2
     doAssert array[3, float](t.arr) == [1.0,2.0,7.0]
+
     doAssert MyRef(t.person).name == "boney"
-    doAssert MyObj(t.distFruit).color == 11
+    doAssert MyObj(t.distfruit).color == 11
     doAssert t.dog.name == "honey"
     doAssert t.fruit.color == 10
     doAssert seq[string](t.emails) == @["abc", "123"]
@@ -517,42 +540,111 @@ when true:
       doAssert v.name == "smith"
       doAssert MyRef(w).name == "smith"
 
-# TODO: when the issue with the limeted vm registers is solved, the
-# exact same test as above should be evaluated at compile time as
-# well, to ensure that the vm functionality won't diverge from the
-# runtime functionality. Until then, the following test should do it.
+  block:
+    # bug #12015
+    type
+      Cluster = object
+        works: tuple[x, y: uint8, ch: uint16] # working
+        fails: Pix # previously broken
+
+    let data = (x: 123'u8, y: 53'u8, ch: 1231'u16)
+    let c = Cluster(works: data, fails: data)
+    let cFromJson = (% c).to(Cluster)
+    doAssert c == cFromJson
 
+  block:
+    # bug related to #12015
+    type
+      PixInt = tuple[x, y, ch: int]
+      SomePix = Pix | PixInt
+      Cluster[T: SomePix] = seq[T]
+      ClusterObject[T: SomePix] = object
+        data: Cluster[T]
+      RecoEvent[T: SomePix] = object
+        cluster: seq[ClusterObject[T]]
+
+    let data = @[(x: 123'u8, y: 53'u8, ch: 1231'u16)]
+    var c = RecoEvent[Pix](cluster: @[ClusterObject[Pix](data: data)])
+    let cFromJson = (% c).to(RecoEvent[Pix])
+    doAssert c == cFromJson
+
+
+  block:
+    # ref objects with cycles.
+    type
+      Misdirection = object
+        cycle: Cycle
+
+      Cycle = ref object
+        foo: string
+        cycle: Misdirection
+
+    let data = """
+      {"cycle": null}
+    """
+
+    let dataParsed = parseJson(data)
+    let dataDeser = to(dataParsed, Misdirection)
+
+  block:
+    # ref object from #12316
+    type
+      Foo = ref Bar
+      Bar = object
+
+    discard "null".parseJson.to Foo
+
+  block:
+    # named array #12289
+    type Vec = array[2, int]
+    let arr = "[1,2]".parseJson.to Vec
+    doAssert arr == [1,2]
+
+  block:
+    # test error message in exception
+
+    type
+      MyType = object
+        otherMember: string
+        member: MySubType
+
+      MySubType = object
+        somethingElse: string
+        list: seq[MyData]
+
+      MyData = object
+        value: int
+
+    let jsonNode = parseJson("""
+      {
+        "otherMember": "otherValue",
+        "member": {
+          "somethingElse": "something",
+          "list": [{"value": 1}, {"value": 2}, {}]
+        }
+      }
+    """)
+
+    try:
+      let tmp = jsonNode.to(MyType)
+      doAssert false, "this should be unreachable"
+    except KeyError:
+      doAssert getCurrentExceptionMsg().contains ".member.list[2].value"
+
+  block:
+    # Enum indexed array test
+    type Test = enum
+      one, two, three, four, five
+    let a = [
+      one: 300,
+      two: 20,
+      three: 10,
+      four: 0,
+      five: -10
+    ]
+    doAssert (%* a).to(a.typeof) == a
+
+
+testJson()
 static:
-  var t = parseJson("""
-    {
-      "name":"Bongo",
-      "email":"bongo@bingo.com",
-      "list": [11,7,15],
-      "year": 1975,
-      "dict": {"a": 1, "b": 2},
-      "arr": [1.0, 2.0, 7.0],
-      "person": {"name": "boney"},
-      "dog": {"name": "honey"},
-      "fruit": {"color": 10},
-      "distfruit": {"color": 11},
-      "emails": ["abc", "123"]
-    }
-  """)
-
-  doAssert t["name"].getStr == "Bongo"
-  doAssert t["email"].getStr == "bongo@bingo.com"
-  doAssert t["list"][0].getInt == 11
-  doAssert t["list"][1].getInt == 7
-  doAssert t["list"][2].getInt == 15
-  doAssert t["year"].getInt == 1975
-  doAssert t["dict"]["a"].getInt == 1
-  doAssert t["dict"]["b"].getInt == 2
-  doAssert t["arr"][0].getFloat == 1.0
-  doAssert t["arr"][1].getFloat == 2.0
-  doAssert t["arr"][2].getFloat == 7.0
-  doAssert t["person"]["name"].getStr == "boney"
-  doAssert t["distfruit"]["color"].getInt == 11
-  doAssert t["dog"]["name"].getStr == "honey"
-  doAssert t["fruit"]["color"].getInt == 10
-  doAssert t["emails"][0].getStr == "abc"
-  doAssert t["emails"][1].getStr == "123"
+  testJson()