This repository has been archived by the owner on Apr 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prior to this commit, the cobra `build` command used package variables and instantiated a PCT-specific `build` command in the `CreateCommand()` function. Any other cobra applications wanting to use the now-generic functionality from the public `build` package would need to reimplement this command wholly themselves as it hard-codes to PCT's packaging paradigm (i.e. it references "templates", expects a `pct-config.yml`, and instantiates the private PCT `ConfigProcessor`). This commit genericizes the `build` command by: 1. Replacing the package variables with a `BuildCommand` struct, declaring a `BuildCommandI` interface, and updating the functions (`CreateCommand()`, `preExecute()`, and `execute()`) to be attached to the new `BuildCommand` struct. 2. Replacing references in the `build` command's reference doc help text and error/info messaging, updating default language to "project" and extending the `BuildCommand` struct to include defining a `ProjectType` to clarify those docs/messages (i.e. "Builds a package from the template project" for PCT where `ProjectType` is set in the struct as `template`). 3. Moving the instantiation of the struct to `main` where it defines the `ProjectType` as `template` and instantiates the `build.Builder` struct, passing in the private `PctConfigProcessor`. During testing for this change, I noticed that the unit tests for the `build` command did not mock the `build.Builder`; this was because the `CreateCommand()` function instantiates that struct inside itself. Therefore, the unit tests were _actually_ trying to build packages. This commit reworks and simplifies those tests so that they use a new mock `Builder` instead of functionally (and without documentation) running integration tests for the `build` package.
- Loading branch information
1 parent
33c4718
commit f15e17d
Showing
5 changed files
with
114 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,105 +1,84 @@ | ||
package build | ||
package build_test | ||
|
||
import ( | ||
"bytes" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func nullFunction(cmd *cobra.Command, args []string) error { | ||
return nil | ||
} | ||
"github.com/puppetlabs/pdkgo/cmd/build" | ||
"github.com/puppetlabs/pdkgo/pkg/mock" | ||
) | ||
|
||
func TestCreatebuildCommand(t *testing.T) { | ||
func TestCreateBuildCommand(t *testing.T) { | ||
wd, _ := os.Getwd() | ||
defaultSourceDir := wd | ||
defaultTargetDir := filepath.Join(wd, "pkg") | ||
|
||
tests := []struct { | ||
name string | ||
args []string | ||
returnCode int | ||
out string | ||
wantCmd *cobra.Command | ||
wantErr bool | ||
f func(cmd *cobra.Command, args []string) error | ||
expSrcDir string | ||
expTargDir string | ||
name string | ||
args []string | ||
expectedSourceDir string | ||
expectedTargetDir string | ||
expectedErrorMatch string | ||
}{ | ||
{ | ||
name: "executes without error for valid flag", | ||
args: []string{"build"}, | ||
f: nullFunction, | ||
out: "", | ||
wantErr: false, | ||
expSrcDir: defaultSourceDir, | ||
expTargDir: defaultTargetDir, | ||
name: "executes without error when no flags passed", | ||
args: []string{}, | ||
expectedSourceDir: defaultSourceDir, | ||
expectedTargetDir: defaultTargetDir, | ||
}, | ||
{ | ||
name: "executes with error for invalid flag", | ||
args: []string{"--foo"}, | ||
f: nullFunction, | ||
out: "unknown flag: --foo", | ||
wantErr: true, | ||
expSrcDir: "", | ||
expTargDir: "", | ||
name: "executes with error for invalid flag", | ||
args: []string{"--foo"}, | ||
expectedErrorMatch: "unknown flag: --foo", | ||
}, | ||
{ | ||
name: "uses sourcedir, targetdir when passed in", | ||
args: []string{"build", "--sourcedir", "/path/to/template", "--targetdir", "/path/to/output"}, | ||
f: nullFunction, | ||
out: "", | ||
wantErr: false, | ||
expSrcDir: "/path/to/template", | ||
expTargDir: "/path/to/output", | ||
name: "uses sourcedir, targetdir when passed in", | ||
args: []string{"--sourcedir", "/path/to/template", "--targetdir", "/path/to/output"}, | ||
expectedSourceDir: "/path/to/template", | ||
expectedTargetDir: "/path/to/output", | ||
}, | ||
{ | ||
name: "Sets correct defaults if sourcedir and targetdir undefined", | ||
args: []string{"build"}, | ||
f: nullFunction, | ||
out: "", | ||
wantErr: false, | ||
expSrcDir: defaultSourceDir, | ||
expTargDir: defaultTargetDir, | ||
name: "Sets correct defaults if sourcedir and targetdir undefined", | ||
args: []string{}, | ||
expectedSourceDir: defaultSourceDir, | ||
expectedTargetDir: defaultTargetDir, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
cmd := CreateCommand() | ||
b := bytes.NewBufferString("") | ||
cmd.SetOut(b) | ||
cmd.SetErr(b) | ||
cmd.SetArgs(tt.args) | ||
cmd.RunE = tt.f | ||
|
||
err := cmd.Execute() | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("executeTestUnit() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
cmd := build.BuildCommand{ | ||
ProjectType: "template", | ||
Builder: &mock.Builder{ | ||
ProjectName: "my-project", | ||
ExpectedSourceDir: tt.expectedSourceDir, | ||
ExpectedTargetDir: tt.expectedTargetDir, | ||
}, | ||
} | ||
buildCmd := cmd.CreateCommand() | ||
|
||
out, err := ioutil.ReadAll(b) | ||
if err != nil { | ||
t.Errorf("Failed to read stdout: %v", err) | ||
return | ||
} | ||
b := bytes.NewBufferString("") | ||
buildCmd.SetOut(b) | ||
buildCmd.SetErr(b) | ||
|
||
assert.Equal(t, tt.expSrcDir, sourceDir) | ||
assert.Equal(t, tt.expTargDir, targetDir) | ||
buildCmd.SetArgs(tt.args) | ||
err := buildCmd.Execute() | ||
|
||
output := string(out) | ||
r := regexp.MustCompile(tt.out) | ||
if !r.MatchString(output) { | ||
t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output) | ||
return | ||
if err != nil { | ||
if tt.expectedErrorMatch == "" { | ||
t.Errorf("Unexpected error when none wanted: %v", err) | ||
return | ||
} else { | ||
out, _ := ioutil.ReadAll(b) | ||
assert.Regexp(t, tt.expectedErrorMatch, string(out)) | ||
} | ||
} else if tt.expectedErrorMatch != "" { | ||
t.Errorf("Expected error '%s'but none raised", err) | ||
} | ||
}) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package mock | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
type Builder struct { | ||
ProjectName string | ||
ExpectedSourceDir string | ||
ExpectedTargetDir string | ||
} | ||
|
||
func (b *Builder) Build(sourceDir, targetDir string) (gzipArchiveFilePath string, err error) { | ||
// if input isn't what's expected, raise an error | ||
if sourceDir != b.ExpectedSourceDir { | ||
return "", fmt.Errorf("Expected source dir '%s' but got '%s'", b.ExpectedSourceDir, sourceDir) | ||
} | ||
if targetDir != b.ExpectedTargetDir { | ||
return "", fmt.Errorf("Expected source dir '%s' but got '%s'", b.ExpectedSourceDir, sourceDir) | ||
} | ||
// If nothing goes wrong, return the path to the packaged project | ||
return fmt.Sprintf("%s/my-project.tar.gz", targetDir), nil | ||
} |