code.cestus.io/tools/fabricator@v0.4.3/pkg/cmd/cmd_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"testing"
     8  
     9  	"code.cestus.io/tools/fabricator/internal/pkg/util"
    10  	"code.cestus.io/tools/fabricator/pkg/fabricator"
    11  	"code.cestus.io/tools/fabricator/pkg/helpers"
    12  )
    13  
    14  func TestFabricatorCommandHandlesPlugins(t *testing.T) {
    15  	tests := []struct {
    16  		name             string
    17  		args             []string
    18  		expectPlugin     string
    19  		expectPluginArgs []string
    20  		expectError      string
    21  	}{
    22  		{
    23  			name:             "test that a plugin executable is found based on command args",
    24  			args:             []string{"fabricator", "foo", "--bar"},
    25  			expectPlugin:     "plugin/testdata/fabricator-foo",
    26  			expectPluginArgs: []string{"--bar"},
    27  		},
    28  		{
    29  			name: "test that a plugin does not execute over an existing command by the same name",
    30  			args: []string{"fabricator", "version"},
    31  		},
    32  	}
    33  
    34  	for _, test := range tests {
    35  		t.Run(test.name, func(t *testing.T) {
    36  			ctx := context.Background()
    37  			pluginsHandler := &testPluginHandler{
    38  				pluginsDirectory: "plugin/testdata",
    39  			}
    40  			io, _, _, errOut := fabricator.NewTestIOStreams()
    41  
    42  			util.BehaviorOnFatal(func(str string, code int) {
    43  				errOut.Write([]byte(str))
    44  			})
    45  
    46  			root := NewDefaultFabricatorCommandWithArgs(ctx, pluginsHandler, test.args, io, helpers.DefaultFlagParser)
    47  
    48  			root.SetArgs(test.args[1:])
    49  			if err := root.Execute(); err != nil {
    50  				t.Fatalf("unexpected error: %v", err)
    51  			}
    52  
    53  			if pluginsHandler.err != nil && pluginsHandler.err.Error() != test.expectError {
    54  				t.Fatalf("unexpected error: expected %q to occur, but got %q", test.expectError, pluginsHandler.err)
    55  			}
    56  
    57  			if pluginsHandler.executedPlugin != test.expectPlugin {
    58  				t.Fatalf("unexpected plugin execution: expected %q, got %q", test.expectPlugin, pluginsHandler.executedPlugin)
    59  			}
    60  
    61  			if len(pluginsHandler.withArgs) != len(test.expectPluginArgs) {
    62  				t.Fatalf("unexpected plugin execution args: expected %q, got %q", test.expectPluginArgs, pluginsHandler.withArgs)
    63  			}
    64  		})
    65  	}
    66  }
    67  
    68  type testPluginHandler struct {
    69  	pluginsDirectory string
    70  
    71  	// execution results
    72  	executedPlugin string
    73  	withArgs       []string
    74  	withEnv        fabricator.Environment
    75  
    76  	err error
    77  }
    78  
    79  func (h *testPluginHandler) Lookup(ctx context.Context, filename string, paths []string) (string, bool) {
    80  	// append supported plugin prefix to the filename
    81  	filename = fmt.Sprintf("%s-%s", "fabricator", filename)
    82  
    83  	dir, err := os.Stat(h.pluginsDirectory)
    84  	if err != nil {
    85  		h.err = err
    86  		return "", false
    87  	}
    88  
    89  	if !dir.IsDir() {
    90  		h.err = fmt.Errorf("expected %q to be a directory", h.pluginsDirectory)
    91  		return "", false
    92  	}
    93  
    94  	plugins, err := os.ReadDir(h.pluginsDirectory)
    95  	if err != nil {
    96  		h.err = err
    97  		return "", false
    98  	}
    99  
   100  	for _, p := range plugins {
   101  		if p.Name() == filename {
   102  			h.err = nil
   103  			return fmt.Sprintf("%s/%s", h.pluginsDirectory, p.Name()), true
   104  		}
   105  	}
   106  
   107  	h.err = fmt.Errorf("unable to find a plugin executable %q", filename)
   108  	return "", false
   109  }
   110  
   111  func (h *testPluginHandler) Execute(ctx context.Context, executablePath string, cmdArgs []string, env fabricator.Environment) error {
   112  	h.executedPlugin = executablePath
   113  	h.withArgs = cmdArgs
   114  	h.withEnv = env
   115  	return nil
   116  }