github.com/windmilleng/wat@v0.0.2-0.20180626175338-9349b638e250/cli/wat/plugins_test.go (about)

     1  package wat
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"reflect"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  type pluginAB struct{}
    15  
    16  func (pluginAB) name() string { return "pluginAB" }
    17  func (pluginAB) run(ctx context.Context, root string) ([]WatCommand, error) {
    18  	return []WatCommand{cmdA, cmdB}, nil
    19  }
    20  
    21  type pluginC struct{}
    22  
    23  func (pluginC) name() string { return "pluginC" }
    24  func (pluginC) run(ctx context.Context, root string) ([]WatCommand, error) {
    25  	return []WatCommand{cmdC}, nil
    26  }
    27  
    28  type pluginErr struct{}
    29  
    30  func (pluginErr) name() string { return "pluginErr" }
    31  func (pluginErr) run(ctx context.Context, root string) ([]WatCommand, error) {
    32  	return []WatCommand{}, errors.New("Oh noes!")
    33  }
    34  
    35  func TestBuiltinGoList(t *testing.T) {
    36  	f := newWatFixture(t)
    37  	defer f.tearDown()
    38  
    39  	f.write("src/github.com/fake/repo/repo.go", `
    40  package repo
    41  
    42  func One() { return 1 }
    43  `)
    44  	f.write("src/github.com/fake/repo/repo_test.go", `
    45  package repo
    46  
    47  import "testing"
    48  
    49  func TestOne(t *testing.T) {}
    50  `)
    51  
    52  	os.Setenv("GOPATH", f.root.Path())
    53  
    54  	cmds, err := PluginGo{}.run(context.Background(), f.root.Path())
    55  	if err != nil {
    56  		f.t.Fatalf("populateAt: %v", err)
    57  	}
    58  
    59  	if len(cmds) != 1 {
    60  		f.t.Fatalf("Expected 1 command, got %d", len(cmds))
    61  	}
    62  
    63  	expected := WatCommand{
    64  		FilePattern: "src/github.com/fake/repo/*",
    65  		Command:     "go test github.com/fake/repo",
    66  	}
    67  	if cmds[0] != expected {
    68  		f.t.Fatalf("Expected %+v. Actual: %+v", expected, cmds[0])
    69  	}
    70  }
    71  
    72  func TestRunBuiltinPlugins(t *testing.T) {
    73  	f := newWatFixture(t)
    74  	defer f.tearDown()
    75  	ws := f.watInit()
    76  
    77  	actual := runPlugins(context.Background(), ws,
    78  		[]plugin{pluginAB{}, pluginErr{}, pluginC{}})
    79  
    80  	// NOTE: we expect to ignore the err thrown by pluginErr and continue running the rest
    81  	expected := []WatCommand{cmdA, cmdB, cmdC}
    82  
    83  	if !reflect.DeepEqual(actual, expected) {
    84  		f.t.Fatalf("Expected command list %+v. Actual: %+v", expected, actual)
    85  	}
    86  }
    87  
    88  func TestGetUserPlugins(t *testing.T) {
    89  	f := newWatFixture(t)
    90  	defer f.tearDown()
    91  	ws := f.watInit()
    92  	f.write(filepath.Join(kWatDirName, fnameUserPlugins), "foo\nbar\nbaz")
    93  
    94  	actual, err := getUserPlugins(ws)
    95  	if err != nil {
    96  		f.t.Fatal("getUserPlugins:", err)
    97  	}
    98  
    99  	expected := []plugin{
   100  		userPlugin{cmd: "foo"},
   101  		userPlugin{cmd: "bar"},
   102  		userPlugin{cmd: "baz"},
   103  	}
   104  	if !reflect.DeepEqual(actual, expected) {
   105  		f.t.Fatalf("Expected to retrieve user plugins %+v, got %+v", expected, actual)
   106  	}
   107  }
   108  
   109  func TestGetUserPluginsNoFile(t *testing.T) {
   110  	f := newWatFixture(t)
   111  	defer f.tearDown()
   112  	ws := f.watInit()
   113  
   114  	actual, err := getUserPlugins(ws)
   115  	if err != nil {
   116  		f.t.Fatal("getUserPlugins:", err)
   117  	}
   118  
   119  	if len(actual) != 0 {
   120  		f.t.Fatalf("Expected to retrieve 0 user plugins, instead got %d: %+v", len(actual), actual)
   121  	}
   122  }
   123  
   124  func TestRunUserPlugins(t *testing.T) {
   125  	f := newWatFixture(t)
   126  	defer f.tearDown()
   127  	ws := f.watInit()
   128  
   129  	// Instead of paths to executables, these "plugins" just echo results straight to stdout.
   130  	f.write(filepath.Join(kWatDirName, fnameUserPlugins),
   131  		fmt.Sprintf(`echo '%s'
   132  echo 'not valid json'
   133  echo '%s'`, MustJson([]WatCommand{cmdA}), MustJson([]WatCommand{cmdB, cmdC})))
   134  
   135  	actual, err := RunUserPlugins(context.Background(), ws)
   136  	if err != nil {
   137  		f.t.Fatal("RunUserPlugins:", err)
   138  	}
   139  
   140  	// NOTE: we expect to ignore the err from invalid json and continue running the rest
   141  	expected := []WatCommand{cmdA, cmdB, cmdC}
   142  	if !reflect.DeepEqual(actual, expected) {
   143  		f.t.Fatalf("Expected to retrieve user plugins %+v, got %+v", expected, actual)
   144  	}
   145  }
   146  
   147  func TestRunUserPluginReturnsErr(t *testing.T) {
   148  	f := newWatFixture(t)
   149  	defer f.tearDown()
   150  
   151  	plugin := userPlugin{cmd: "not-a-valid-command"}
   152  
   153  	_, err := plugin.run(context.Background(), f.root.Path())
   154  	if err == nil {
   155  		f.t.Fatal("Expected error b/c of bad command, but none returned")
   156  	}
   157  }
   158  
   159  func TestRunUserPluginReturnsTimeoutErr(t *testing.T) {
   160  	f := newWatFixture(t)
   161  	defer f.tearDown()
   162  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   163  	defer cancel()
   164  
   165  	plugin := userPlugin{cmd: "sleep 2"}
   166  
   167  	_, err := plugin.run(ctx, f.root.Path())
   168  	if err == nil {
   169  		f.t.Fatal("Expected error b/c of timeout, but none returned")
   170  	}
   171  }