github.com/aca02djr/gb@v0.4.1/context_test.go (about)

     1  package gb
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"reflect"
     7  	"runtime"
     8  	"runtime/debug"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/constabulary/gb/importer"
    13  )
    14  
    15  func testImportCycle(pkg string, t *testing.T) {
    16  	ctx := testContext(t)
    17  
    18  	debug.SetMaxStack(1 << 18)
    19  
    20  	_, err := ctx.ResolvePackage(pkg)
    21  	if strings.Index(err.Error(), "cycle detected") == -1 {
    22  		t.Errorf("ctx.ResolvePackage returned wrong error. Expected cycle detection, got: %v", err)
    23  	}
    24  
    25  	if err == nil {
    26  		t.Errorf("ctx.ResolvePackage should have returned an error for cycle, returned nil")
    27  	}
    28  }
    29  
    30  func TestOneElementCycleDetection(t *testing.T) {
    31  	testImportCycle("cycle0", t)
    32  }
    33  
    34  func TestSimpleCycleDetection(t *testing.T) {
    35  	testImportCycle("cycle1/a", t)
    36  }
    37  
    38  func TestLongCycleDetection(t *testing.T) {
    39  	testImportCycle("cycle2/a", t)
    40  }
    41  
    42  func TestContextCtxString(t *testing.T) {
    43  	opts := func(o ...func(*Context) error) []func(*Context) error { return o }
    44  	join := func(s ...string) string { return strings.Join(s, "-") }
    45  	tests := []struct {
    46  		opts []func(*Context) error
    47  		want string
    48  	}{
    49  		{nil, join(runtime.GOOS, runtime.GOARCH)},
    50  		{opts(GOOS("windows")), join("windows", runtime.GOARCH)},
    51  		{opts(GOARCH("arm64")), join(runtime.GOOS, "arm64")},
    52  		{opts(GOARCH("arm64"), GOOS("plan9")), join("plan9", "arm64")},
    53  		{opts(Tags()), join(runtime.GOOS, runtime.GOARCH)},
    54  		{opts(Tags("sphinx", "leon")), join(runtime.GOOS, runtime.GOARCH, "leon", "sphinx")},
    55  		{opts(Tags("sphinx", "leon"), GOARCH("ppc64le")), join(runtime.GOOS, "ppc64le", "leon", "sphinx")},
    56  	}
    57  
    58  	proj := testProject(t)
    59  	for _, tt := range tests {
    60  		ctx, err := proj.NewContext(tt.opts...)
    61  		if err != nil {
    62  			t.Fatal(err)
    63  		}
    64  		defer ctx.Destroy()
    65  		got := ctx.ctxString()
    66  		if got != tt.want {
    67  			t.Errorf("NewContext(%q).ctxString(): got %v, want %v", tt.opts, got, tt.want)
    68  		}
    69  	}
    70  }
    71  
    72  func TestContextOptions(t *testing.T) {
    73  	matches := func(want Context) func(t *testing.T, got *Context) {
    74  		return func(t *testing.T, got *Context) {
    75  			if !reflect.DeepEqual(got, &want) {
    76  				t.Errorf("got %#v, want %#v", got, &want)
    77  			}
    78  		}
    79  	}
    80  
    81  	tests := []struct {
    82  		ctx    Context
    83  		fn     func(*Context) error
    84  		err    error
    85  		expect func(*testing.T, *Context)
    86  	}{{
    87  		// assert that an zero context is not altered by the test rig.
    88  		fn:     func(*Context) error { return nil },
    89  		expect: matches(Context{}),
    90  	}, {
    91  		// test blank GOOS is an error
    92  		fn:  GOOS(""),
    93  		err: fmt.Errorf("GOOS cannot be blank"),
    94  	}, {
    95  		// test blank GOARCH is an error
    96  		fn:  GOARCH(""),
    97  		err: fmt.Errorf("GOARCH cannot be blank"),
    98  	}, {
    99  		ctx: Context{
   100  			gotargetos:   "bar",
   101  			gotargetarch: "baz",
   102  		},
   103  		fn: GOOS("foo"),
   104  		expect: matches(Context{
   105  			gotargetos:   "foo",
   106  			gotargetarch: "baz",
   107  		}),
   108  	}, {
   109  		ctx: Context{
   110  			gotargetos:   "bar",
   111  			gotargetarch: "baz",
   112  		},
   113  		fn: GOARCH("foo"),
   114  		expect: matches(Context{
   115  			gotargetos:   "bar",
   116  			gotargetarch: "foo",
   117  		}),
   118  	}, {
   119  		fn:     Tags(),
   120  		expect: matches(Context{}),
   121  	}, {
   122  		fn:     Tags("foo"),
   123  		expect: matches(Context{buildtags: []string{"foo"}}),
   124  	}, {
   125  		ctx:    Context{buildtags: []string{"foo"}},
   126  		fn:     Tags("bar"),
   127  		expect: matches(Context{buildtags: []string{"foo", "bar"}}),
   128  	}, {
   129  		fn:     Gcflags("foo"),
   130  		expect: matches(Context{gcflags: []string{"foo"}}),
   131  	}, {
   132  		ctx:    Context{gcflags: []string{"foo"}},
   133  		fn:     Gcflags("bar"),
   134  		expect: matches(Context{gcflags: []string{"foo", "bar"}}),
   135  	}, {
   136  		fn:     Ldflags("foo"),
   137  		expect: matches(Context{ldflags: []string{"foo"}}),
   138  	}, {
   139  		ctx:    Context{ldflags: []string{"foo"}},
   140  		fn:     Ldflags("bar"),
   141  		expect: matches(Context{ldflags: []string{"foo", "bar"}}),
   142  	}, {
   143  		fn: WithRace,
   144  		expect: matches(Context{
   145  			buildtags: []string{"race"},
   146  			race:      true,
   147  			gcflags:   []string{"-race"},
   148  			ldflags:   []string{"-race"},
   149  		}),
   150  	}, {
   151  		ctx: Context{buildtags: []string{"zzz"}},
   152  		fn:  WithRace,
   153  		expect: matches(Context{
   154  			buildtags: []string{"zzz", "race"},
   155  			race:      true,
   156  			gcflags:   []string{"-race"},
   157  			ldflags:   []string{"-race"},
   158  		}),
   159  	}}
   160  
   161  	for i, tt := range tests {
   162  		ctx := tt.ctx
   163  		err := tt.fn(&ctx)
   164  		switch {
   165  		case !reflect.DeepEqual(err, tt.err):
   166  			t.Errorf("test %d: expected err: %v, got %v", i+1, tt.err, err)
   167  		case err == nil:
   168  			tt.expect(t, &ctx)
   169  		}
   170  	}
   171  }
   172  
   173  func TestContextLoadPackage(t *testing.T) {
   174  	tests := []struct {
   175  		opts []func(*Context) error
   176  		path string
   177  	}{
   178  		{path: "errors"},
   179  		{path: "net/http"}, // triggers vendor logic on go 1.6+
   180  	}
   181  
   182  	proj := testProject(t)
   183  	for _, tt := range tests {
   184  		ctx, err := proj.NewContext(tt.opts...)
   185  		if err != nil {
   186  			t.Fatal(err)
   187  		}
   188  		defer ctx.Destroy()
   189  		_, err = ctx.loadPackage(nil, tt.path)
   190  		if err != nil {
   191  			t.Errorf("loadPackage(%q): %v", tt.path, err)
   192  		}
   193  	}
   194  }
   195  
   196  func TestCgoEnabled(t *testing.T) {
   197  	tests := []struct {
   198  		gohostos, gohostarch     string
   199  		gotargetos, gotargetarch string
   200  		want                     bool
   201  	}{{
   202  		"linux", "amd64", "linux", "amd64", true,
   203  	}, {
   204  		"linux", "amd64", "linux", "386", false,
   205  	}}
   206  
   207  	for _, tt := range tests {
   208  		got := cgoEnabled(tt.gohostos, tt.gohostarch, tt.gotargetos, tt.gotargetarch)
   209  		if got != tt.want {
   210  			t.Errorf("cgoEnabled(%q, %q, %q, %q): got %v, want %v", tt.gohostos, tt.gohostarch, tt.gotargetos, tt.gotargetarch, got, tt.want)
   211  		}
   212  	}
   213  }
   214  
   215  func TestContextImportPackage(t *testing.T) {
   216  	proj := testProject(t)
   217  	tests := []struct {
   218  		path string
   219  		err  error
   220  	}{{
   221  		path: "a",
   222  	}, {
   223  		path: "cgomain",
   224  	}, {
   225  		path: "net/http", // loaded from GOROOT
   226  	}, {
   227  		path: "cmd",
   228  		err:  &importer.NoGoError{Dir: filepath.Join(proj.Projectdir(), "src", "cmd")},
   229  	}}
   230  
   231  	for _, tt := range tests {
   232  		ctx, err := proj.NewContext()
   233  		if err != nil {
   234  			t.Fatal(err)
   235  		}
   236  		_, err = ctx.importPackage(tt.path)
   237  		if !reflect.DeepEqual(err, tt.err) {
   238  			t.Errorf("importPackage(%q): got %v, want %v", tt.path, err, tt.err)
   239  		}
   240  	}
   241  }
   242  
   243  func TestContextMatchPackages(t *testing.T) {
   244  	tests := []struct {
   245  		pattern string
   246  		want    []string
   247  	}{{
   248  		pattern: "all",
   249  		want:    []string{"a", "aprime", "b", "c", "cgomain", "cgoonlynotest", "cgotest", "cmd/f", "cppmain", "cycle0", "cycle1/a", "cycle1/b", "cycle2/a", "cycle2/b", "cycle2/c", "cycle2/d", "d.v1", "e", "external_only_test", "extest", "extestonly", "f", "g", "h", "ldflags", "localimport", "main", "mainnoruntime", "nested/a", "nested/b", "notestfiles", "tags1", "testflags", "testonly", "x", "y"},
   250  	}, {
   251  		pattern: "...",
   252  		want:    []string{"a", "aprime", "b", "c", "cgomain", "cgoonlynotest", "cgotest", "cmd/f", "cppmain", "cycle0", "cycle1/a", "cycle1/b", "cycle2/a", "cycle2/b", "cycle2/c", "cycle2/d", "d.v1", "e", "external_only_test", "extest", "extestonly", "f", "g", "h", "ldflags", "localimport", "main", "mainnoruntime", "nested/a", "nested/b", "notestfiles", "tags1", "testflags", "testonly", "x", "y"},
   253  	}, {
   254  		pattern: "cmd/...",
   255  		want:    []string{"cmd/f"},
   256  	}, {
   257  		pattern: ".../f",
   258  		want:    []string{"cmd/f"},
   259  	}, {
   260  		pattern: "net/http",
   261  		want:    nil, // should match nothing
   262  	}}
   263  
   264  	for _, tt := range tests {
   265  		ctx := testContext(t)
   266  		got, err := matchPackages(ctx, tt.pattern)
   267  		if err != nil {
   268  			t.Errorf("matchPackages(..., %q): %v", err)
   269  			continue
   270  		}
   271  		if !reflect.DeepEqual(got, tt.want) {
   272  			t.Errorf("matchPackages(..., %q): got %#v, want %#v", tt.pattern, got, tt.want)
   273  		}
   274  	}
   275  }