mirror of
https://github.com/go-task/task.git
synced 2026-08-29 10:08:27 +02:00
test(templater): snapshot the template function surface and behaviour
Golden tests capturing the sorted list of template function names and the rendered output of a representative expression per function. Generated against the current slim-sprig implementation so that any change of templating library produces an auditable diff.
This commit is contained in:
325
internal/templater/snapshot_test.go
Normal file
325
internal/templater/snapshot_test.go
Normal file
@@ -0,0 +1,325 @@
|
||||
package templater
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/sebdah/goldie/v2"
|
||||
|
||||
"github.com/go-task/task/v3/taskfile/ast"
|
||||
)
|
||||
|
||||
// The two tests in this file snapshot the entire template surface: the set of
|
||||
// function names, and the rendered output of a representative expression per
|
||||
// function. They exist to make any change of templating library auditable —
|
||||
// the golden diff is the exhaustive list of what changed for users.
|
||||
//
|
||||
// Expressions must stay deterministic and platform independent, so anything
|
||||
// depending on the clock, the filesystem, the environment or randomness is
|
||||
// deliberately absent (`now`, `uuid`, `randInt`, `env`, `os*`, `exeExt`, `OS`,
|
||||
// `ARCH`, `spew`, `getHostByName`). Those are covered by unit tests instead.
|
||||
|
||||
// TestMain pins the local timezone so that the date expressions below render
|
||||
// identically on every machine. A consequence is that this golden cannot show
|
||||
// the local-vs-UTC difference between sprig's `date`/`toDate` and sprout's —
|
||||
// that one belongs in the migration documentation.
|
||||
func TestMain(m *testing.M) {
|
||||
time.Local = time.UTC
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestFuncNames(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
names := slices.Sorted(maps.Keys(templateFuncs))
|
||||
|
||||
g := goldie.New(t)
|
||||
g.Assert(t, "func_names", []byte(strings.Join(names, "\n")+"\n"))
|
||||
}
|
||||
|
||||
func TestFuncBehaviour(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var b strings.Builder
|
||||
for _, group := range funcBehaviourGroups {
|
||||
fmt.Fprintf(&b, "## %s\n\n", group.name)
|
||||
for _, expr := range group.exprs {
|
||||
cache := &Cache{Vars: ast.NewVars()}
|
||||
got := ReplaceWithExtra(expr, cache, nil)
|
||||
fmt.Fprintf(&b, "%s\n", expr)
|
||||
if err := cache.Err(); err != nil {
|
||||
fmt.Fprintf(&b, "\t! %s\n", normalizeTemplateError(err))
|
||||
} else {
|
||||
fmt.Fprintf(&b, "\t= %s\n", strings.ReplaceAll(got, "\n", "\\n"))
|
||||
}
|
||||
}
|
||||
b.WriteString("\n")
|
||||
}
|
||||
|
||||
g := goldie.New(t)
|
||||
g.Assert(t, "func_behaviour", []byte(b.String()))
|
||||
}
|
||||
|
||||
// normalizeTemplateError strips the position prefix that text/template adds to
|
||||
// execution errors, which is noise in the golden and shifts whenever an
|
||||
// expression is added to a group.
|
||||
func normalizeTemplateError(err error) string {
|
||||
s := err.Error()
|
||||
if _, after, found := strings.Cut(s, `at <`); found {
|
||||
return "at <" + after
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
var funcBehaviourGroups = []struct {
|
||||
name string
|
||||
exprs []string
|
||||
}{
|
||||
{
|
||||
// The ten functions whose argument order differs between sprig and
|
||||
// sprout. Written here in sprig order, which is what users' Taskfiles
|
||||
// contain today.
|
||||
"argument order — sprig order (target first)",
|
||||
[]string{
|
||||
`{{ get (dict "a" "b") "a" }}`,
|
||||
`{{ set (dict "a" "b") "c" "d" | toJson }}`,
|
||||
`{{ unset (dict "a" "b" "c" "d") "a" | toJson }}`,
|
||||
`{{ hasKey (dict "a" "b") "a" }}`,
|
||||
`{{ pick (dict "a" "1" "b" "2") "a" | toJson }}`,
|
||||
`{{ omit (dict "a" "1" "b" "2") "a" | toJson }}`,
|
||||
`{{ append (list 1 2) 3 | toJson }}`,
|
||||
`{{ push (list 1 2) 3 | toJson }}`,
|
||||
`{{ prepend (list 2 3) 1 | toJson }}`,
|
||||
`{{ without (list 1 2 3) 2 | toJson }}`,
|
||||
`{{ slice (list 1 2 3 4) 1 3 | toJson }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Same ten functions in sprout order. Today these mostly fail; after
|
||||
// the migration both forms must work.
|
||||
"argument order — sprout order (target last)",
|
||||
[]string{
|
||||
`{{ dict "a" "b" | get "a" }}`,
|
||||
`{{ dict "a" "b" | set "c" "d" | toJson }}`,
|
||||
`{{ dict "a" "b" "c" "d" | unset "a" | toJson }}`,
|
||||
`{{ dict "a" "b" | hasKey "a" }}`,
|
||||
`{{ list 1 2 | append 3 | toJson }}`,
|
||||
`{{ list 2 3 | prepend 1 | toJson }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"maps — unchanged signatures",
|
||||
[]string{
|
||||
`{{ dict "a" 1 "b" 2 | toJson }}`,
|
||||
`{{ keys (dict "b" 1 "a" 2) | sortAlpha | toJson }}`,
|
||||
`{{ values (dict "a" 1) | toJson }}`,
|
||||
`{{ pluck "a" (dict "a" 1) (dict "a" 2) | toJson }}`,
|
||||
`{{ dig "a" "b" "fallback" (dict "a" (dict "b" "found")) }}`,
|
||||
`{{ dig "a" "missing" "fallback" (dict "a" (dict "b" "found")) }}`,
|
||||
`{{ dig "a.b" "fallback" (dict "a" (dict "b" "found")) }}`,
|
||||
`{{ merge (dict "a" 1) (dict "b" 2) | toJson }}`,
|
||||
`{{ merge (dict "a" 1) (dict "a" 0) | toJson }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"lists",
|
||||
[]string{
|
||||
`{{ list 1 2 3 | toJson }}`,
|
||||
`{{ tuple 1 2 3 | toJson }}`,
|
||||
`{{ first (list 1 2 3) }}`,
|
||||
`{{ last (list 1 2 3) }}`,
|
||||
`{{ rest (list 1 2 3) | toJson }}`,
|
||||
`{{ initial (list 1 2 3) | toJson }}`,
|
||||
`{{ reverse (list 1 2 3) | toJson }}`,
|
||||
`{{ uniq (list 1 1 2) | toJson }}`,
|
||||
`{{ compact (list 1 "" 2) | toJson }}`,
|
||||
`{{ concat (list 1) (list 2) | toJson }}`,
|
||||
`{{ chunk 2 (list 1 2 3) | toJson }}`,
|
||||
`{{ has 2 (list 1 2 3) }}`,
|
||||
`{{ sortAlpha (list "b" "a") | toJson }}`,
|
||||
`{{ splitList "," "a,b,c" | toJson }}`,
|
||||
`{{ toStrings (list 1 2) | toJson }}`,
|
||||
`{{ until 3 | toJson }}`,
|
||||
`{{ untilStep 0 6 2 | toJson }}`,
|
||||
`{{ seq 1 3 }}`,
|
||||
`{{ join "," (list "a" "b") }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"strings",
|
||||
[]string{
|
||||
`{{ trim " x " }}`,
|
||||
`{{ trimAll "-" "-x-" }}`,
|
||||
`{{ trimall "-" "-x-" }}`,
|
||||
`{{ trimPrefix "a" "ab" }}`,
|
||||
`{{ trimSuffix "b" "ab" }}`,
|
||||
`{{ upper "abc" }}`,
|
||||
`{{ lower "ABC" }}`,
|
||||
`{{ title "hello world" }}`,
|
||||
`{{ title "hello wORLD" }}`,
|
||||
`{{ trunc 3 "foobar" }}`,
|
||||
`{{ trunc -3 "foobar" }}`,
|
||||
`{{ substr 0 3 "foobar" }}`,
|
||||
`{{ substr 0 -3 "foobar" }}`,
|
||||
`{{ repeat 3 "x" }}`,
|
||||
`{{ contains "oo" "foobar" }}`,
|
||||
`{{ hasPrefix "foo" "foobar" }}`,
|
||||
`{{ hasSuffix "bar" "foobar" }}`,
|
||||
`{{ quote "x" }}`,
|
||||
`{{ squote "x" }}`,
|
||||
`{{ cat "a" "b" }}`,
|
||||
`{{ indent 2 "x" }}`,
|
||||
`{{ nindent 2 "x" }}`,
|
||||
`{{ replace "a" "b" "aa" }}`,
|
||||
`{{ plural "one" "many" 2 }}`,
|
||||
`{{ split "," "a,b" | toJson }}`,
|
||||
`{{ splitn "," 2 "a,b,c" | toJson }}`,
|
||||
`{{ toString 42 }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"numbers",
|
||||
[]string{
|
||||
`{{ add 1 2 }}`,
|
||||
`{{ add1 1 }}`,
|
||||
`{{ sub 5 2 }}`,
|
||||
`{{ mul 2 3 }}`,
|
||||
`{{ div 6 2 }}`,
|
||||
`{{ mod 5 3 }}`,
|
||||
`{{ max 1 5 3 }}`,
|
||||
`{{ min 1 5 3 }}`,
|
||||
`{{ biggest 1 5 3 }}`,
|
||||
`{{ maxf 1.5 2.5 }}`,
|
||||
`{{ minf 1.5 2.5 }}`,
|
||||
`{{ ceil 1.1 }}`,
|
||||
`{{ floor 1.9 }}`,
|
||||
`{{ round 1.55 1 }}`,
|
||||
`{{ atoi "42" }}`,
|
||||
`{{ atoi "abc" }}`,
|
||||
`{{ int "42" }}`,
|
||||
`{{ int64 "42" }}`,
|
||||
`{{ float64 "1.5" }}`,
|
||||
`{{ toDecimal "0777" }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"defaults and flow",
|
||||
[]string{
|
||||
`{{ default "d" "" }}`,
|
||||
`{{ default "d" "x" }}`,
|
||||
`{{ empty "" }}`,
|
||||
`{{ empty 0 }}`,
|
||||
`{{ coalesce "" "x" }}`,
|
||||
`{{ all 1 1 }}`,
|
||||
`{{ any 0 1 }}`,
|
||||
`{{ ternary "y" "n" true }}`,
|
||||
`{{ fail "boom" }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"encoding",
|
||||
[]string{
|
||||
`{{ toJson (dict "a" 1) }}`,
|
||||
`{{ toPrettyJson (dict "a" 1) }}`,
|
||||
`{{ toRawJson (dict "a" "<b>") }}`,
|
||||
`{{ fromJson "{\"a\":1}" | toJson }}`,
|
||||
`{{ fromJson "not json" | toJson }}`,
|
||||
`{{ mustFromJson "not json" | toJson }}`,
|
||||
`{{ toYaml (dict "a" 1) }}`,
|
||||
`{{ fromYaml "a: 1" | toJson }}`,
|
||||
`{{ mustFromYaml "a: :" | toJson }}`,
|
||||
`{{ b64enc "hello" }}`,
|
||||
`{{ b64dec "aGVsbG8=" }}`,
|
||||
`{{ b32enc "hello" }}`,
|
||||
`{{ b32dec "NBSWY3DP" }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"regex",
|
||||
[]string{
|
||||
`{{ regexMatch "^a" "abc" }}`,
|
||||
`{{ regexFind "[0-9]+" "abc123" }}`,
|
||||
`{{ regexFindAll "[0-9]" "a1b2" -1 | toJson }}`,
|
||||
`{{ regexReplaceAll "[0-9]" "abc123" "#" }}`,
|
||||
`{{ regexReplaceAllLiteral "[0-9]" "abc123" "#" }}`,
|
||||
`{{ regexSplit "," "a,b" -1 | toJson }}`,
|
||||
`{{ regexQuoteMeta "a.b" }}`,
|
||||
`{{ mustRegexFind "[" "abc" }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"reflection",
|
||||
[]string{
|
||||
`{{ typeOf 1 }}`,
|
||||
`{{ typeIs "int" 1 }}`,
|
||||
`{{ typeIsLike "int" 1 }}`,
|
||||
`{{ kindOf 1 }}`,
|
||||
`{{ kindOf (list 1) }}`,
|
||||
`{{ kindIs "int" 1 }}`,
|
||||
`{{ deepEqual (list 1) (list 1) }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"checksums",
|
||||
[]string{
|
||||
`{{ sha1sum "x" }}`,
|
||||
`{{ sha256sum "x" }}`,
|
||||
`{{ adler32sum "x" }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
// path.* semantics — slash based, therefore identical on every platform.
|
||||
"paths",
|
||||
[]string{
|
||||
`{{ base "/foo/bar.txt" }}`,
|
||||
`{{ dir "/foo/bar.txt" }}`,
|
||||
`{{ ext "/foo/bar.txt" }}`,
|
||||
`{{ clean "/foo//bar" }}`,
|
||||
`{{ isAbs "/foo" }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"dates — fixed epoch, explicit zone",
|
||||
[]string{
|
||||
`{{ dateInZone "2006-01-02T15:04:05" 0 "UTC" }}`,
|
||||
`{{ date "2006-01-02T15:04:05" 0 }}`,
|
||||
`{{ dateModify "1h" (toDate "2006-01-02T15:04:05Z07:00" "2020-01-01T00:00:00Z") }}`,
|
||||
`{{ date_modify "1h" (toDate "2006-01-02T15:04:05Z07:00" "2020-01-01T00:00:00Z") }}`,
|
||||
`{{ toDate "2006-01-02" "2020-01-01" }}`,
|
||||
`{{ unixEpoch (toDate "2006-01-02" "2020-01-01") }}`,
|
||||
`{{ duration 90 }}`,
|
||||
`{{ durationRound "1h35m30s" }}`,
|
||||
`{{ htmlDate 0 }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"urls",
|
||||
[]string{
|
||||
`{{ urlParse "http://example.com/a?b=c" | toJson }}`,
|
||||
`{{ urlJoin (dict "scheme" "http" "host" "example.com" "path" "/a") }}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
"task's own functions",
|
||||
[]string{
|
||||
`{{ numCPU | kindOf }}`,
|
||||
`{{ catLines "a\nb" }}`,
|
||||
`{{ splitLines "a\nb" | toJson }}`,
|
||||
`{{ toSlash "a/b" }}`,
|
||||
`{{ fromSlash "a/b" | kindOf }}`,
|
||||
`{{ ToSlash "a/b" }}`,
|
||||
`{{ shellQuote "a b" }}`,
|
||||
`{{ q "a b" }}`,
|
||||
`{{ splitArgs "a b c" | toJson }}`,
|
||||
`{{ IsSH }}`,
|
||||
`{{ joinUrl "http://localhost" "a" "b" }}`,
|
||||
`{{ mustToYaml (dict "a" 1) }}`,
|
||||
`{{ randIntN 1 }}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
367
internal/templater/testdata/func_behaviour.golden
vendored
Normal file
367
internal/templater/testdata/func_behaviour.golden
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
## argument order — sprig order (target first)
|
||||
|
||||
{{ get (dict "a" "b") "a" }}
|
||||
= b
|
||||
{{ set (dict "a" "b") "c" "d" | toJson }}
|
||||
= {"a":"b","c":"d"}
|
||||
{{ unset (dict "a" "b" "c" "d") "a" | toJson }}
|
||||
= {"c":"d"}
|
||||
{{ hasKey (dict "a" "b") "a" }}
|
||||
= true
|
||||
{{ pick (dict "a" "1" "b" "2") "a" | toJson }}
|
||||
= {"a":"1"}
|
||||
{{ omit (dict "a" "1" "b" "2") "a" | toJson }}
|
||||
= {"b":"2"}
|
||||
{{ append (list 1 2) 3 | toJson }}
|
||||
= [1,2,3]
|
||||
{{ push (list 1 2) 3 | toJson }}
|
||||
= [1,2,3]
|
||||
{{ prepend (list 2 3) 1 | toJson }}
|
||||
= [1,2,3]
|
||||
{{ without (list 1 2 3) 2 | toJson }}
|
||||
= [1,3]
|
||||
{{ slice (list 1 2 3 4) 1 3 | toJson }}
|
||||
= [2,3]
|
||||
|
||||
## argument order — sprout order (target last)
|
||||
|
||||
{{ dict "a" "b" | get "a" }}
|
||||
! at <"a">: can't handle "a" for arg of type map[string]interface {}
|
||||
{{ dict "a" "b" | set "c" "d" | toJson }}
|
||||
! at <"c">: can't handle "c" for arg of type map[string]interface {}
|
||||
{{ dict "a" "b" "c" "d" | unset "a" | toJson }}
|
||||
! at <"a">: can't handle "a" for arg of type map[string]interface {}
|
||||
{{ dict "a" "b" | hasKey "a" }}
|
||||
! at <"a">: can't handle "a" for arg of type map[string]interface {}
|
||||
{{ list 1 2 | append 3 | toJson }}
|
||||
! at <append 3>: error calling append: Cannot push on type int
|
||||
{{ list 2 3 | prepend 1 | toJson }}
|
||||
! at <prepend 1>: error calling prepend: Cannot prepend on type int
|
||||
|
||||
## maps — unchanged signatures
|
||||
|
||||
{{ dict "a" 1 "b" 2 | toJson }}
|
||||
= {"a":1,"b":2}
|
||||
{{ keys (dict "b" 1 "a" 2) | sortAlpha | toJson }}
|
||||
= ["a","b"]
|
||||
{{ values (dict "a" 1) | toJson }}
|
||||
= [1]
|
||||
{{ pluck "a" (dict "a" 1) (dict "a" 2) | toJson }}
|
||||
= [1,2]
|
||||
{{ dig "a" "b" "fallback" (dict "a" (dict "b" "found")) }}
|
||||
= found
|
||||
{{ dig "a" "missing" "fallback" (dict "a" (dict "b" "found")) }}
|
||||
= fallback
|
||||
{{ dig "a.b" "fallback" (dict "a" (dict "b" "found")) }}
|
||||
= fallback
|
||||
{{ merge (dict "a" 1) (dict "b" 2) | toJson }}
|
||||
= {"a":1,"b":2}
|
||||
{{ merge (dict "a" 1) (dict "a" 0) | toJson }}
|
||||
= {"a":0}
|
||||
|
||||
## lists
|
||||
|
||||
{{ list 1 2 3 | toJson }}
|
||||
= [1,2,3]
|
||||
{{ tuple 1 2 3 | toJson }}
|
||||
= [1,2,3]
|
||||
{{ first (list 1 2 3) }}
|
||||
= 1
|
||||
{{ last (list 1 2 3) }}
|
||||
= 3
|
||||
{{ rest (list 1 2 3) | toJson }}
|
||||
= [2,3]
|
||||
{{ initial (list 1 2 3) | toJson }}
|
||||
= [1,2]
|
||||
{{ reverse (list 1 2 3) | toJson }}
|
||||
= [3,2,1]
|
||||
{{ uniq (list 1 1 2) | toJson }}
|
||||
= [1,2]
|
||||
{{ compact (list 1 "" 2) | toJson }}
|
||||
= [1,2]
|
||||
{{ concat (list 1) (list 2) | toJson }}
|
||||
= [1,2]
|
||||
{{ chunk 2 (list 1 2 3) | toJson }}
|
||||
= [[1,2],[3]]
|
||||
{{ has 2 (list 1 2 3) }}
|
||||
= true
|
||||
{{ sortAlpha (list "b" "a") | toJson }}
|
||||
= ["a","b"]
|
||||
{{ splitList "," "a,b,c" | toJson }}
|
||||
= ["a","b","c"]
|
||||
{{ toStrings (list 1 2) | toJson }}
|
||||
= ["1","2"]
|
||||
{{ until 3 | toJson }}
|
||||
= [0,1,2]
|
||||
{{ untilStep 0 6 2 | toJson }}
|
||||
= [0,2,4]
|
||||
{{ seq 1 3 }}
|
||||
= 1 2 3
|
||||
{{ join "," (list "a" "b") }}
|
||||
= a,b
|
||||
|
||||
## strings
|
||||
|
||||
{{ trim " x " }}
|
||||
= x
|
||||
{{ trimAll "-" "-x-" }}
|
||||
= x
|
||||
{{ trimall "-" "-x-" }}
|
||||
= x
|
||||
{{ trimPrefix "a" "ab" }}
|
||||
= b
|
||||
{{ trimSuffix "b" "ab" }}
|
||||
= a
|
||||
{{ upper "abc" }}
|
||||
= ABC
|
||||
{{ lower "ABC" }}
|
||||
= abc
|
||||
{{ title "hello world" }}
|
||||
= Hello World
|
||||
{{ title "hello wORLD" }}
|
||||
= Hello WORLD
|
||||
{{ trunc 3 "foobar" }}
|
||||
= foo
|
||||
{{ trunc -3 "foobar" }}
|
||||
= bar
|
||||
{{ substr 0 3 "foobar" }}
|
||||
= foo
|
||||
{{ substr 0 -3 "foobar" }}
|
||||
= foobar
|
||||
{{ repeat 3 "x" }}
|
||||
= xxx
|
||||
{{ contains "oo" "foobar" }}
|
||||
= true
|
||||
{{ hasPrefix "foo" "foobar" }}
|
||||
= true
|
||||
{{ hasSuffix "bar" "foobar" }}
|
||||
= true
|
||||
{{ quote "x" }}
|
||||
= "x"
|
||||
{{ squote "x" }}
|
||||
= 'x'
|
||||
{{ cat "a" "b" }}
|
||||
= a b
|
||||
{{ indent 2 "x" }}
|
||||
= x
|
||||
{{ nindent 2 "x" }}
|
||||
= \n x
|
||||
{{ replace "a" "b" "aa" }}
|
||||
= bb
|
||||
{{ plural "one" "many" 2 }}
|
||||
= many
|
||||
{{ split "," "a,b" | toJson }}
|
||||
= {"_0":"a","_1":"b"}
|
||||
{{ splitn "," 2 "a,b,c" | toJson }}
|
||||
= {"_0":"a","_1":"b,c"}
|
||||
{{ toString 42 }}
|
||||
= 42
|
||||
|
||||
## numbers
|
||||
|
||||
{{ add 1 2 }}
|
||||
= 3
|
||||
{{ add1 1 }}
|
||||
= 2
|
||||
{{ sub 5 2 }}
|
||||
= 3
|
||||
{{ mul 2 3 }}
|
||||
= 6
|
||||
{{ div 6 2 }}
|
||||
= 3
|
||||
{{ mod 5 3 }}
|
||||
= 2
|
||||
{{ max 1 5 3 }}
|
||||
= 5
|
||||
{{ min 1 5 3 }}
|
||||
= 1
|
||||
{{ biggest 1 5 3 }}
|
||||
= 5
|
||||
{{ maxf 1.5 2.5 }}
|
||||
= 2.5
|
||||
{{ minf 1.5 2.5 }}
|
||||
= 1.5
|
||||
{{ ceil 1.1 }}
|
||||
= 2
|
||||
{{ floor 1.9 }}
|
||||
= 1
|
||||
{{ round 1.55 1 }}
|
||||
= 1.6
|
||||
{{ atoi "42" }}
|
||||
= 42
|
||||
{{ atoi "abc" }}
|
||||
= 0
|
||||
{{ int "42" }}
|
||||
= 42
|
||||
{{ int64 "42" }}
|
||||
= 42
|
||||
{{ float64 "1.5" }}
|
||||
= 1.5
|
||||
{{ toDecimal "0777" }}
|
||||
= 511
|
||||
|
||||
## defaults and flow
|
||||
|
||||
{{ default "d" "" }}
|
||||
= d
|
||||
{{ default "d" "x" }}
|
||||
= x
|
||||
{{ empty "" }}
|
||||
= true
|
||||
{{ empty 0 }}
|
||||
= true
|
||||
{{ coalesce "" "x" }}
|
||||
= x
|
||||
{{ all 1 1 }}
|
||||
= true
|
||||
{{ any 0 1 }}
|
||||
= true
|
||||
{{ ternary "y" "n" true }}
|
||||
= y
|
||||
{{ fail "boom" }}
|
||||
! at <fail "boom">: error calling fail: boom
|
||||
|
||||
## encoding
|
||||
|
||||
{{ toJson (dict "a" 1) }}
|
||||
= {"a":1}
|
||||
{{ toPrettyJson (dict "a" 1) }}
|
||||
= {\n "a": 1\n}
|
||||
{{ toRawJson (dict "a" "<b>") }}
|
||||
= {"a":"<b>"}
|
||||
{{ fromJson "{\"a\":1}" | toJson }}
|
||||
= {"a":1}
|
||||
{{ fromJson "not json" | toJson }}
|
||||
= null
|
||||
{{ mustFromJson "not json" | toJson }}
|
||||
! at <mustFromJson "not json">: error calling mustFromJson: invalid character 'o' in literal null (expecting 'u')
|
||||
{{ toYaml (dict "a" 1) }}
|
||||
= a: 1\n
|
||||
{{ fromYaml "a: 1" | toJson }}
|
||||
= {"a":1}
|
||||
{{ mustFromYaml "a: :" | toJson }}
|
||||
! at <mustFromYaml "a: :">: error calling mustFromYaml: yaml: mapping values are not allowed in this context
|
||||
{{ b64enc "hello" }}
|
||||
= aGVsbG8=
|
||||
{{ b64dec "aGVsbG8=" }}
|
||||
= hello
|
||||
{{ b32enc "hello" }}
|
||||
= NBSWY3DP
|
||||
{{ b32dec "NBSWY3DP" }}
|
||||
= hello
|
||||
|
||||
## regex
|
||||
|
||||
{{ regexMatch "^a" "abc" }}
|
||||
= true
|
||||
{{ regexFind "[0-9]+" "abc123" }}
|
||||
= 123
|
||||
{{ regexFindAll "[0-9]" "a1b2" -1 | toJson }}
|
||||
= ["1","2"]
|
||||
{{ regexReplaceAll "[0-9]" "abc123" "#" }}
|
||||
= abc###
|
||||
{{ regexReplaceAllLiteral "[0-9]" "abc123" "#" }}
|
||||
= abc###
|
||||
{{ regexSplit "," "a,b" -1 | toJson }}
|
||||
= ["a","b"]
|
||||
{{ regexQuoteMeta "a.b" }}
|
||||
= a\.b
|
||||
{{ mustRegexFind "[" "abc" }}
|
||||
! at <mustRegexFind "[" "abc">: error calling mustRegexFind: error parsing regexp: missing closing ]: `[`
|
||||
|
||||
## reflection
|
||||
|
||||
{{ typeOf 1 }}
|
||||
= int
|
||||
{{ typeIs "int" 1 }}
|
||||
= true
|
||||
{{ typeIsLike "int" 1 }}
|
||||
= true
|
||||
{{ kindOf 1 }}
|
||||
= int
|
||||
{{ kindOf (list 1) }}
|
||||
= slice
|
||||
{{ kindIs "int" 1 }}
|
||||
= true
|
||||
{{ deepEqual (list 1) (list 1) }}
|
||||
= true
|
||||
|
||||
## checksums
|
||||
|
||||
{{ sha1sum "x" }}
|
||||
= 11f6ad8ec52a2984abaafd7c3b516503785c2072
|
||||
{{ sha256sum "x" }}
|
||||
= 2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881
|
||||
{{ adler32sum "x" }}
|
||||
= 7929977
|
||||
|
||||
## paths
|
||||
|
||||
{{ base "/foo/bar.txt" }}
|
||||
= bar.txt
|
||||
{{ dir "/foo/bar.txt" }}
|
||||
= /foo
|
||||
{{ ext "/foo/bar.txt" }}
|
||||
= .txt
|
||||
{{ clean "/foo//bar" }}
|
||||
= /foo/bar
|
||||
{{ isAbs "/foo" }}
|
||||
= true
|
||||
|
||||
## dates — fixed epoch, explicit zone
|
||||
|
||||
{{ dateInZone "2006-01-02T15:04:05" 0 "UTC" }}
|
||||
= 1970-01-01T00:00:00
|
||||
{{ date "2006-01-02T15:04:05" 0 }}
|
||||
= 1970-01-01T00:00:00
|
||||
{{ dateModify "1h" (toDate "2006-01-02T15:04:05Z07:00" "2020-01-01T00:00:00Z") }}
|
||||
= 2020-01-01 01:00:00 +0000 UTC
|
||||
{{ date_modify "1h" (toDate "2006-01-02T15:04:05Z07:00" "2020-01-01T00:00:00Z") }}
|
||||
= 2020-01-01 01:00:00 +0000 UTC
|
||||
{{ toDate "2006-01-02" "2020-01-01" }}
|
||||
= 2020-01-01 00:00:00 +0000 UTC
|
||||
{{ unixEpoch (toDate "2006-01-02" "2020-01-01") }}
|
||||
= 1577836800
|
||||
{{ duration 90 }}
|
||||
= 0s
|
||||
{{ durationRound "1h35m30s" }}
|
||||
= 1h
|
||||
{{ htmlDate 0 }}
|
||||
= 1970-01-01
|
||||
|
||||
## urls
|
||||
|
||||
{{ urlParse "http://example.com/a?b=c" | toJson }}
|
||||
= {"fragment":"","host":"example.com","hostname":"example.com","opaque":"","path":"/a","query":"b=c","scheme":"http","userinfo":""}
|
||||
{{ urlJoin (dict "scheme" "http" "host" "example.com" "path" "/a") }}
|
||||
= http://example.com/a
|
||||
|
||||
## task's own functions
|
||||
|
||||
{{ numCPU | kindOf }}
|
||||
= int
|
||||
{{ catLines "a\nb" }}
|
||||
= a b
|
||||
{{ splitLines "a\nb" | toJson }}
|
||||
= ["a","b"]
|
||||
{{ toSlash "a/b" }}
|
||||
= a/b
|
||||
{{ fromSlash "a/b" | kindOf }}
|
||||
= string
|
||||
{{ ToSlash "a/b" }}
|
||||
= a/b
|
||||
{{ shellQuote "a b" }}
|
||||
= 'a b'
|
||||
{{ q "a b" }}
|
||||
= 'a b'
|
||||
{{ splitArgs "a b c" | toJson }}
|
||||
= ["a","b","c"]
|
||||
{{ IsSH }}
|
||||
= true
|
||||
{{ joinUrl "http://localhost" "a" "b" }}
|
||||
= http://localhost/a/b
|
||||
{{ mustToYaml (dict "a" 1) }}
|
||||
= a: 1\n
|
||||
{{ randIntN 1 }}
|
||||
= 0
|
||||
|
||||
194
internal/templater/testdata/func_names.golden
vendored
Normal file
194
internal/templater/testdata/func_names.golden
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
ARCH
|
||||
ExeExt
|
||||
FromSlash
|
||||
IsSH
|
||||
OS
|
||||
ToSlash
|
||||
absPath
|
||||
add
|
||||
add1
|
||||
adler32sum
|
||||
ago
|
||||
all
|
||||
any
|
||||
append
|
||||
atoi
|
||||
b32dec
|
||||
b32enc
|
||||
b64dec
|
||||
b64enc
|
||||
base
|
||||
biggest
|
||||
cat
|
||||
catLines
|
||||
ceil
|
||||
chunk
|
||||
clean
|
||||
coalesce
|
||||
compact
|
||||
concat
|
||||
contains
|
||||
date
|
||||
dateInZone
|
||||
dateModify
|
||||
date_in_zone
|
||||
date_modify
|
||||
deepEqual
|
||||
default
|
||||
dict
|
||||
dig
|
||||
dir
|
||||
div
|
||||
duration
|
||||
durationRound
|
||||
empty
|
||||
env
|
||||
exeExt
|
||||
expandenv
|
||||
ext
|
||||
fail
|
||||
first
|
||||
float64
|
||||
floor
|
||||
fromJson
|
||||
fromSlash
|
||||
fromYaml
|
||||
get
|
||||
getHostByName
|
||||
has
|
||||
hasKey
|
||||
hasPrefix
|
||||
hasSuffix
|
||||
hello
|
||||
htmlDate
|
||||
htmlDateInZone
|
||||
indent
|
||||
initial
|
||||
int
|
||||
int64
|
||||
isAbs
|
||||
join
|
||||
joinEnv
|
||||
joinPath
|
||||
joinUrl
|
||||
keys
|
||||
kindIs
|
||||
kindOf
|
||||
last
|
||||
list
|
||||
lower
|
||||
max
|
||||
maxf
|
||||
merge
|
||||
min
|
||||
minf
|
||||
mod
|
||||
mul
|
||||
mustAppend
|
||||
mustChunk
|
||||
mustCompact
|
||||
mustDateModify
|
||||
mustFirst
|
||||
mustFromJson
|
||||
mustFromYaml
|
||||
mustHas
|
||||
mustInitial
|
||||
mustLast
|
||||
mustPrepend
|
||||
mustPush
|
||||
mustRegexFind
|
||||
mustRegexFindAll
|
||||
mustRegexMatch
|
||||
mustRegexReplaceAll
|
||||
mustRegexReplaceAllLiteral
|
||||
mustRegexSplit
|
||||
mustRest
|
||||
mustReverse
|
||||
mustSlice
|
||||
mustToDate
|
||||
mustToJson
|
||||
mustToPrettyJson
|
||||
mustToRawJson
|
||||
mustToYaml
|
||||
mustUniq
|
||||
mustWithout
|
||||
must_date_modify
|
||||
nindent
|
||||
now
|
||||
numCPU
|
||||
omit
|
||||
osBase
|
||||
osClean
|
||||
osDir
|
||||
osExt
|
||||
osIsAbs
|
||||
pick
|
||||
pluck
|
||||
plural
|
||||
prepend
|
||||
push
|
||||
q
|
||||
quote
|
||||
randInt
|
||||
randIntN
|
||||
regexFind
|
||||
regexFindAll
|
||||
regexMatch
|
||||
regexQuoteMeta
|
||||
regexReplaceAll
|
||||
regexReplaceAllLiteral
|
||||
regexSplit
|
||||
relPath
|
||||
repeat
|
||||
replace
|
||||
rest
|
||||
reverse
|
||||
round
|
||||
seq
|
||||
set
|
||||
sha1sum
|
||||
sha256sum
|
||||
shellQuote
|
||||
slice
|
||||
sortAlpha
|
||||
spew
|
||||
split
|
||||
splitArgs
|
||||
splitLines
|
||||
splitList
|
||||
splitn
|
||||
squote
|
||||
sub
|
||||
substr
|
||||
ternary
|
||||
title
|
||||
toDate
|
||||
toDecimal
|
||||
toJson
|
||||
toPrettyJson
|
||||
toRawJson
|
||||
toSlash
|
||||
toString
|
||||
toStrings
|
||||
toYaml
|
||||
trim
|
||||
trimAll
|
||||
trimPrefix
|
||||
trimSuffix
|
||||
trimall
|
||||
trunc
|
||||
tuple
|
||||
typeIs
|
||||
typeIsLike
|
||||
typeOf
|
||||
uniq
|
||||
unixEpoch
|
||||
unset
|
||||
until
|
||||
untilStep
|
||||
upper
|
||||
urlJoin
|
||||
urlParse
|
||||
uuid
|
||||
values
|
||||
without
|
||||
Reference in New Issue
Block a user