github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/plugins_test.go (about)

     1  package gomplate
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  	"text/template"
    11  	"time"
    12  
    13  	"github.com/hairyhenderson/gomplate/v4/internal/config"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestBindPlugins(t *testing.T) {
    19  	ctx := context.Background()
    20  	fm := template.FuncMap{}
    21  	cfg := &config.Config{
    22  		Plugins: map[string]config.PluginConfig{},
    23  	}
    24  	err := bindPlugins(ctx, cfg, fm)
    25  	require.NoError(t, err)
    26  	assert.EqualValues(t, template.FuncMap{}, fm)
    27  
    28  	cfg.Plugins = map[string]config.PluginConfig{"foo": {Cmd: "bar"}}
    29  	err = bindPlugins(ctx, cfg, fm)
    30  	require.NoError(t, err)
    31  	assert.Contains(t, fm, "foo")
    32  
    33  	err = bindPlugins(ctx, cfg, fm)
    34  	assert.ErrorContains(t, err, "already bound")
    35  }
    36  
    37  func TestBuildCommand(t *testing.T) {
    38  	ctx := context.Background()
    39  	data := []struct {
    40  		name, path string
    41  		args       []string
    42  		expected   []string
    43  	}{
    44  		{"foo", "foo", nil, []string{"foo"}},
    45  		{"foo", "foo", []string{"bar"}, []string{"foo", "bar"}},
    46  		{"foo", "foo.bat", nil, []string{"cmd.exe", "/c", "foo.bat"}},
    47  		{"foo", "foo.cmd", []string{"bar"}, []string{"cmd.exe", "/c", "foo.cmd", "bar"}},
    48  		{"foo", "foo.ps1", []string{"bar", "baz"}, []string{"pwsh", "-File", "foo.ps1", "bar", "baz"}},
    49  	}
    50  	for _, d := range data {
    51  		p := &plugin{
    52  			ctx:  ctx,
    53  			path: d.path,
    54  		}
    55  		name, args := p.buildCommand(d.args)
    56  		actual := append([]string{name}, args...)
    57  		assert.EqualValues(t, d.expected, actual)
    58  	}
    59  }
    60  
    61  func TestRun(t *testing.T) {
    62  	ctx, cancel := context.WithCancel(context.Background())
    63  	defer cancel()
    64  
    65  	stderr := &bytes.Buffer{}
    66  	p := &plugin{
    67  		ctx:     ctx,
    68  		timeout: 500 * time.Millisecond,
    69  		stderr:  stderr,
    70  		path:    "echo",
    71  	}
    72  	out, err := p.run("foo")
    73  	require.NoError(t, err)
    74  	assert.Equal(t, "", stderr.String())
    75  	assert.Equal(t, "foo", strings.TrimSpace(out.(string)))
    76  
    77  	p = &plugin{
    78  		ctx:     ctx,
    79  		timeout: 500 * time.Millisecond,
    80  		stderr:  stderr,
    81  		path:    "echo",
    82  		args:    []string{"foo", "bar"},
    83  	}
    84  	out, err = p.run()
    85  	require.NoError(t, err)
    86  	assert.Equal(t, "", stderr.String())
    87  	assert.Equal(t, "foo bar", strings.TrimSpace(out.(string)))
    88  
    89  	p = &plugin{
    90  		ctx:     ctx,
    91  		timeout: 500 * time.Millisecond,
    92  		stderr:  stderr,
    93  		path:    "echo",
    94  		args:    []string{"foo", "bar"},
    95  	}
    96  	out, err = p.run("baz", "qux")
    97  	require.NoError(t, err)
    98  	assert.Equal(t, "", stderr.String())
    99  	assert.Equal(t, "foo bar baz qux", strings.TrimSpace(out.(string)))
   100  }
   101  
   102  func ExamplePluginFunc() {
   103  	ctx := context.Background()
   104  
   105  	// PluginFunc creates a template function that runs an arbitrary command.
   106  	f := PluginFunc(ctx, "echo", PluginOpts{})
   107  
   108  	// The function can be used in a template, but here we'll just run it
   109  	// directly. This is equivalent to running 'echo foo bar'
   110  	out, err := f("foo", "bar")
   111  	if err != nil {
   112  		panic(err)
   113  	}
   114  	fmt.Println(out)
   115  
   116  	// Output:
   117  	// foo bar
   118  }
   119  
   120  func ExamplePluginFunc_with_template() {
   121  	ctx := context.Background()
   122  
   123  	f := PluginFunc(ctx, "echo", PluginOpts{})
   124  
   125  	// PluginFunc is intended for use with gomplate, but can be used in any
   126  	// text/template by adding it to the FuncMap.
   127  	tmpl := template.New("new").Funcs(template.FuncMap{"echo": f})
   128  
   129  	tmpl, err := tmpl.Parse(`{{ echo "baz" "qux" }}`)
   130  	if err != nil {
   131  		panic(err)
   132  	}
   133  
   134  	err = tmpl.Execute(os.Stdout, nil)
   135  	if err != nil {
   136  		panic(err)
   137  	}
   138  
   139  	// Output:
   140  	// baz qux
   141  }