github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/parser/metadecoders/decoder_test.go (about) 1 // Copyright 2018 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package metadecoders 15 16 import ( 17 "reflect" 18 "testing" 19 20 qt "github.com/frankban/quicktest" 21 ) 22 23 func TestUnmarshalXML(t *testing.T) { 24 c := qt.New(t) 25 26 xmlDoc := `<?xml version="1.0" encoding="utf-8" standalone="yes"?> 27 <rss version="2.0" 28 xmlns:atom="http://www.w3.org/2005/Atom"> 29 <channel> 30 <title>Example feed</title> 31 <link>https://example.com/</link> 32 <description>Example feed</description> 33 <generator>Hugo -- gohugo.io</generator> 34 <language>en-us</language> 35 <copyright>Example</copyright> 36 <lastBuildDate>Fri, 08 Jan 2021 14:44:10 +0000</lastBuildDate> 37 <atom:link href="https://example.com/feed.xml" rel="self" type="application/rss+xml"/> 38 <item> 39 <title>Example title</title> 40 <link>https://example.com/2021/11/30/example-title/</link> 41 <pubDate>Tue, 30 Nov 2021 15:00:00 +0000</pubDate> 42 <guid>https://example.com/2021/11/30/example-title/</guid> 43 <description>Example description</description> 44 </item> 45 </channel> 46 </rss>` 47 48 expect := map[string]any{ 49 "-atom": "http://www.w3.org/2005/Atom", "-version": "2.0", 50 "channel": map[string]any{ 51 "copyright": "Example", 52 "description": "Example feed", 53 "generator": "Hugo -- gohugo.io", 54 "item": map[string]any{ 55 "description": "Example description", 56 "guid": "https://example.com/2021/11/30/example-title/", 57 "link": "https://example.com/2021/11/30/example-title/", 58 "pubDate": "Tue, 30 Nov 2021 15:00:00 +0000", 59 "title": "Example title"}, 60 "language": "en-us", 61 "lastBuildDate": "Fri, 08 Jan 2021 14:44:10 +0000", 62 "link": []any{"https://example.com/", map[string]any{ 63 "-href": "https://example.com/feed.xml", 64 "-rel": "self", 65 "-type": "application/rss+xml"}}, 66 "title": "Example feed", 67 }} 68 69 d := Default 70 71 m, err := d.Unmarshal([]byte(xmlDoc), XML) 72 c.Assert(err, qt.IsNil) 73 c.Assert(m, qt.DeepEquals, expect) 74 75 } 76 func TestUnmarshalToMap(t *testing.T) { 77 c := qt.New(t) 78 79 expect := map[string]any{"a": "b"} 80 81 d := Default 82 83 for i, test := range []struct { 84 data string 85 format Format 86 expect any 87 }{ 88 {`a = "b"`, TOML, expect}, 89 {`a: "b"`, YAML, expect}, 90 // Make sure we get all string keys, even for YAML 91 {"a: Easy!\nb:\n c: 2\n d: [3, 4]", YAML, map[string]any{"a": "Easy!", "b": map[string]any{"c": 2, "d": []any{3, 4}}}}, 92 {"a:\n true: 1\n false: 2", YAML, map[string]any{"a": map[string]any{"true": 1, "false": 2}}}, 93 {`{ "a": "b" }`, JSON, expect}, 94 {`<root><a>b</a></root>`, XML, expect}, 95 {`#+a: b`, ORG, expect}, 96 // errors 97 {`a = b`, TOML, false}, 98 {`a,b,c`, CSV, false}, // Use Unmarshal for CSV 99 } { 100 msg := qt.Commentf("%d: %s", i, test.format) 101 m, err := d.UnmarshalToMap([]byte(test.data), test.format) 102 if b, ok := test.expect.(bool); ok && !b { 103 c.Assert(err, qt.Not(qt.IsNil), msg) 104 } else { 105 c.Assert(err, qt.IsNil, msg) 106 c.Assert(m, qt.DeepEquals, test.expect, msg) 107 } 108 } 109 } 110 111 func TestUnmarshalToInterface(t *testing.T) { 112 c := qt.New(t) 113 114 expect := map[string]any{"a": "b"} 115 116 d := Default 117 118 for i, test := range []struct { 119 data []byte 120 format Format 121 expect any 122 }{ 123 {[]byte(`[ "Brecker", "Blake", "Redman" ]`), JSON, []any{"Brecker", "Blake", "Redman"}}, 124 {[]byte(`{ "a": "b" }`), JSON, expect}, 125 {[]byte(``), JSON, map[string]any{}}, 126 {[]byte(nil), JSON, map[string]any{}}, 127 {[]byte(`#+a: b`), ORG, expect}, 128 {[]byte(`#+DATE: <2020-06-26 Fri>`), ORG, map[string]any{"date": "2020-06-26"}}, 129 {[]byte(`#+LASTMOD: <2020-06-26 Fri>`), ORG, map[string]any{"lastmod": "2020-06-26"}}, 130 {[]byte(`#+PUBLISHDATE: <2020-06-26 Fri>`), ORG, map[string]any{"publishdate": "2020-06-26"}}, 131 {[]byte(`#+EXPIRYDATE: <2020-06-26 Fri>`), ORG, map[string]any{"expirydate": "2020-06-26"}}, 132 {[]byte(`a = "b"`), TOML, expect}, 133 {[]byte(`a: "b"`), YAML, expect}, 134 {[]byte(`<root><a>b</a></root>`), XML, expect}, 135 {[]byte(`a,b,c`), CSV, [][]string{{"a", "b", "c"}}}, 136 {[]byte("a: Easy!\nb:\n c: 2\n d: [3, 4]"), YAML, map[string]any{"a": "Easy!", "b": map[string]any{"c": 2, "d": []any{3, 4}}}}, 137 // errors 138 {[]byte(`a = "`), TOML, false}, 139 } { 140 msg := qt.Commentf("%d: %s", i, test.format) 141 m, err := d.Unmarshal(test.data, test.format) 142 if b, ok := test.expect.(bool); ok && !b { 143 c.Assert(err, qt.Not(qt.IsNil), msg) 144 } else { 145 c.Assert(err, qt.IsNil, msg) 146 c.Assert(m, qt.DeepEquals, test.expect, msg) 147 } 148 149 } 150 } 151 152 func TestUnmarshalStringTo(t *testing.T) { 153 c := qt.New(t) 154 155 d := Default 156 157 expectMap := map[string]any{"a": "b"} 158 159 for i, test := range []struct { 160 data string 161 to any 162 expect any 163 }{ 164 {"a string", "string", "a string"}, 165 {`{ "a": "b" }`, make(map[string]any), expectMap}, 166 {"32", int64(1234), int64(32)}, 167 {"32", int(1234), int(32)}, 168 {"3.14159", float64(1), float64(3.14159)}, 169 {"[3,7,9]", []any{}, []any{3, 7, 9}}, 170 {"[3.1,7.2,9.3]", []any{}, []any{3.1, 7.2, 9.3}}, 171 } { 172 msg := qt.Commentf("%d: %T", i, test.to) 173 m, err := d.UnmarshalStringTo(test.data, test.to) 174 if b, ok := test.expect.(bool); ok && !b { 175 c.Assert(err, qt.Not(qt.IsNil), msg) 176 } else { 177 c.Assert(err, qt.IsNil, msg) 178 c.Assert(m, qt.DeepEquals, test.expect, msg) 179 } 180 181 } 182 } 183 184 func TestStringifyYAMLMapKeys(t *testing.T) { 185 cases := []struct { 186 input any 187 want any 188 replaced bool 189 }{ 190 { 191 map[any]any{"a": 1, "b": 2}, 192 map[string]any{"a": 1, "b": 2}, 193 true, 194 }, 195 { 196 map[any]any{"a": []any{1, map[any]any{"b": 2}}}, 197 map[string]any{"a": []any{1, map[string]any{"b": 2}}}, 198 true, 199 }, 200 { 201 map[any]any{true: 1, "b": false}, 202 map[string]any{"true": 1, "b": false}, 203 true, 204 }, 205 { 206 map[any]any{1: "a", 2: "b"}, 207 map[string]any{"1": "a", "2": "b"}, 208 true, 209 }, 210 { 211 map[any]any{"a": map[any]any{"b": 1}}, 212 map[string]any{"a": map[string]any{"b": 1}}, 213 true, 214 }, 215 { 216 map[string]any{"a": map[string]any{"b": 1}}, 217 map[string]any{"a": map[string]any{"b": 1}}, 218 false, 219 }, 220 { 221 []any{map[any]any{1: "a", 2: "b"}}, 222 []any{map[string]any{"1": "a", "2": "b"}}, 223 false, 224 }, 225 } 226 227 for i, c := range cases { 228 res, replaced := stringifyMapKeys(c.input) 229 230 if c.replaced != replaced { 231 t.Fatalf("[%d] Replaced mismatch: %t", i, replaced) 232 } 233 if !c.replaced { 234 res = c.input 235 } 236 if !reflect.DeepEqual(res, c.want) { 237 t.Errorf("[%d] given %q\nwant: %q\n got: %q", i, c.input, c.want, res) 238 } 239 } 240 } 241 242 func BenchmarkStringifyMapKeysStringsOnlyInterfaceMaps(b *testing.B) { 243 maps := make([]map[any]any, b.N) 244 for i := 0; i < b.N; i++ { 245 maps[i] = map[any]any{ 246 "a": map[any]any{ 247 "b": 32, 248 "c": 43, 249 "d": map[any]any{ 250 "b": 32, 251 "c": 43, 252 }, 253 }, 254 "b": []any{"a", "b"}, 255 "c": "d", 256 } 257 } 258 b.ResetTimer() 259 for i := 0; i < b.N; i++ { 260 stringifyMapKeys(maps[i]) 261 } 262 } 263 264 func BenchmarkStringifyMapKeysStringsOnlyStringMaps(b *testing.B) { 265 m := map[string]any{ 266 "a": map[string]any{ 267 "b": 32, 268 "c": 43, 269 "d": map[string]any{ 270 "b": 32, 271 "c": 43, 272 }, 273 }, 274 "b": []any{"a", "b"}, 275 "c": "d", 276 } 277 278 b.ResetTimer() 279 for i := 0; i < b.N; i++ { 280 stringifyMapKeys(m) 281 } 282 } 283 284 func BenchmarkStringifyMapKeysIntegers(b *testing.B) { 285 maps := make([]map[any]any, b.N) 286 for i := 0; i < b.N; i++ { 287 maps[i] = map[any]any{ 288 1: map[any]any{ 289 4: 32, 290 5: 43, 291 6: map[any]any{ 292 7: 32, 293 8: 43, 294 }, 295 }, 296 2: []any{"a", "b"}, 297 3: "d", 298 } 299 } 300 b.ResetTimer() 301 for i := 0; i < b.N; i++ { 302 stringifyMapKeys(maps[i]) 303 } 304 }