package launch_test import ( "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/sclevine/spec" "github.com/sclevine/spec/report" "github.com/buildpacks/lifecycle/api" "github.com/buildpacks/lifecycle/launch" h "github.com/buildpacks/lifecycle/testhelpers" ) func TestProcess(t *testing.T) { spec.Run(t, "Process", testProcess, spec.Report(report.Terminal{})) } // PlatformAPI should be ignored because it is not always set in these tests var processCmpOpts = []cmp.Option{ cmpopts.IgnoreFields(launch.Process{}, "PlatformAPI"), cmpopts.IgnoreFields(launch.RawCommand{}, "PlatformAPI"), } func testProcess(t *testing.T, when spec.G, it spec.S) { var ( launcher *launch.Launcher ) it.Before(func() { launcher = &launch.Launcher{ Buildpacks: []launch.Buildpack{ {ID: "some-buildpack", API: "0.8"}, {ID: "some-newer-buildpack", API: "0.9"}, }, Processes: []launch.Process{ { Type: "some-type", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"some-arg1", "some-arg2"}, BuildpackID: "some-buildpack", }, { Type: "other-type", Command: launch.NewRawCommand([]string{"other-command"}), Args: []string{"other-arg1", "other-arg2"}, BuildpackID: "some-buildpack", }, { Type: "type-with-always-and-overridable-args", Command: launch.NewRawCommand([]string{"some-command", "always-arg"}), Args: []string{"overridable-arg"}, BuildpackID: "some-newer-buildpack", }, { Type: "type-with-overridable-arg", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"overridable-arg"}, BuildpackID: "some-newer-buildpack", }, }, PlatformAPI: api.Platform.Latest(), } }) when("ProcessFor", func() { when("DefaultProcessType", func() { when("is unset", func() { when("cmd starts with --", func() { it("creates a new direct process from cmd", func() { proc, err := launcher.ProcessFor([]string{"--", "user-command", "user-arg1", "user-arg2"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Command: launch.NewRawCommand([]string{"user-command"}), Args: []string{"user-arg1", "user-arg2"}, Direct: true, }, processCmpOpts...) }) }) when("cmd does not start with --", func() { it("creates a new shell process from cmd", func() { proc, err := launcher.ProcessFor([]string{"user-command", "user-arg1", "user-arg2"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Command: launch.NewRawCommand([]string{"user-command"}), Args: []string{"user-arg1", "user-arg2"}, }, processCmpOpts...) }) }) when("cmd is empty", func() { it("errors", func() { _, err := launcher.ProcessFor([]string{}) h.AssertNotNil(t, err) }) }) }) when("exists", func() { when("process' 'command' has args", func() { it.Before(func() { launcher.DefaultProcessType = "type-with-always-and-overridable-args" }) it("provides command args and replaces process args with cmd", func() { proc, err := launcher.ProcessFor([]string{"user-arg1", "user-arg2"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Type: "type-with-always-and-overridable-args", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"always-arg", "user-arg1", "user-arg2"}, BuildpackID: "some-newer-buildpack", }, processCmpOpts...) }) when("cmd is empty", func() { it("provides command args and process args", func() { proc, err := launcher.ProcessFor([]string{}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Type: "type-with-always-and-overridable-args", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"always-arg", "overridable-arg"}, BuildpackID: "some-newer-buildpack", }, processCmpOpts...) }) }) }) when("process' 'command' does not have args", func() { when("newer buildpack with API >= 0.9", func() { it.Before(func() { launcher.DefaultProcessType = "type-with-overridable-arg" }) it("replaces process args with cmd", func() { proc, err := launcher.ProcessFor([]string{"user-arg1", "user-arg1"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Type: "type-with-overridable-arg", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"user-arg1", "user-arg1"}, BuildpackID: "some-newer-buildpack", }, processCmpOpts...) }) when("cmd is empty", func() { it("provides process args", func() { proc, err := launcher.ProcessFor([]string{}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Type: "type-with-overridable-arg", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"overridable-arg"}, BuildpackID: "some-newer-buildpack", }, processCmpOpts...) }) }) }) when("older buildpack with API < 0.9", func() { it.Before(func() { launcher.DefaultProcessType = "some-type" }) it("appends cmd to process args", func() { proc, err := launcher.ProcessFor([]string{"user-arg1", "user-arg1"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Type: "some-type", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"some-arg1", "some-arg2", "user-arg1", "user-arg1"}, BuildpackID: "some-buildpack", }, processCmpOpts...) }) }) }) }) when("doesn't exist", func() { it.Before(func() { launcher.DefaultProcessType = "missing-type" }) it("errors", func() { _, err := launcher.ProcessFor([]string{"user-arg1", "user-arg1"}) h.AssertNotNil(t, err) }) }) }) when("Platform API < 0.10", func() { it.Before(func() { launcher.PlatformAPI = api.MustParse("0.9") }) when("DefaultProcessType", func() { when("is unset", func() { when("cmd starts with --", func() { it("creates a new direct process from cmd", func() { proc, err := launcher.ProcessFor([]string{"--", "user-command", "user-arg1", "user-arg2"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Command: launch.NewRawCommand([]string{"user-command"}), Args: []string{"user-arg1", "user-arg2"}, Direct: true, }, processCmpOpts...) }) }) when("cmd does not start with --", func() { it("creates a new shell process from cmd", func() { proc, err := launcher.ProcessFor([]string{"user-command", "user-arg1", "user-arg2"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Command: launch.NewRawCommand([]string{"user-command"}), Args: []string{"user-arg1", "user-arg2"}, }, processCmpOpts...) }) }) when("cmd is empty", func() { it("errors", func() { _, err := launcher.ProcessFor([]string{}) h.AssertNotNil(t, err) }) }) }) when("exists", func() { it.Before(func() { launcher.DefaultProcessType = "type-with-overridable-arg" }) it("appends cmd to process args", func() { proc, err := launcher.ProcessFor([]string{"user-arg1", "user-arg1"}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Type: "type-with-overridable-arg", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"overridable-arg", "user-arg1", "user-arg1"}, BuildpackID: "some-newer-buildpack", }, processCmpOpts...) }) when("cmd is empty", func() { it("provides process args", func() { proc, err := launcher.ProcessFor([]string{}) h.AssertNil(t, err) h.AssertEq(t, proc, launch.Process{ Type: "type-with-overridable-arg", Command: launch.NewRawCommand([]string{"some-command"}), Args: []string{"overridable-arg"}, BuildpackID: "some-newer-buildpack", }, processCmpOpts...) }) }) }) when("doesn't exist", func() { it.Before(func() { launcher.DefaultProcessType = "missing-type" }) it("errors", func() { _, err := launcher.ProcessFor([]string{"user-arg1", "user-arg1"}) h.AssertNotNil(t, err) }) }) }) }) }) }