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  }