Skip to content

Commit

Permalink
Unit Test Coverage Increase (#420)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianAtDell authored Feb 13, 2025
1 parent 29798ad commit db06878
Show file tree
Hide file tree
Showing 15 changed files with 1,426 additions and 125 deletions.
9 changes: 8 additions & 1 deletion core/core.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2019-2022 Dell Inc. or its subsidiaries. All Rights Reserved.
// Copyright © 2019-2025 Dell Inc. or its subsidiaries. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,3 +32,10 @@ var (
// this program was built.
CommitTime time.Time
)

func setValues(semver string, commit7 string, commit32 string, commitTime time.Time) {
SemVer = semver
CommitSha7 = commit7
CommitSha32 = commit32
CommitTime = commitTime
}
30 changes: 30 additions & 0 deletions core/core_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright © 2025 Dell Inc. or its subsidiaries. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package core

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestSetValues(t *testing.T) {
timestamp := time.Now()
setValues("0.0.0.0", "0123456", "abcdefghijklmnopqrstuvwxyz01234567891", timestamp)
assert.Equal(t, "0.0.0.0", SemVer)
assert.Equal(t, "0123456", CommitSha7)
assert.Equal(t, "abcdefghijklmnopqrstuvwxyz01234567891", CommitSha32)
assert.Equal(t, timestamp, CommitTime)
}
205 changes: 128 additions & 77 deletions core/semver/semver.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// Copyright © 2019-2022 Dell Inc. or its subsidiaries. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/*
Copyright © 2025 Dell Inc. or its subsidiaries. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

Expand All @@ -31,30 +32,51 @@ import (
"time"
)

var (
format string
output string
export bool
tpl *template.Template
)

func init() {
if flag.Lookup("f") == nil {
flag.StringVar(
&format,
"f",
"ver",
"The output format: env, go, json, mk, rpm, ver")
}
if flag.Lookup("o") == nil {
flag.StringVar(
&output,
"o",
"",
"The output file")
}
if flag.Lookup("x") == nil {
flag.BoolVar(
&export,
"x",
false,
"Export env vars. Used with -f env")
}
}

// must be injectable for unit testing
var gitDescribeFunc = func() ([]byte, error) {
return doExec("git", "describe", "--long", "--dirty")
}

func initFlags() {
format = flag.Lookup("f").Value.(flag.Getter).Get().(string)
output = flag.Lookup("o").Value.(flag.Getter).Get().(string)
export = flag.Lookup("x").Value.(flag.Getter).Get().(bool)
}

