github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/resources/page/permalinks_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 page
    15  
    16  import (
    17  	"fmt"
    18  	"regexp"
    19  	"sync"
    20  	"testing"
    21  	"time"
    22  
    23  	qt "github.com/frankban/quicktest"
    24  )
    25  
    26  // testdataPermalinks is used by a couple of tests; the expandsTo content is
    27  // subject to the data in simplePageJSON.
    28  var testdataPermalinks = []struct {
    29  	spec      string
    30  	valid     bool
    31  	expandsTo string
    32  }{
    33  	{":title", true, "spf13-vim-3.0-release-and-new-website"},
    34  	{"/:year-:month-:title", true, "/2012-04-spf13-vim-3.0-release-and-new-website"},
    35  	{"/:year/:yearday/:month/:monthname/:day/:weekday/:weekdayname/", true, "/2012/97/04/April/06/5/Friday/"}, // Dates
    36  	{"/:section/", true, "/blue/"},                                  // Section
    37  	{"/:title/", true, "/spf13-vim-3.0-release-and-new-website/"},   // Title
    38  	{"/:slug/", true, "/the-slug/"},                                 // Slug
    39  	{"/:filename/", true, "/test-page/"},                            // Filename
    40  	{"/:06-:1-:2-:Monday", true, "/12-4-6-Friday"},                  // Dates with Go formatting
    41  	{"/:2006_01_02_15_04_05.000", true, "/2012_04_06_03_01_59.000"}, // Complicated custom date format
    42  	{"/:sections/", true, "/a/b/c/"},                                // Sections
    43  	{"/:sections[last]/", true, "/c/"},                              // Sections
    44  
    45  	// Failures
    46  	{"/blog/:fred", false, ""},
    47  	{"/:year//:title", false, ""},
    48  	{"/:TITLE", false, ""},      // case is not normalized
    49  	{"/:2017", false, ""},       // invalid date format
    50  	{"/:2006-01-02", false, ""}, // valid date format but invalid attribute name
    51  }
    52  
    53  func TestPermalinkExpansion(t *testing.T) {
    54  	t.Parallel()
    55  
    56  	c := qt.New(t)
    57  
    58  	page := newTestPageWithFile("/test-page/index.md")
    59  	page.title = "Spf13 Vim 3.0 Release and new website"
    60  	d, _ := time.Parse("2006-01-02 15:04:05", "2012-04-06 03:01:59")
    61  	page.date = d
    62  	page.section = "blue"
    63  	page.slug = "The Slug"
    64  
    65  	for _, item := range testdataPermalinks {
    66  		if !item.valid {
    67  			continue
    68  		}
    69  
    70  		specNameCleaner := regexp.MustCompile(`[\:\/\[\]]`)
    71  		name := specNameCleaner.ReplaceAllString(item.spec, "")
    72  
    73  		c.Run(name, func(c *qt.C) {
    74  
    75  			permalinksConfig := map[string]string{
    76  				"posts": item.spec,
    77  			}
    78  
    79  			ps := newTestPathSpec()
    80  			ps.Cfg.Set("permalinks", permalinksConfig)
    81  
    82  			expander, err := NewPermalinkExpander(ps)
    83  			c.Assert(err, qt.IsNil)
    84  
    85  			expanded, err := expander.Expand("posts", page)
    86  			c.Assert(err, qt.IsNil)
    87  			c.Assert(expanded, qt.Equals, item.expandsTo)
    88  		})
    89  
    90  	}
    91  }
    92  
    93  func TestPermalinkExpansionMultiSection(t *testing.T) {
    94  	t.Parallel()
    95  
    96  	c := qt.New(t)
    97  
    98  	page := newTestPage()
    99  	page.title = "Page Title"
   100  	d, _ := time.Parse("2006-01-02", "2012-04-06")
   101  	page.date = d
   102  	page.section = "blue"
   103  	page.slug = "The Slug"
   104  
   105  	permalinksConfig := map[string]string{
   106  		"posts": "/:slug",
   107  		"blog":  "/:section/:year",
   108  	}
   109  
   110  	ps := newTestPathSpec()
   111  	ps.Cfg.Set("permalinks", permalinksConfig)
   112  
   113  	expander, err := NewPermalinkExpander(ps)
   114  	c.Assert(err, qt.IsNil)
   115  
   116  	expanded, err := expander.Expand("posts", page)
   117  	c.Assert(err, qt.IsNil)
   118  	c.Assert(expanded, qt.Equals, "/the-slug")
   119  
   120  	expanded, err = expander.Expand("blog", page)
   121  	c.Assert(err, qt.IsNil)
   122  	c.Assert(expanded, qt.Equals, "/blue/2012")
   123  }
   124  
   125  func TestPermalinkExpansionConcurrent(t *testing.T) {
   126  	t.Parallel()
   127  
   128  	c := qt.New(t)
   129  
   130  	permalinksConfig := map[string]string{
   131  		"posts": "/:slug/",
   132  	}
   133  
   134  	ps := newTestPathSpec()
   135  	ps.Cfg.Set("permalinks", permalinksConfig)
   136  
   137  	expander, err := NewPermalinkExpander(ps)
   138  	c.Assert(err, qt.IsNil)
   139  
   140  	var wg sync.WaitGroup
   141  
   142  	for i := 1; i < 20; i++ {
   143  		wg.Add(1)
   144  		go func(i int) {
   145  			defer wg.Done()
   146  			page := newTestPage()
   147  			for j := 1; j < 20; j++ {
   148  				page.slug = fmt.Sprintf("slug%d", i+j)
   149  				expanded, err := expander.Expand("posts", page)
   150  				c.Assert(err, qt.IsNil)
   151  				c.Assert(expanded, qt.Equals, fmt.Sprintf("/%s/", page.slug))
   152  			}
   153  		}(i)
   154  	}
   155  
   156  	wg.Wait()
   157  }
   158  
   159  func TestPermalinkExpansionSliceSyntax(t *testing.T) {
   160  	t.Parallel()
   161  
   162  	c := qt.New(t)
   163  	exp, _ := NewPermalinkExpander(newTestPathSpec())
   164  	slice := []string{"a", "b", "c", "d"}
   165  	fn := func(s string) []string {
   166  		return exp.toSliceFunc(s)(slice)
   167  	}
   168  
   169  	c.Run("Basic", func(c *qt.C) {
   170  		c.Assert(fn("[1:3]"), qt.DeepEquals, []string{"b", "c"})
   171  		c.Assert(fn("[1:]"), qt.DeepEquals, []string{"b", "c", "d"})
   172  		c.Assert(fn("[:2]"), qt.DeepEquals, []string{"a", "b"})
   173  		c.Assert(fn("[0:2]"), qt.DeepEquals, []string{"a", "b"})
   174  		c.Assert(fn("[:]"), qt.DeepEquals, []string{"a", "b", "c", "d"})
   175  		c.Assert(fn(""), qt.DeepEquals, []string{"a", "b", "c", "d"})
   176  		c.Assert(fn("[last]"), qt.DeepEquals, []string{"d"})
   177  		c.Assert(fn("[:last]"), qt.DeepEquals, []string{"a", "b", "c"})
   178  
   179  	})
   180  
   181  	c.Run("Out of bounds", func(c *qt.C) {
   182  		c.Assert(fn("[1:5]"), qt.DeepEquals, []string{"b", "c", "d"})
   183  		c.Assert(fn("[-1:5]"), qt.DeepEquals, []string{"a", "b", "c", "d"})
   184  		c.Assert(fn("[5:]"), qt.DeepEquals, []string{})
   185  		c.Assert(fn("[5:]"), qt.DeepEquals, []string{})
   186  		c.Assert(fn("[5:32]"), qt.DeepEquals, []string{})
   187  		c.Assert(exp.toSliceFunc("[:1]")(nil), qt.DeepEquals, []string(nil))
   188  		c.Assert(exp.toSliceFunc("[:1]")([]string{}), qt.DeepEquals, []string(nil))
   189  
   190  		// These all return nil
   191  		c.Assert(fn("[]"), qt.IsNil)
   192  		c.Assert(fn("[1:}"), qt.IsNil)
   193  		c.Assert(fn("foo"), qt.IsNil)
   194  
   195  	})
   196  
   197  }
   198  
   199  func BenchmarkPermalinkExpand(b *testing.B) {
   200  	page := newTestPage()
   201  	page.title = "Hugo Rocks"
   202  	d, _ := time.Parse("2006-01-02", "2019-02-28")
   203  	page.date = d
   204  
   205  	permalinksConfig := map[string]string{
   206  		"posts": "/:year-:month-:title",
   207  	}
   208  
   209  	ps := newTestPathSpec()
   210  	ps.Cfg.Set("permalinks", permalinksConfig)
   211  
   212  	expander, err := NewPermalinkExpander(ps)
   213  	if err != nil {
   214  		b.Fatal(err)
   215  	}
   216  
   217  	b.ResetTimer()
   218  	for i := 0; i < b.N; i++ {
   219  		s, err := expander.Expand("posts", page)
   220  		if err != nil {
   221  			b.Fatal(err)
   222  		}
   223  		if s != "/2019-02-hugo-rocks" {
   224  			b.Fatal(s)
   225  		}
   226  
   227  	}
   228  }