diff --git a/context.go b/context.go index 4a061cd..bef4422 100644 --- a/context.go +++ b/context.go @@ -34,6 +34,7 @@ type Context struct { Force bool // force rebuild of packages SkipInstall bool // do not cache compiled packages Verbose bool // verbose output + race bool // race detector requested pkgs map[string]*Package // map of package paths to resolved packages @@ -49,7 +50,7 @@ type Context struct { func GOOS(goos string) func(*Context) error { return func(c *Context) error { if goos == "" { - return fmt.Errorf("goos cannot be blank") + return fmt.Errorf("GOOS cannot be blank") } c.gotargetos = goos return nil @@ -60,7 +61,7 @@ func GOOS(goos string) func(*Context) error { func GOARCH(goarch string) func(*Context) error { return func(c *Context) error { if goarch == "" { - return fmt.Errorf("goarch cannot be blank") + return fmt.Errorf("GOARCH cannot be blank") } c.gotargetarch = goarch return nil @@ -70,12 +71,18 @@ func GOARCH(goarch string) func(*Context) error { // Tags configured the context to use these additional build tags func Tags(tags ...string) func(*Context) error { return func(c *Context) error { - c.buildtags = make([]string, len(tags)) - copy(c.buildtags, tags) + c.buildtags = append(c.buildtags, tags...) return nil } } +// WithRace enables the race detector and adds the tag "race" to +// the Context build tags. +func WithRace(c *Context) error { + c.race = true + return Tags("race")(c) +} + // NewContext returns a new build context from this project. // By default this context will use the gc toolchain with the // host's GOOS and GOARCH values. diff --git a/context_test.go b/context_test.go index d20eb89..a3da205 100644 --- a/context_test.go +++ b/context_test.go @@ -1,6 +1,8 @@ package gb import ( + "fmt" + "reflect" "runtime" "runtime/debug" "strings" @@ -63,3 +65,86 @@ func TestContextCtxString(t *testing.T) { } } } + +func TestContextOptions(t *testing.T) { + matches := func(want Context) func(t *testing.T, got *Context) { + return func(t *testing.T, got *Context) { + if !reflect.DeepEqual(got, &want) { + t.Errorf("got %#v, want %#v", got, &want) + } + } + } + + tests := []struct { + ctx Context + fn func(*Context) error + err error + expect func(*testing.T, *Context) + }{{ + // assert that an zero context is not altered by the test rig. + fn: func(*Context) error { return nil }, + expect: matches(Context{}), + }, { + // test blank GOOS is an error + fn: GOOS(""), + err: fmt.Errorf("GOOS cannot be blank"), + }, { + // test blank GOARCH is an error + fn: GOARCH(""), + err: fmt.Errorf("GOARCH cannot be blank"), + }, { + ctx: Context{ + gotargetos: "bar", + gotargetarch: "baz", + }, + fn: GOOS("foo"), + expect: matches(Context{ + gotargetos: "foo", + gotargetarch: "baz", + }), + }, { + ctx: Context{ + gotargetos: "bar", + gotargetarch: "baz", + }, + fn: GOARCH("foo"), + expect: matches(Context{ + gotargetos: "bar", + gotargetarch: "foo", + }), + }, { + fn: Tags(), + expect: matches(Context{}), + }, { + fn: Tags("foo"), + expect: matches(Context{buildtags: []string{"foo"}}), + }, { + ctx: Context{buildtags: []string{"foo"}}, + fn: Tags("bar"), + expect: matches(Context{buildtags: []string{"foo", "bar"}}), + }, { + fn: WithRace, + expect: matches(Context{ + buildtags: []string{"race"}, + race: true, + }), + }, { + ctx: Context{buildtags: []string{"zzz"}}, + fn: WithRace, + expect: matches(Context{ + buildtags: []string{"zzz", "race"}, + race: true, + }), + }} + + for i, tt := range tests { + ctx := tt.ctx + err := tt.fn(&ctx) + switch { + case !reflect.DeepEqual(err, tt.err): + t.Errorf("test %d: expected err: %v, got %v", i+1, tt.err, err) + case err == nil: + tt.expect(t, &ctx) + } + } +}