func main() {
var (
tpl *template.Template
format string
output string
export bool
)

flag.StringVar(
&format,
"f",
"ver",
"The output format: env, go, json, mk, rpm, ver")
flag.StringVar(
&output,
"o",
"",
"The output file")
flag.BoolVar(
&export,
"x",
false,
"Export env vars. Used with -f env")
flag.Parse()
initFlags()

if strings.EqualFold("env", format) {
format = "env"
Expand All @@ -69,13 +91,10 @@ func main() {
} else if strings.EqualFold("ver", format) {
format = "ver"
} else {
/* #nosec G304 */
format = filepath.Clean(format)
if fileExists(format) {
buf, err := os.ReadFile(format)
buf, err := ReadFile(format) // #nosec G304
if err != nil {
fmt.Fprintf(os.Stderr, "error: read tpl failed: %v\n", err)
os.Exit(1)
errorExit(fmt.Sprintf("error: read tpl failed: %v\n", err))
}
format = string(buf)
}
Expand All @@ -85,24 +104,24 @@ func main() {

var w io.Writer = os.Stdout
if len(output) > 0 {
output = filepath.Clean(output)
fout, err := os.Create(output)
fout, err := os.Create(filepath.Clean(output))
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
errorExit(fmt.Sprintf("error: %v\n", err))
}
w = fout
/* #nosec G307 */
defer fout.Close()
defer func() {
if err := fout.Close(); err != nil {
panic(err)
}
}() // #nosec G20
}

gitdesc := chkErr(doExec("git", "describe", "--tags", "--long", "--dirty"))
gitdesc := chkErr(gitDescribeFunc())
rx := regexp.MustCompile(
`^[^\d]*(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z].+?))?(?:-(\d+)-g(.+?)(?:-(dirty))?)?\s*$`)
m := rx.FindStringSubmatch(gitdesc)
if len(m) == 0 {
fmt.Fprintf(os.Stderr, "error: match git describe failed: %s\n", gitdesc)
os.Exit(1)
errorExit(fmt.Sprintf("error: match git describe failed: %s\n", gitdesc))
}

goos := os.Getenv("XGOOS")
Expand All @@ -113,7 +132,16 @@ func main() {
if goarch == "" {
goarch = runtime.GOARCH
}

// get the build number. Jenkins exposes this as an
// env variable called BUILD_NUMBER
buildNumber := os.Getenv("BUILD_NUMBER")
if buildNumber == "" {
buildNumber = m[5]
}
buildType := os.Getenv("BUILD_TYPE")
if buildType == "" {
buildType = "X"
}
ver := &semver{
GOOS: goos,
GOARCH: goarch,
Expand All @@ -123,7 +151,8 @@ func main() {
Minor: toInt(m[2]),
Patch: toInt(m[3]),
Notes: m[4],
Build: toInt(m[5]),
Type: buildType,
Build: toInt(buildNumber),
Sha7: m[6],
Sha32: chkErr(doExec("git", "log", "-n1", `--format=%H`)),
Dirty: m[7] != "",
Expand All @@ -147,8 +176,7 @@ func main() {
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
if err := enc.Encode(ver); err != nil {
fmt.Fprintf(os.Stderr, "error: encode to json failed: %v\n", err)
os.Exit(1)
errorExit(fmt.Sprintf("error: encode to json failed: %v\n", err))
}
case "mk":
for _, v := range ver.EnvVars() {
Expand All @@ -157,51 +185,54 @@ func main() {
fmt.Fprintf(w, "%s ?=", key)
if len(p) == 1 {
fmt.Fprintln(w)
continue
} else {
val := p[1]
if strings.HasPrefix(val, `"`) &&
strings.HasSuffix(val, `"`) {
val = val[1 : len(val)-1]
}
val = strings.Replace(val, "$", "$$", -1)
fmt.Fprintf(w, " %s\n", val)
}
val := p[1]
if strings.HasPrefix(val, `"`) &&
strings.HasSuffix(val, `"`) {
val = val[1 : len(val)-1]
}
val = strings.Replace(val, "$", "$$", -1)
fmt.Fprintf(w, " %s\n", val)
}
case "rpm":
fmt.Fprintln(w, ver.RPM())
case "tpl":
if err := tpl.Execute(w, ver); err != nil {
fmt.Fprintf(os.Stderr, "error: template failed: %v\n", err)
os.Exit(1)
errorExit(fmt.Sprintf("error: template failed: %v\n", err))
}
case "ver":
fmt.Fprintln(w, ver.String())
}
}

func doExec(cmd string, args ...string) ([]byte, error) {
/* #nosec G204 */
c := exec.Command(cmd, args...)
c := exec.Command(cmd, args...) // #nosec G204
c.Stderr = os.Stderr
return c.Output()
}

func errorExit(message string) {
fmt.Fprintf(os.Stderr, "%s", message)
OSExit(1)
}

func chkErr(out []byte, err error) string {
if err == nil {
return strings.TrimSpace(string(out))
}

e, ok := err.(*exec.ExitError)
e, ok := GetExitError(err)
if !ok {
os.Exit(1)
OSExit(1)
}

st, ok := e.Sys().(syscall.WaitStatus)
status, ok := GetStatusError(e)
if !ok {
os.Exit(1)
OSExit(1)
}

os.Exit(st.ExitStatus())
OSExit(status)
return ""
}

Expand All @@ -215,6 +246,7 @@ type semver struct {
Patch int `json:"patch"`
Build int `json:"build"`
Notes string `json:"notes"`
Type string `json:"type"`
Dirty bool `json:"dirty"`
Sha7 string `json:"sha7"`
Sha32 string `json:"sha32"`
Expand Down Expand Up @@ -253,8 +285,9 @@ func (v *semver) EnvVars() []string {
fmt.Sprintf("MAJOR=%d", v.Major),
fmt.Sprintf("MINOR=%d", v.Minor),
fmt.Sprintf("PATCH=%d", v.Patch),
fmt.Sprintf("BUILD=%d", v.Build),
fmt.Sprintf("BUILD=%3.3d", v.Build),
fmt.Sprintf("NOTES=\"%s\"", v.Notes),
fmt.Sprintf("TYPE=%s", v.Type),
fmt.Sprintf("DIRTY=%v", v.Dirty),
fmt.Sprintf("SHA7=%s", v.Sha7),
fmt.Sprintf("SHA32=%s", v.Sha32),
Expand Down Expand Up @@ -310,14 +343,32 @@ var goarchToUname = map[string]string{
}

func fileExists(filePath string) bool {
_, err := os.Stat(filePath)
if err == nil {
if _, err := os.Stat(filePath); !os.IsNotExist(err) {
return true
}
if os.IsNotExist(err) {
fmt.Printf("File %s doesn't exist", filePath)
} else {
fmt.Printf("Found error %v while checking stat of file %s ", err, filePath)
}
return false
}

// ReadFile is a wrapper around os.ReadFile
var ReadFile = func(file string) ([]byte, error) {
return os.ReadFile(file) // #nosec G304
}

// OSExit is a wrapper around os.Exit
var OSExit = func(code int) {
os.Exit(code)
}

// GetExitError is a wrapper around exec.ExitError
var GetExitError = func(err error) (e *exec.ExitError, ok bool) {
e, ok = err.(*exec.ExitError)
return
}

// GetStatusError is a wrapper around syscall.WaitStatus
var GetStatusError = func(exitError *exec.ExitError) (status int, ok bool) {
if e, ok := exitError.Sys().(syscall.WaitStatus); ok {
return e.ExitStatus(), true
}
return 1, false
}
Loading

0 comments on commit db06878

Please sign in to comment.