1// Copyright 2015 Jean Niklas L'orange. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package edn 6 7import ( 8 "bytes" 9 "testing" 10) 11 12func TestEncoding(t *testing.T) { 13 testEncode(t, Keyword("foo"), ":foo") 14 testEncode(t, Symbol("foo"), "foo") 15 testEncode(t, "foo", `"foo"`) 16 17 testEncode(t, 1, "1") 18 testEncode(t, -1.2, "-1.2") 19 testEncode(t, 3.0, "3.0") 20 testEncode(t, 10E12, "1e+13") 21 22 var val interface{} 23 24 val = struct { 25 Foo int `edn:"quux"` 26 }{10} 27 testEncode(t, val, "{:quux 10}") 28 29 val = struct { 30 Bar [2]int `edn:",sym,list"` 31 }{[2]int{3, 4}} 32 testEncode(t, val, "{bar(3 4)}") 33 34 val = struct { 35 Comp string `edn:",str"` 36 }{"ressed"} 37 testEncode(t, val, `{"comp""ressed"}`) 38 39 val = struct { 40 TheSet [2]int `edn:"the-set,set,sym"` 41 Slice []string `edn:",set"` 42 }{ 43 [2]int{3, 4}, 44 []string{"foo", "bar"}, 45 } 46 testEncode(t, val, `{the-set #{3 4}:slice #{"foo""bar"}}`) 47 48 val = map[float64]struct{}{ 49 1.0: {}, 50 } 51 testEncode(t, val, `#{1.0}`) 52 53 val = Tag{ 54 Tagname: "floatset", 55 Value: map[float64]struct{}{ 56 1.0: {}, 57 }, 58 } 59 testEncode(t, val, `#floatset #{1.0}`) 60 61 val = Tag{ 62 Tagname: "some/tag", 63 Value: 1, 64 } 65 testEncode(t, val, `#some/tag 1`) 66 67 val = Tag{ 68 Tagname: "some/tag", 69 Value: struct{ X int }{1}, 70 } 71 testEncode(t, val, `#some/tag{:x 1}`) 72 73 val = Tag{ 74 Tagname: "a", 75 Value: Tag{ 76 Tagname: "b", 77 Value: Tag{ 78 Tagname: "c", 79 Value: nil, 80 }, 81 }, 82 } 83 testEncode(t, val, `#a #b #c nil`) 84 85 val = Tag{ 86 Tagname: "a", 87 Value: Tag{ 88 Tagname: "b", 89 Value: 1, 90 }, 91 } 92 testEncode(t, val, `#a #b 1`) 93 94 val = Tag{ 95 Tagname: "a", 96 Value: Tag{ 97 Tagname: "b", 98 Value: "c", 99 }, 100 } 101 testEncode(t, val, `#a #b"c"`) 102 103 val = Tag{ 104 Tagname: "a", 105 Value: []int{1}, 106 } 107 testEncode(t, val, `#a[1]`) 108 109 val = Tag{ 110 Tagname: "a", 111 Value: Tag{ 112 Tagname: "b", 113 Value: []int{1}, 114 }, 115 } 116 testEncode(t, val, `#a #b[1]`) 117 118 val = Tag{ 119 Tagname: "some/tag", 120 Value: Tag{ 121 Tagname: "inner", 122 Value: struct{ X int }{1}, 123 }, 124 } 125 testEncode(t, val, `#some/tag #inner{:x 1}`) 126 127 val = A{} 128 testEncode(t, val, `#tag/a{:x 1}`) 129 130 val = Tag{ 131 Tagname: "outer", 132 Value: A{}, 133 } 134 testEncode(t, val, `#outer #tag/a{:x 1}`) 135} 136 137func testEncode(t *testing.T, val interface{}, expects string) { 138 bs, err := Marshal(val) 139 if err != nil { 140 t.Errorf("Unexpected error marshalling %q: %s", val, err.Error()) 141 } else if !bytes.Equal([]byte(expects), bs) { 142 t.Errorf("Expected to see '%s', but got '%s' instead", expects, string(bs)) 143 } 144} 145 146type A struct{} 147 148func (a A) MarshalEDN() ([]byte, error) { 149 t := Tag{ 150 Tagname: "tag/a", 151 Value: struct{ X int }{1}, 152 } 153 return Marshal(t) 154} 155 156func TestJSONEncoding(t *testing.T) { 157 jsonOnly := struct { 158 Data string `json:"json"` 159 }{Data: "hi"} 160 jsonAndEdn := struct { 161 Data string `json:"json" edn:"edn"` 162 }{Data: "hi"} 163 164 UseJSONAsFallback(false) 165 testEncode(t, jsonOnly, `{:data"hi"}`) 166 testEncode(t, jsonAndEdn, `{:edn"hi"}`) 167 168 UseJSONAsFallback(true) 169 testEncode(t, jsonOnly, `{:json"hi"}`) 170 testEncode(t, jsonAndEdn, `{:edn"hi"}`) 171 172 UseJSONAsFallback(false) 173 testEncode(t, jsonOnly, `{:data"hi"}`) 174 testEncode(t, jsonAndEdn, `{:edn"hi"}`) 175} 176