hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

decoder_test.go (7539B)

    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   string
  120 		format Format
  121 		expect any
  122 	}{
  123 		{`[ "Brecker", "Blake", "Redman" ]`, JSON, []any{"Brecker", "Blake", "Redman"}},
  124 		{`{ "a": "b" }`, JSON, expect},
  125 		{`#+a: b`, ORG, expect},
  126 		{`#+DATE: <2020-06-26 Fri>`, ORG, map[string]any{"date": "2020-06-26"}},
  127 		{`a = "b"`, TOML, expect},
  128 		{`a: "b"`, YAML, expect},
  129 		{`<root><a>b</a></root>`, XML, expect},
  130 		{`a,b,c`, CSV, [][]string{{"a", "b", "c"}}},
  131 		{"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}}}},
  132 		// errors
  133 		{`a = "`, TOML, false},
  134 	} {
  135 		msg := qt.Commentf("%d: %s", i, test.format)
  136 		m, err := d.Unmarshal([]byte(test.data), test.format)
  137 		if b, ok := test.expect.(bool); ok && !b {
  138 			c.Assert(err, qt.Not(qt.IsNil), msg)
  139 		} else {
  140 			c.Assert(err, qt.IsNil, msg)
  141 			c.Assert(m, qt.DeepEquals, test.expect, msg)
  142 		}
  143 
  144 	}
  145 }
  146 
  147 func TestUnmarshalStringTo(t *testing.T) {
  148 	c := qt.New(t)
  149 
  150 	d := Default
  151 
  152 	expectMap := map[string]any{"a": "b"}
  153 
  154 	for i, test := range []struct {
  155 		data   string
  156 		to     any
  157 		expect any
  158 	}{
  159 		{"a string", "string", "a string"},
  160 		{`{ "a": "b" }`, make(map[string]any), expectMap},
  161 		{"32", int64(1234), int64(32)},
  162 		{"32", int(1234), int(32)},
  163 		{"3.14159", float64(1), float64(3.14159)},
  164 		{"[3,7,9]", []any{}, []any{3, 7, 9}},
  165 		{"[3.1,7.2,9.3]", []any{}, []any{3.1, 7.2, 9.3}},
  166 	} {
  167 		msg := qt.Commentf("%d: %T", i, test.to)
  168 		m, err := d.UnmarshalStringTo(test.data, test.to)
  169 		if b, ok := test.expect.(bool); ok && !b {
  170 			c.Assert(err, qt.Not(qt.IsNil), msg)
  171 		} else {
  172 			c.Assert(err, qt.IsNil, msg)
  173 			c.Assert(m, qt.DeepEquals, test.expect, msg)
  174 		}
  175 
  176 	}
  177 }
  178 
  179 func TestStringifyYAMLMapKeys(t *testing.T) {
  180 	cases := []struct {
  181 		input    any
  182 		want     any
  183 		replaced bool
  184 	}{
  185 		{
  186 			map[any]any{"a": 1, "b": 2},
  187 			map[string]any{"a": 1, "b": 2},
  188 			true,
  189 		},
  190 		{
  191 			map[any]any{"a": []any{1, map[any]any{"b": 2}}},
  192 			map[string]any{"a": []any{1, map[string]any{"b": 2}}},
  193 			true,
  194 		},
  195 		{
  196 			map[any]any{true: 1, "b": false},
  197 			map[string]any{"true": 1, "b": false},
  198 			true,
  199 		},
  200 		{
  201 			map[any]any{1: "a", 2: "b"},
  202 			map[string]any{"1": "a", "2": "b"},
  203 			true,
  204 		},
  205 		{
  206 			map[any]any{"a": map[any]any{"b": 1}},
  207 			map[string]any{"a": map[string]any{"b": 1}},
  208 			true,
  209 		},
  210 		{
  211 			map[string]any{"a": map[string]any{"b": 1}},
  212 			map[string]any{"a": map[string]any{"b": 1}},
  213 			false,
  214 		},
  215 		{
  216 			[]any{map[any]any{1: "a", 2: "b"}},
  217 			[]any{map[string]any{"1": "a", "2": "b"}},
  218 			false,
  219 		},
  220 	}
  221 
  222 	for i, c := range cases {
  223 		res, replaced := stringifyMapKeys(c.input)
  224 
  225 		if c.replaced != replaced {
  226 			t.Fatalf("[%d] Replaced mismatch: %t", i, replaced)
  227 		}
  228 		if !c.replaced {
  229 			res = c.input
  230 		}
  231 		if !reflect.DeepEqual(res, c.want) {
  232 			t.Errorf("[%d] given %q\nwant: %q\n got: %q", i, c.input, c.want, res)
  233 		}
  234 	}
  235 }
  236 
  237 func BenchmarkStringifyMapKeysStringsOnlyInterfaceMaps(b *testing.B) {
  238 	maps := make([]map[any]any, b.N)
  239 	for i := 0; i < b.N; i++ {
  240 		maps[i] = map[any]any{
  241 			"a": map[any]any{
  242 				"b": 32,
  243 				"c": 43,
  244 				"d": map[any]any{
  245 					"b": 32,
  246 					"c": 43,
  247 				},
  248 			},
  249 			"b": []any{"a", "b"},
  250 			"c": "d",
  251 		}
  252 	}
  253 	b.ResetTimer()
  254 	for i := 0; i < b.N; i++ {
  255 		stringifyMapKeys(maps[i])
  256 	}
  257 }
  258 
  259 func BenchmarkStringifyMapKeysStringsOnlyStringMaps(b *testing.B) {
  260 	m := map[string]any{
  261 		"a": map[string]any{
  262 			"b": 32,
  263 			"c": 43,
  264 			"d": map[string]any{
  265 				"b": 32,
  266 				"c": 43,
  267 			},
  268 		},
  269 		"b": []any{"a", "b"},
  270 		"c": "d",
  271 	}
  272 
  273 	b.ResetTimer()
  274 	for i := 0; i < b.N; i++ {
  275 		stringifyMapKeys(m)
  276 	}
  277 }
  278 
  279 func BenchmarkStringifyMapKeysIntegers(b *testing.B) {
  280 	maps := make([]map[any]any, b.N)
  281 	for i := 0; i < b.N; i++ {
  282 		maps[i] = map[any]any{
  283 			1: map[any]any{
  284 				4: 32,
  285 				5: 43,
  286 				6: map[any]any{
  287 					7: 32,
  288 					8: 43,
  289 				},
  290 			},
  291 			2: []any{"a", "b"},
  292 			3: "d",
  293 		}
  294 	}
  295 	b.ResetTimer()
  296 	for i := 0; i < b.N; i++ {
  297 		stringifyMapKeys(maps[i])
  298 	}
  299 }