mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-30 22:39:58 +02:00
tpl/collections: Add an integration test for collections.D
Also * improve the handling if invalid input * add a sanity check for number of elements asked for in D (1000000).
This commit is contained in:
@@ -409,6 +409,11 @@ func (ns *Namespace) Reverse(l any) (any, error) {
|
||||
return sliceCopy.Interface(), nil
|
||||
}
|
||||
|
||||
// Sanity check for slices created by Seq and D.
|
||||
const maxSeqSize = 1000000
|
||||
|
||||
var errSeqSizeExceedsLimit = errors.New("size of result exceeds limit")
|
||||
|
||||
// Seq creates a sequence of integers from args. It's named and used as GNU's seq.
|
||||
//
|
||||
// Examples:
|
||||
@@ -462,14 +467,14 @@ func (ns *Namespace) Seq(args ...any) ([]int, error) {
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if last < -100000 {
|
||||
return nil, errors.New("size of result exceeds limit")
|
||||
if last < -maxSeqSize {
|
||||
return nil, errSeqSizeExceedsLimit
|
||||
}
|
||||
size := ((last - first) / inc) + 1
|
||||
|
||||
// sanity check
|
||||
if size <= 0 || size > 2000 {
|
||||
return nil, errors.New("size of result exceeds limit")
|
||||
if size <= 0 || size > maxSeqSize {
|
||||
return nil, errSeqSizeExceedsLimit
|
||||
}
|
||||
|
||||
seq := make([]int, size)
|
||||
@@ -536,6 +541,12 @@ type dKey struct {
|
||||
// See https://getkerf.wordpress.com/2016/03/30/the-best-algorithm-no-one-knows-about/
|
||||
func (ns *Namespace) D(seed, n, hi any) []int {
|
||||
key := dKey{seed: cast.ToUint64(seed), n: cast.ToInt(n), hi: cast.ToInt(hi)}
|
||||
if key.n <= 0 || key.hi <= 0 || key.n > key.hi {
|
||||
return nil
|
||||
}
|
||||
if key.n > maxSeqSize {
|
||||
panic(errSeqSizeExceedsLimit)
|
||||
}
|
||||
v, _ := ns.dCache.GetOrCreate(key, func() ([]int, error) {
|
||||
prng := rand.New(rand.NewPCG(key.seed, 0))
|
||||
result := make([]int, 0, key.n)
|
||||
|
@@ -298,3 +298,33 @@ All|{{ .Title }}|
|
||||
|
||||
b.AssertFileContent("public/index.html", "Len: 1|")
|
||||
}
|
||||
|
||||
func TestD(t *testing.T) {
|
||||
t.Parallel()
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
-- layouts/home.html --
|
||||
{{ $p := site.RegularPages }}
|
||||
5 random pages: {{ range collections.D 42 5 ($p | len) }}{{ with (index $p .) }}{{ .RelPermalink }}|{{ end }}{{ end }}$
|
||||
-- content/a.md --
|
||||
-- content/b.md --
|
||||
-- content/c.md --
|
||||
-- content/d.md --
|
||||
-- content/e.md --
|
||||
-- content/f.md --
|
||||
-- content/g.md --
|
||||
-- content/h.md --
|
||||
-- content/i.md --
|
||||
-- content/j.md --
|
||||
-- content/k.md --
|
||||
-- content/l.md --
|
||||
-- content/m.md --
|
||||
-- content/n.md --
|
||||
-- content/o.md --
|
||||
-- content/p.md --
|
||||
|
||||
`
|
||||
b := hugolib.Test(t, files)
|
||||
|
||||
b.AssertFileContentExact("public/index.html", "5 random pages: /b/|/g/|/j/|/k/|/l/|$")
|
||||
}
|
||||
|
@@ -536,7 +536,7 @@ func TestSeq(t *testing.T) {
|
||||
{[]any{1, -1, 2}, false},
|
||||
{[]any{2, 1, 1}, false},
|
||||
{[]any{2, 1, 1, 1}, false},
|
||||
{[]any{2001}, false},
|
||||
{[]any{-1000001}, false},
|
||||
{[]any{}, false},
|
||||
{[]any{0, -1000000}, false},
|
||||
{[]any{tstNoStringer{}}, false},
|
||||
@@ -795,6 +795,15 @@ func TestD(t *testing.T) {
|
||||
|
||||
c.Assert(ns.D(42, 5, 100), qt.DeepEquals, []int{24, 34, 66, 82, 96})
|
||||
c.Assert(ns.D(31, 5, 100), qt.DeepEquals, []int{12, 37, 38, 69, 98})
|
||||
c.Assert(ns.D(42, 9, 10), qt.DeepEquals, []int{0, 1, 2, 3, 4, 6, 7, 8, 9})
|
||||
c.Assert(ns.D(42, 10, 10), qt.DeepEquals, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
|
||||
c.Assert(ns.D(42, 11, 10), qt.IsNil) // n > hi
|
||||
c.Assert(ns.D(42, -5, 100), qt.IsNil)
|
||||
c.Assert(ns.D(42, 0, 100), qt.IsNil)
|
||||
c.Assert(ns.D(42, 5, 0), qt.IsNil)
|
||||
c.Assert(ns.D(42, 5, -10), qt.IsNil)
|
||||
c.Assert(ns.D(42, 5, 3000000), qt.DeepEquals, []int{720363, 1041693, 2009179, 2489106, 2873969})
|
||||
c.Assert(func() { ns.D(31, 2000000, 3000000) }, qt.PanicMatches, "size of result exceeds limit")
|
||||
}
|
||||
|
||||
func BenchmarkD2(b *testing.B) {
|
||||
|
Reference in New Issue
Block a user