github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/tpl/transform/unmarshal_test.go (about)

     1  // Copyright 2019 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 transform
    15  
    16  import (
    17  	"fmt"
    18  	"math/rand"
    19  	"strings"
    20  	"testing"
    21  
    22  	"github.com/gohugoio/hugo/config"
    23  
    24  	"github.com/gohugoio/hugo/common/hugio"
    25  	"github.com/gohugoio/hugo/resources/resource"
    26  
    27  	"github.com/gohugoio/hugo/media"
    28  
    29  	qt "github.com/frankban/quicktest"
    30  )
    31  
    32  const (
    33  	testJSON = `
    34  	
    35  {
    36      "ROOT_KEY": {
    37          "title": "example glossary",
    38  		"GlossDiv": {
    39              "title": "S",
    40  			"GlossList": {
    41                  "GlossEntry": {
    42                      "ID": "SGML",
    43  					"SortAs": "SGML",
    44  					"GlossTerm": "Standard Generalized Markup Language",
    45  					"Acronym": "SGML",
    46  					"Abbrev": "ISO 8879:1986",
    47  					"GlossDef": {
    48                          "para": "A meta-markup language, used to create markup languages such as DocBook.",
    49  						"GlossSeeAlso": ["GML", "XML"]
    50                      },
    51  					"GlossSee": "markup"
    52                  }
    53              }
    54          }
    55      }
    56  }
    57  
    58  	`
    59  )
    60  
    61  var _ resource.ReadSeekCloserResource = (*testContentResource)(nil)
    62  
    63  type testContentResource struct {
    64  	content string
    65  	mime    media.Type
    66  
    67  	key string
    68  }
    69  
    70  func (t testContentResource) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
    71  	return hugio.NewReadSeekerNoOpCloserFromString(t.content), nil
    72  }
    73  
    74  func (t testContentResource) MediaType() media.Type {
    75  	return t.mime
    76  }
    77  
    78  func (t testContentResource) Key() string {
    79  	return t.key
    80  }
    81  
    82  func TestUnmarshal(t *testing.T) {
    83  	v := config.New()
    84  	ns := New(newDeps(v))
    85  	c := qt.New(t)
    86  
    87  	assertSlogan := func(m map[string]interface{}) {
    88  		c.Assert(m["slogan"], qt.Equals, "Hugo Rocks!")
    89  	}
    90  
    91  	for _, test := range []struct {
    92  		data    interface{}
    93  		options interface{}
    94  		expect  interface{}
    95  	}{
    96  		{`{ "slogan": "Hugo Rocks!" }`, nil, func(m map[string]interface{}) {
    97  			assertSlogan(m)
    98  		}},
    99  		{`slogan: "Hugo Rocks!"`, nil, func(m map[string]interface{}) {
   100  			assertSlogan(m)
   101  		}},
   102  		{`slogan = "Hugo Rocks!"`, nil, func(m map[string]interface{}) {
   103  			assertSlogan(m)
   104  		}},
   105  		{testContentResource{key: "r1", content: `slogan: "Hugo Rocks!"`, mime: media.YAMLType}, nil, func(m map[string]interface{}) {
   106  			assertSlogan(m)
   107  		}},
   108  		{testContentResource{key: "r1", content: `{ "slogan": "Hugo Rocks!" }`, mime: media.JSONType}, nil, func(m map[string]interface{}) {
   109  			assertSlogan(m)
   110  		}},
   111  		{testContentResource{key: "r1", content: `slogan = "Hugo Rocks!"`, mime: media.TOMLType}, nil, func(m map[string]interface{}) {
   112  			assertSlogan(m)
   113  		}},
   114  		{testContentResource{key: "r1", content: `1997,Ford,E350,"ac, abs, moon",3000.00
   115  1999,Chevy,"Venture ""Extended Edition""","",4900.00`, mime: media.CSVType}, nil, func(r [][]string) {
   116  			c.Assert(len(r), qt.Equals, 2)
   117  			first := r[0]
   118  			c.Assert(len(first), qt.Equals, 5)
   119  			c.Assert(first[1], qt.Equals, "Ford")
   120  		}},
   121  		{testContentResource{key: "r1", content: `a;b;c`, mime: media.CSVType}, map[string]interface{}{"delimiter": ";"}, func(r [][]string) {
   122  			c.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
   123  		}},
   124  		{"a,b,c", nil, func(r [][]string) {
   125  			c.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
   126  		}},
   127  		{"a;b;c", map[string]interface{}{"delimiter": ";"}, func(r [][]string) {
   128  			c.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
   129  		}},
   130  		{testContentResource{key: "r1", content: `
   131  % This is a comment
   132  a;b;c`, mime: media.CSVType}, map[string]interface{}{"DElimiter": ";", "Comment": "%"}, func(r [][]string) {
   133  			c.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
   134  		}},
   135  		// errors
   136  		{"thisisnotavaliddataformat", nil, false},
   137  		{testContentResource{key: "r1", content: `invalid&toml"`, mime: media.TOMLType}, nil, false},
   138  		{testContentResource{key: "r1", content: `unsupported: MIME"`, mime: media.CalendarType}, nil, false},
   139  		{"thisisnotavaliddataformat", nil, false},
   140  		{`{ notjson }`, nil, false},
   141  		{tstNoStringer{}, nil, false},
   142  	} {
   143  
   144  		ns.cache.Clear()
   145  
   146  		var args []interface{}
   147  
   148  		if test.options != nil {
   149  			args = []interface{}{test.options, test.data}
   150  		} else {
   151  			args = []interface{}{test.data}
   152  		}
   153  
   154  		result, err := ns.Unmarshal(args...)
   155  
   156  		if b, ok := test.expect.(bool); ok && !b {
   157  			c.Assert(err, qt.Not(qt.IsNil))
   158  		} else if fn, ok := test.expect.(func(m map[string]interface{})); ok {
   159  			c.Assert(err, qt.IsNil)
   160  			m, ok := result.(map[string]interface{})
   161  			c.Assert(ok, qt.Equals, true)
   162  			fn(m)
   163  		} else if fn, ok := test.expect.(func(r [][]string)); ok {
   164  			c.Assert(err, qt.IsNil)
   165  			r, ok := result.([][]string)
   166  			c.Assert(ok, qt.Equals, true)
   167  			fn(r)
   168  		} else {
   169  			c.Assert(err, qt.IsNil)
   170  			c.Assert(result, qt.Equals, test.expect)
   171  		}
   172  
   173  	}
   174  }
   175  
   176  func BenchmarkUnmarshalString(b *testing.B) {
   177  	v := config.New()
   178  	ns := New(newDeps(v))
   179  
   180  	const numJsons = 100
   181  
   182  	var jsons [numJsons]string
   183  	for i := 0; i < numJsons; i++ {
   184  		jsons[i] = strings.Replace(testJSON, "ROOT_KEY", fmt.Sprintf("root%d", i), 1)
   185  	}
   186  
   187  	b.ResetTimer()
   188  	for i := 0; i < b.N; i++ {
   189  		result, err := ns.Unmarshal(jsons[rand.Intn(numJsons)])
   190  		if err != nil {
   191  			b.Fatal(err)
   192  		}
   193  		if result == nil {
   194  			b.Fatal("no result")
   195  		}
   196  	}
   197  }
   198  
   199  func BenchmarkUnmarshalResource(b *testing.B) {
   200  	v := config.New()
   201  	ns := New(newDeps(v))
   202  
   203  	const numJsons = 100
   204  
   205  	var jsons [numJsons]testContentResource
   206  	for i := 0; i < numJsons; i++ {
   207  		key := fmt.Sprintf("root%d", i)
   208  		jsons[i] = testContentResource{key: key, content: strings.Replace(testJSON, "ROOT_KEY", key, 1), mime: media.JSONType}
   209  	}
   210  
   211  	b.ResetTimer()
   212  	for i := 0; i < b.N; i++ {
   213  		result, err := ns.Unmarshal(jsons[rand.Intn(numJsons)])
   214  		if err != nil {
   215  			b.Fatal(err)
   216  		}
   217  		if result == nil {
   218  			b.Fatal("no result")
   219  		}
   220  	}
   221  }